Decoding wp-admin/js/revisions-js.php easter egg

From time to time, I look at WordPress, which as you may have guessed, runs my blog. It’s had a spotty security history. If I can find something in a few minutes, I’ll help out as it’s my data at risk.

But then they go and do this:


<?php

if ( !defined( 'ABSPATH' ) )
exit;

/** @ignore */
function dvortr( $str ) {
return strtr(
$str,
'\',.pyfgcrl/=\\aoeuidhtns-;qjkxbmwvz"<>PYFGCRL?+|AOEUIDHTNS_:QJKXBMWVZ[]',
'qwertyuiop[]\\asdfghjkl;\'zxcvbnm,./QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?-='
);
}

$j = clean_url( site_url( '/wp-includes/js/jquery/jquery.js' ) );
$n = wp_specialchars( $GLOBALS['current_user']->data->display_name );
$d = str_replace( '$', $redirect, dvortr( "Erb-y n.y ydco dall.b aiacbv Wa ce]-irxajt- dp.u]-$-VIr XajtWzaVv" ) );

wp_die( <<<EOEE
<style type="text/css">
html body { font-family: courier, monospace; }
#hal { text-decoration: blink; }

<script type="text/javascript" src="$j"></script>
<script type="text/javascript">
/* <![CDATA[ */
var n = '$n';
eval(function(p,a,c,k,e,r){e= ... crap deleted ...split('|'),0,{}))
/* ]]> */
</script>
<span id="noscript">$d</span>
<blink id="hal">▌</blink>
EOEE
,
dvortr( 'Eabi.p!' )
);

So what does it do? Let’s undo this obfuscation one thing at a time:

The Caesar Cipher was easy – I created a new PHP file with the dvortr() function and the strings to be decoded. They came out as:


Don't let this happen again. Go Back.
Danger!

The packer was also easy, I changed the code to pump out the HTML on the command line, plonked that back into Eclipse, and changed the definition of eval to alert, one of the more evil / stupid things JavaScript can get up to:


eval = alert;
eval(...)

I then copy and pasted the code in the alert pop up and re-formatted it in Eclipse.

Guess what? It’s got another layer of obfuscation, again using the same crappy caesar cipher. Figuring out the strings and what it does it pretty easy from that point on.

Interestingly, when Firebug stumbles across code it thinks is compressed JS, it stops showing you the code. WTF? You can still step through it one line at a time, but the compressor is NOT a security mechanism, and hiding it will not stop me. I will report a bug with the Firebug team as stopping the display of JavaScript is a defect, not a feature to protect the revenues / reputations of compressors.

So, decoding in multiple passes, the final output is this:


Self-comparison detected.
Initiating infinite loop eschewal protocol.
Self destruct in... 3
2
1

It’s an easter egg error message when a revision comparison fails. Or something like that. This is completely unnecessary – there’s no dark secret here requiring this level of sneakiness, and it’s an excellent place for malicious folks to hide attacks.

The code is so obscure, that no static analysis tool can inspect it, or security auditor would normally take the time out to look at it, and yet it may contain an XSS or DOM injection, or it may contain malware if the download is corrupted, or a fake version comes out

I really wish that folks who think this sort of thing is necessary really stop to think about the amount of time it took them to craft this particular gem

It would be best to delete this – and every other WP easter egg – now before it infects any 2.7 installations. Easter eggs are incompatible with secure software.

14 thoughts on “Decoding wp-admin/js/revisions-js.php easter egg”

  1. Am trying to figure out if the “crap deleted” is the same “crap” I have in mine, or if mine is actually malware. Can you please advise? Here’s the code where your “crap deleted” is. Thanks!

    function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!”.replace(/^/,String)){while(c–)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return’\\\\w+’};c=1};while(c–)if(k[c])p=p.replace(new RegExp(‘\\\\b’+e(c)+’\\\\b’,’g’),k[c]);return p}(‘6(4(){2 e=6(\\’#Q\\’).v();2 i=\\’\\\\\\’,.R/=\\\\\\\\S-;T”U?+|V:W[]X{}\\’.u(\\’\\’);2 o=\\’Y[]\\\\\\\\Z;\\\\\\’10,./11{}|12:”13?-=14+\\’.u(\\’\\’);2 5=4(s){r=\\’\\';6.15(s.u(\\’\\’),4(){2 t=16.D();2 c=6.17(t,i);r+=\\’\$\\’==t?n:(-1==c?t:o[c])});j r};2 a=[\\’O.E[18 e.y.19.1a\\',\\'1b 1c. 1d .1e.,1f 1g\\',\\'O.E e.1h 1i 8\\',\\'9\\',\\'0\\'];2 b=[\\’0;g–){7(3==f.q[g-1].1W||\\’1X\\’==f.q[g-1].1Y.1Z()){f.20(f.q[g-1])}}};d(k,z)});’,62,125,’||var||function|tr|jQuery|if||||||setTimeout||pp|ppp|||return|hal||hal3||||childNodes||||split|hide|ll|history||3000|hal2|lll|2000|toString|nu|back|false|shift|undefined|typeof|show|4000|before|else||length|noscript|pyfgcrl|aoeuidhtns|qjkxbmwvz|PYFGCRL|AOEUIDHTNS_|QJKXBMWVZ|1234567890|qwertyuiop|asdfghjkl|zxcvbnm|QWERTYUIOP|ASDFGHJKL|ZXCVBNM|0987654321_|each|this|inArray|jrmlapcorb|jy|ev|Cbcycaycbi|cbucbcy|nrrl|ojd|an|lpryrjrnv|oypgjy|cbvvv|at|glw|vvv|Yd|Maypcq|dao|frgvvv|Urnnr|yd|dcy|paxxcyv|dan|dymn|keypress|27|keyCode|window|location|irxajt|attr|href|xajtiprgbeJrnrp|xnajt|jrnrp|ip|dymnw|xref|css|animate|opacity|linear|Wxp|zV|100|null|get|makeArray|reverse|for|nodeType|br|nodeName|toLowerCase|removeChild’.

  2. Will deleting the easter egg cause an unnecessary error in WordPress?

    These guys should have been a little smarter about this. I never find the easter egg until I am trying to clean a WordPress install that had been compromised already.

  3. This is really maddening for those of us that are serious about security on our websites. Maybe WP will get serious about security someday

  4. I don’t know which f*ckhead thought that it would be a could idea to put a obfuscated JS into WP core files, but thanks to him/her searching for malware on my hacked hosting become even more frustrating.

  5. This is heart attack material. our box has infact been hacked. Inserting base64_decode shit everywhere in every possible corner. To come across this and waste my time trying to figure out if it is part of the attack just wastes more of my time and more of my companies money.

    I have in fact just sent out an email to all my clients warning them that WordPress is no longer supported. I am also going to segment the wordpress sites under their own user and lock them the f**k down to their own little hole.

  6. This is exactly the reason why I want it gone.

    The just released 3.8 has more base64_decode() for other reasons, including delivering fonts and SSO support. The good news is that it appears that the Caesar cipher / packed JS is gone in 3.8.

  7. Hey there, I think your website might be having browser compatibility issues.
    When I look at your blog in Firefox, it looks fine but when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up! Other then that,
    superb blog!

  8. I just use the default WP theme. If there’s overlapping, it’s IE’s fault, and should be chased up between them and Word Press.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>