最近,我的服务器成为一系列 php 漏洞攻击的目标,使用 ClamAV 我能够识别许多受感染的文件。
这里的问题是,有些合法文件被感染,有些则完全是恶意代码。
幸运的是,受感染的文件采用以下格式:
<?php //malicious code ?>
<?php //legitimate part ?>
所以我想我可以sed
只删除第一次出现的 php 标签。这样,合法代码将保持完整,恶意部分将被删除。
为此,我使用了以下命令:
sed 's/<?php.*?>//' file.php
这有两个问题:
- 它替换每一个出现的地方而不是第一个
- 多行出现时失败
我使用过很多表格,但它们都在某一点上失败了。
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
扩展名的文件中。
尽管如此,当您的服务器受到威胁时,最佳实践是擦除它并从备份中恢复。不知道还会发生什么其他糟糕的事情。