使用 sed 清除受感染文件中的 PHP 漏洞

使用 sed 清除受感染文件中的 PHP 漏洞

最近,我的服务器成为一系列 php 漏洞攻击的目标,使用 ClamAV 我能够识别许多受感染的文件。

这里的问题是,有些合法文件被感染,有些则完全是恶意代码。

幸运的是,受感染的文件采用以下格式:

<?php //malicious code ?>
<?php //legitimate part ?>

所以我想我可以sed只删除第一次出现的 php 标签。这样,合法代码将保持完整,恶意部分将被删除。

为此,我使用了以下命令:

sed 's/<?php.*?>//' file.php

这有两个问题:

  1. 它替换每一个出现的地方而不是第一个
  2. 多行出现时失败

我使用过很多表格,但它们都在某一点上失败了。

sed '0,/<?php.*?>/{s/<?php.*?>//}' //this has also failed

所以我想也许你们可以给我一些关于如何使这个 sed 命令工作的提示,或者建议任何更好的工具来完成手头的任务。

答案1

抱歉,我使用 perl oneliner 表达式代替 sed,但不知怎的,我无法学习/记住 sed 的正则表达式。所以你可以尝试这个:

  $ cat somefile.php | tr '\n' '@@@' | perl -p -e 's/^(.*?)(<\?php.*?\?>)(.*$)/$1$3/' | tr '@@@' '\n' > somefile_1.php

第一个tr是更改单行字符串中的多行字符串。 ' @@@' 字符串只是一个示例,它可以是您要编辑的任何文件中不存在的任何字符串(首先 grep 它只是为了确定)。
接下来,perl 命令正在执行实际工作:使用正则表达式组将字符串拆分为三个部分 - 首先是 php 块第一次出现之前的所有内容,下一个 php 块本身,最后是第一个 php 块之后的所有内容。请注意,?字符用于使通配符表达式.*非贪婪,其他问号必须转义。
最后一个tr返回换行符(它必须使用与第一个相同的字符串tr- 在本例中为“ @@@”)。

答案2

您的问题是 sed 是一个单行工具;它一次查看一行文件。可以告诉它保留跨行上下文,并据此改变其操作,但这是 sed 的一个相当模糊和困难的功能,因此很少使用。相反,我会用 Perl 来做到这一点:

#!/usr/bin/perl -w
use strict;
use warnings;

foreach my $file (@ARGV) {
    open INPUT, "<$file";
    open OUTPUT, ">$file.new";
    my $found = 0;
    while (my $line=<INPUT>) {
        if ($line =~ /<\?php/ && !$found) {
            $found=1;
        } else {
            print OUTPUT $line;
        }
    }
    close INPUT;
    close OUTPUT;
}

使用您希望其作为命令行参数编辑的文件列表进行调用。它将过滤后的输出转储到具有附加.new扩展名的文件中。

尽管如此,当您的服务器受到威胁时,最佳实践是擦除它并从备份中恢复。不知道还会发生什么其他糟糕的事情。

相关内容