Advertisement
black_paste

PHP Web Backdoor Scanner

Mar 16th, 2016
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.88 KB | None | 0 0
  1. <?php
  2. /* lookforbadguys.php 3-10-2011
  3. --Purpose: iterate through server files looking for hacker code snippets, backdoor scripts,
  4. .htaccess redirects, and suspicious file names.
  5. -- Caveats: Not all things it finds are hacks. Not all hacks are found.
  6. --You should look also for weird files (such as .php files) in your image directories, especially
  7. if your .htaccess has redirects or was made executable.
  8. --Some searches are commented out because they can give too many false positives.
  9. --This script should work the same on a Linux or Windows server.
  10. It runs fast in Linux/Apache/PHP, and very slowly in Windows/Apache/PHP.
  11.  
  12. */
  13. ?>
  14. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  15. <head>
  16. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  17. <meta http-equiv="Content-Language" content="en-us">
  18. <title>Looking for bad guys</title>
  19. </head>
  20.  
  21. <body>
  22. <p>Looking for bad guys. </p>
  23. <p>This script looks for traces of malicious code including code injections,
  24. modified .htaccess that makes images executable, and so on.</p>
  25. <p>
  26.  
  27. <?php
  28. // SET MAXIMUM EXECUTION TIME TO UNLIMITED (0) BECAUSE THE SCRIPT CAN TAKE A WHILE.
  29. // YOU COULD USE A MORE CONSERVATIVE TIME LIMIT SUCH AS 1 HOUR (3600 SECONDS), JUST IN CASE.
  30. // THESE HAVE NO EFFECT IF YOU RUN PHP IN "SAFE MODE" (SAFE MODE IS USUALLY UNDESIRABLE ANYWAY).
  31. ini_set('max_execution_time', '0');
  32. ini_set('set_time_limit', '0');
  33.  
  34. // --------------------------------------------------------------------------------
  35. // UTILITY FUNCTIONS.
  36. // OUTPUT TEXT IN SPECIFIED COLOR, CLEANING IT WITH HTMLENTITIES().
  37. function CleanColorText($text, $color)
  38. {
  39. $outputcolor = 'black';
  40. $color = trim($color);
  41. if(preg_match('/^(red|blue|green|black)$/i', $color))
  42. $outputcolor = $color;
  43. return '<span style="color:' . $outputcolor . ';">' . htmlentities($text, ENT_QUOTES) . '</span>';
  44. }
  45.  
  46. // --------------------------------------------------------------------------------
  47. // THIS FUNCTION RECURSIVELY FINDS FILES AND PROCESSES THEM THROUGH THE SPECIFIED CALLBACK FUNCTION.
  48. // DIFFERENT TYPES OF FILES NEED TO BE HANDLED BY DIFFERENT CALLBACK FUNCTIONS.
  49.  
  50. function find_files($path, $pattern, $callback)
  51. {
  52. // CHANGE BACKSLASHES TO FORWARD, WHICH IS OK IN PHP, EVEN IN WINDOWS.
  53. // REMOVE ANY TRAILING SLASHES, THEN ADD EXACTLY ONE.
  54. $path = rtrim(str_replace("\\", "/", $path), '/') . '/';
  55. if(!is_readable($path))
  56. {
  57. echo "Warning: Unable to open and enter directory " . CleanColorText($path, 'blue') .
  58. ". Check its owner/group permissions.<br>";
  59. return;
  60. }
  61. $dir = dir($path);
  62. $entries = array();
  63. while(($entry = $dir->read()) !== FALSE)
  64. $entries[] = $entry;
  65. $dir->close();
  66. foreach($entries as $entry)
  67. {
  68. $fullname = $path . $entry;
  69. if(($entry !== '.') && ($entry !== '..') && is_dir($fullname))
  70. find_files($fullname, $pattern, $callback);
  71. else
  72. if(is_file($fullname) && preg_match($pattern, $entry))
  73. call_user_func($callback, $fullname);
  74. }
  75. }
  76.  
  77. // --------------------------------------------------------------------------------
  78. // CALLBACK FUNCTIONS.
  79. // CALLBACK FUNCTION TO LOOK FOR MALICIOUS CODE - YOU COULD ADD ANY OTHER MALICIOUS CODE SNIPPETS YOU KNOW OF.
  80. function maliciouscodesnippets($filename)
  81. {
  82. if(stripos($filename, "lookforbadguys.php")) // DON'T FLAG THIS FILE WHICH I CALLED lookforbadguys.php
  83. return;
  84.  
  85. if(!is_readable($filename))
  86. {
  87. echo "Warning: Unable to read " . CleanColorText($filename, 'blue') .
  88. ". Check it manually and check its access permissions.<br>";
  89. return;
  90. }
  91. $file = file_get_contents($filename); //READ THE FILE
  92.  
  93. // PRINTING EVERY FILENAME GENERATES A LOT OF OUTPUT.
  94. //echo CleanColorText($filename, 'green') . " is being examined.<br>";
  95.  
  96. // TEXT FILES WILL BE SEARCHED FOR THESE SNIPPETS OF SUSPICIOUS TEXT.
  97. // THESE ARE REGULAR EXPRESSIONS WITH THE REQUIRED /DELIMITERS/ AND WITH SPECIAL CHARACTERS ESCAPED.
  98. // /i AT THE END MEANS CASE INSENSITIVE.
  99. $SuspiciousSnippets = array
  100. (
  101. // POTENTIALLY SUSPICIOUS PHP CODE
  102. '/edoced_46esab/i',
  103. '/passthru *\(/i',
  104. '/shell_exec *\(/i',
  105. '/document\.write *\(unescape *\(/i',
  106.  
  107. // THESE CAN GIVE MANY FALSE POSITIVES WHEN CHECKING WORDPRESS AND OTHER CMS.
  108. // NONETHELESS, THEY CAN BE IMPORTANT TO FIND, ESPECIALLY BASE64_DECODE.
  109. '/base64_decode *\(/i',
  110. '/system *\(/i',
  111. '/`.+`/', // BACKTICK OPERATOR INVOKES SYSTEM FUNCTIONS, SAME AS system()
  112. // '/phpinfo *\(/i',
  113. // '/chmod *\(/i',
  114. // '/mkdir *\(/i',
  115. // '/fopen *\(/i',
  116. // '/fclose *\(/i',
  117. // '/readfile *\(/i',
  118.  
  119. // SUSPICIOUS NAMES. SOME HACKERS SIGN THEIR SCRIPTS. MANY NAMES COULD GO HERE,
  120. // HERE IS A GENERIC EXAMPLE. YOU CAN FILL IN WHATEVER NAMES YOU WANT.
  121. '/hacked by /i',
  122.  
  123. // OTHER SUSPICIOUS TEXT STRINGS
  124. '/web[\s-]*shell/i', // TO FIND BACKDOOR WEB SHELL SCRIPTS.
  125. '/c99/i', // THE NAMES OF TWO POPULAR WEB SHELLS.
  126. '/r57/i',
  127.  
  128. // YOU COULD ADD IN THE SPACE BELOW SOME REGULAR EXPRESSIONS TO MATCH THE NAMES OF MALICIOUS DOMAINS
  129. // AND IP ADDRESSES MENTIONED IN YOUR GOOGLE SAFEBROWSING DIAGNOSTIC REPORT. SOME EXAMPLES:
  130. '/gumblar\.cn/i',
  131. '/martuz\.cn/i',
  132. '/beladen\.net/i',
  133. '/gooqle/i', // NOTE THIS HAS A Q IN IT.
  134.  
  135. // THESE 2 ARE THE WORDPRESS CODE INJECTION IN FRONT OF EVERY INDEX.PHP AND SOME OTHERS
  136. '/_analist/i',
  137. '/anaiytics/i' // THE LAST ENTRY IN THE LIST MUST HAVE NO COMMA AFTER IT.
  138. );
  139.  
  140. foreach($SuspiciousSnippets as $i)
  141. {
  142. // STRPOS/STRIPOS WERE A LITTLE FASTER BUT LESS FLEXIBLE
  143. if(preg_match($i, $file))
  144. echo CleanColorText($filename, 'blue') . ' MATCHES REGEX: ' . CleanColorText($i, 'red') . '<br>';
  145. }
  146.  
  147. if(!strpos($filename,"network.php") && !strpos($filename,"rewrite.php") && stripos($file,"RewriteRule"))
  148. echo CleanColorText($filename, 'blue') . " contains " . CleanColorText("RewriteRule", 'red') .
  149. " - check it manually for malicious redirects.<br>";
  150.  
  151. /*
  152. // THIS FINDS ALL JAVASCRIPT CODE. IF ENABLED, IT WILL GIVE *MANY* FALSE POSITIVES IN MOST WEBSITES.
  153. if($p = stripos($file, "<script "))
  154. echo CleanColorText($filename, 'blue') . ' contains SCRIPT:<br>' .
  155. CleanColorText(substr($file, $p, 100), 'red') . '<br><br>';
  156. */
  157. /*
  158. // THIS FINDS ALL IFRAMES. IF ENABLED, IT CAN GIVE MANY FALSE POSITIVES IN SOME WEBSITES.
  159. if($p = stripos($file, "<iframe "))
  160. echo CleanColorText($filename, 'blue') . ' contains IFRAME:<br>' .
  161. CleanColorText(substr($file, $p, 100), 'red') . '<br><br>';
  162. */
  163.  
  164. if(stripos($file, "AddHandler"))
  165. {
  166. // THIS IS HOW THEY MAKE THE IMAGE FILES EXECUTABLE.
  167. echo CleanColorText($filename, 'blue') . " contains " . CleanColorText('AddHandler', 'red') .
  168. " - make sure it does not make ordinary files like images executable.<br>";
  169. // IF YOU FIND NINE ZILLION OF THESE, UNCOMMENT IT BECAUSE IT IS A PAIN TO DELETE THEM BY HAND.
  170. // BUT CHECK THE LIST CAREFULLY FIRST TO MAKE SURE YOU REALLY WANT TO DELETE
  171. // ALL THE FILES AND NONE OF THEM ARE FALSE POSITIVES.
  172. //unlink($filename); // THIS DELETES THE FILE WITHOUT GIVING YOU THE OPTION OF EXAMINING IT!
  173. }
  174. }
  175.  
  176. // CALLBACK FUNCTION TO REPORT PHARMA LINK HACKS.
  177. function pharma($filename)
  178. {
  179. echo CleanColorText($filename, 'blue') . " is most likely a " . CleanColorText('pharma hack', 'red') . ".<br>";
  180. }
  181.  
  182. // CALLBACK FUNCTION TO REPORT FILES WHOSE NAMES ARE SUSPICIOUS.
  183. function badnames($filename)
  184. {
  185. echo CleanColorText($filename, 'blue') . " is a " . CleanColorText('suspicious file name', 'red') . ".<br>";
  186. }
  187.  
  188. // --------------------------------------------------------------------------------
  189. // SET UP THE SEARCH CRITERIA.
  190.  
  191. // SEARCHES WILL BE DONE IN THIS DIRECTORY AND ALL DIRS INSIDE IT.
  192. // './' MEANS CURRENT DIRECTORY, WHERE THIS SCRIPT IS NOW.
  193. // THUS, TO SEARCH EVERYTHING INSIDE PUBLIC_HTML, THAT'S WHERE THIS FILE SHOULD BE PUT.
  194. // TO SEARCH OUTSIDE PUBLIC_HTML, OR TO SEARCH A FOLDER OTHER THAN WHERE THIS SCRIPT IS STORED,
  195. // CHANGE THIS TO THE FULL PATHNAME, SUCH AS /home/userid/ OR /home/userid/public_html/somefolder/
  196. // USE FORWARD SLASHES FOR PATH. WINDOWS EXAMPLE: C:/wamp/apache2/htdocs/test/
  197. $StartPath = './';
  198.  
  199. // ENTRIES IN THE FOLLOWING 3 ARRAYS ARE REGULAR EXPRESSIONS, WHICH IS THE REASON FOR THE /DELIMITERS/.
  200. // FILES WHOSE NAMES MATCH THESE REGEXES WILL HAVE THEIR TEXT SEARCHED FOR MALICIOUS CODE.
  201. $FiletypesToSearch = array
  202. (
  203. '/\.htaccess$/i',
  204. '/\.php[45]?$/i',
  205. '/\.html?$/i',
  206. '/\.aspx?$/i',
  207. '/\.inc$/i',
  208. '/\.cfm$/i',
  209. '/\.js$/i',
  210. '/\.css$/i'
  211. );
  212.  
  213. // FILES OR FOLDERS WITH THESE STRINGS IN THEIR *NAMES* WILL BE REPORTED AS SUSPICIOUS.
  214. $SuspiciousFileAndPathNames = array
  215. (
  216. // '/root/i',
  217. // '/kit/i',
  218. '/c99/i',
  219. '/r57/i',
  220. '/gifimg/i'
  221. );
  222.  
  223. // FILENAMES RELATED TO WORDPRESS PHARMA HACK, USING THE NAMING CONVENTIONS
  224. // DESCRIBED AT http://www.pearsonified.com/2010/04/wordpress-pharma-hack.php
  225. // FILES MATCHING THESE NAMES WILL BE REPORTED AS POSSIBLE PHARMA HACK FILES.
  226. $PharmaFilenames = array
  227. (
  228. '/^\..*(cache|bak|old)\.php/i', // HIDDEN FILES WITH PSEUDO-EXTENSIONS IN THE MIDDLE OF THE FILENAME
  229. '/^db-.*\.php/i',
  230.  
  231. // PERMIT THE STANDARD WORDPRESS FILES THAT START WITH CLASS-, BUT FLAG ALL OTHERS AS SUSPICIOUS.
  232. // THE (?!) IS CALLED A NEGATIVE LOOKAHEAD ASSERTION. IT MEANS "NOT FOLLOWED BY..."
  233.  
  234. '/^class-(?!snoopy|smtp|feed|pop3|IXR|phpmailer|json|simplepie|phpass|http|oembed|ftp-pure|wp-filesystem-ssh2|wp-filesystem-ftpsockets|ftp|wp-filesystem-ftpext|pclzip|wp-importer|wp-upgrader|wp-filesystem-base|ftp-sockets|wp-filesystem-direct)\.php/i'
  235. );
  236.  
  237. // --------------------------------------------------------------------------------
  238. // FINALLY, DO THE SEARCHES, USING THE ABOVE ARRAYS AS THE STRING DATA SOURCES.
  239.  
  240. // REPORT FILES WITH SUSPICIOUS NAMES
  241. foreach($SuspiciousFileAndPathNames as $i)
  242. find_files($StartPath, $i, 'badnames');
  243.  
  244. // REPORT FILES WITH SUSPICIOUS PHARMA-RELATED NAMES
  245. foreach($PharmaFilenames as $i)
  246. find_files($StartPath, $i, 'pharma');
  247.  
  248. // REPORT FILES CONTAINING SUSPICIOUS CODE OR TEXT
  249. foreach($FiletypesToSearch as $i)
  250. find_files($StartPath, $i, 'maliciouscodesnippets');
  251.  
  252. echo "<br>Done<br>";
  253.  
  254. ?>
  255.  
  256. </p>
  257. </body>
  258. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement