최근 내 서버는 일련의 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
죄송합니다. sed 대신 perl oneliner 표현식을 사용하고 있지만 어떻게 든 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
확장자가 추가된 파일 에 덤프합니다 .
하지만 서버가 손상된 경우 가장 좋은 방법은 서버를 지우고 백업에서 복원하는 것입니다. 또 어떤 나쁜 일이 일어날지 전혀 모릅니다.