Expressão regular para remover Iframe de arquivos PHP e HTML

Boa tarde a todos,
Tive alguns problemas de segurança referente à um script malicioso que fora executado e permitindo que em todos os arquivos (index.*) fosse adicionado uma tag IFRAME para fazer o carregamento de uma página de sei lá onde.
Bom, peço desculpas pelos usuários que tenham acessado a página na quinta-feira à noite e quero hoje compartilhar uma solução que utilizei além de dar algumas dicas de segurança para as configurações de um site.Primeiramente, a permissão de escrita de um arquivo, é algo complicado nos servidores WEB, logo porque devem ser tomadas uma série de cuidados antes de deixar um diretório ou arquivo com permissão de escrita, logo porque qualquer furo de SCRIPT PHP (ou da linguagem do servidor) pode fazer com que todos os arquivos com permissão de escrita sejam alterados.
O recomendado é que nenhum diretório fique com permissão de escrita, assim como os seus arquivos, mas um diretório de imagens por exemplo pode ficar liberado, mas o arquivo INDEX desse diretório tem que ficar protegido, no caso sem permissão de escrita.Quando se tem uma brecha de segurança em algum arquivo PHP por exemplo, o hacker/cracker pode fazer uma instrução que pode acabar com todo o servidor. Para isso é importante que todos os arquivos fiquem sem permissão de escrita.
Mas quando é tarde demais, e os arquivos do site, geralmente arquivos de índices do site (index.*) são os mais atacados, ou o atacante troca o conteúdo todo do arquivo por um determinado código ou ele inbute um trecho de códugo malicioso, no caso podem ser:

  • Iframes para forçar o download de algum arquivo;
  • Objects ou Embed para abrir propagandas e Flash;
  • Arquivos Javascripts, chamadas locais ou remotas;

Para resolver isso sem ter que ir alterar N milhões de arquivos PHP, HTML, etc. que tiveram um Iframe adicionado por exemplo, pode ser feita uma instrução recursiva para ler e alterar estes arquivos caso encontre uma determinada tag maliciosa.
Com a função PHP preg_match, é possível definir uma Expressão Regular para procurar dentro de um arquivo um determinado trecho, neste caso uma ou mais tags IFRAME.

[php]
‘{(<iframe).*?(>).*?(</iframe>)}i’
[/php]

Recomendo que seja utilizada a Expressão regular abaixo no caso de no seu site/código fonte a ser limpo, o mesmo faça o uso de IFRAMES para algum caso, upload em AJAX/IFRAME por exemplo.

[php]
‘{(<iframe).*?src=”http:.*?(>).*?(</iframe>)}i’
[/php]

Para agilizar a leitura, vamos definir algumas extensões de arquivos que não precisam ser lidas, logo temos a seguinte Expressão regular:

[php]
“(jpg|jpeg|gif|bmp|png|zip|doc|docx|pdf|xml|exe|gz|tar|rar)”;
[/php]

Após que o arquivo seja lido, vamos “fechar” a escrita do mesmo, logo definimos uma variável com as permissões devidas para o arquivo.

[php]
$permissoes = 0755;
//(Estas permissões podem ser em modo string, por exemplo ‘dr-x-x’…)
[/php]

Agora a função que iremos fazer, utiliza uma classe para arquivos do PHP, no caso a RecursiveDirectoryIterator, que contém diversas informações sobre arquivos e diretórios pronta. Esta classe necessita que a sua execução esteja dentro de um laço protejido, ou seja, dentro de um TRY/CATCH.

[php]
function lista_arquivos_diretorio_recursivo($it, $permissoes = 0555, $extensoes_negadas)
{
$corrigidos = 0;
$ER_iframe = ‘{(<iframe).*?(>).*?(</iframe>)}i’;
$modifica = false;
$string = null;
$fd = null;

while ($it->valid())
{
if($it->isDir() && !$it->isDot())
{
echo ‘<pre>Diretorio atual ‘.$it->current().’………………………………</pre>’;
if($it->hasChildren())
{
$bleh = $it->getChildren();
// Conta os próximos arquivos da iteração recursivamente.
$corrigidos += lista_arquivos_diretorio_recursivo($bleh, $permissoes, $extensoes_negadas);
}
}
elseif($it->isFile())
{
// Se tiver permissão faça os procedimentos necessários.
if($it->isReadable() && $it->isWritable())
{
if(!preg_match(“/.”.$extensoes_negadas.”$/i”, $it->current()))
{
$string = null;
$fd = fopen($it->current(), “r+”);
echo ‘<pre>Iniciando a leitura do conteúdo do arquivo ‘.$it->current().’……………………..</pre>’;
while($linha = fgets($fd))
{

if (preg_match($ER_iframe, $linha))
{
echo ‘<pre>Uma tag IFRAME encontrada no arquivo ‘.$it->current().’………………………..</pre>’;
$string .= preg_replace($ER_iframe, ”, $linha);
$modifica = true;
} else
{
$string .= $linha;
}
}
echo ‘<pre>Salvando modificações no arquivo ‘.$it->current().’……………………………</pre>’;

if($modifica)
{
$corrigidos++;
// Vai voltar o ponteiro para o início
rewind($fd);
// Apagará todos as linhas
ftruncate($fd, 0);
// Vai reescrever o arquivo, com os iframes removidos
fwrite($fd, $string);
// Vai fechar o arquivo
fclose($fd);
}

$fd = null;
$string = null;
echo ‘<pre>Definindo o arquivo ‘.$it->current().’ com permissões de leitura (‘.$permissoes.’)……………………………</pre>’;
chmod ($it->current(), $permissoes);
}
else
{
echo ‘<pre>O arquivo ‘.$it->current().’ não está na lista de Extensões de arquivos a serem verificados……………………..</pre>’;
}
}
else
{
echo ‘<pre>O arquivo ‘.$it->current().’ não possui permissão de Leitura ou Escrita……………………..</pre>’;
}
}
// Vai para o próximo arquivo ou diretório.
$it->next();
}
return $corrigidos;
}
[/php]

Feito isso, agora temos que fazer a chamada da nossa função, que segue no código abaixo:

[php]
try
{
// Caminho absoluto do diretório a ser lido.
$dir = “C:\xampp\htdocs\carlosinf-17-09\”;
$permissoes = 0755;
$extensoes_negadas = “(jpg|jpeg|gif|bmp|png|zip|doc|docx|pdf|xml|exe|gz|tar|rar)”;

echo ‘<pre>Iniciando leitura do diretório (‘.$dir.’)………………………….</pre>’;
$corrigidos = lista_arquivos_diretorio_recursivo(new RecursiveDirectoryIterator($dir), $permissoes, $extensoes_negadas);
echo ‘<pre>Leitura dos arquivos finalizada, foram corrigidos (‘.$corrigidos.’) arquivos(s)…………………</pre>’;
}
catch (Exception $e)
{
var_dump($e);
}
[/php]

Lembre-se de definir o diretório que irá ser lido, recomendo que execute em um diretório por vez, para ter uma maior segurança e controle. Ao andar da execução, a função irá imprimindo informações sobre a leitura e modificação dos arquivos.

Para fazer o download do código fonte clique no link abaixo:

http://www.mediafire.com/file/yeo8ry9y4i36p1b/remove-iframe.php.zip

Abraços e até a próxima.