Evitar Mail Injection em PHP

Maio 26, 2007

Pessoal nosso blog mudou de endereço! http://meiocodigo.com/

Bom pessoal, eu vou falar sobre um assunto que não é muito discutido e que muitos programadores até ignoram. O Mail Injection, que é uma forma de burlar um sistema de envio de e-mails em PHP, normalmente enviando spans a partir do servidor no qual o sistema esteja instalado. Isto pode denegrir a imagem de uma empresa, dentre outros problemas. Para saber mais, visite esta wiki que explica melhor.

Para começar vamos explicar o funcionamento da função mail(), a qual é nativa do php. Ela tem cinco parâmetros:

  • to > Endereço que irá receber o e-mail;
  • subject > Assunto da mensagem;
  • message > O corpo da mensagem;
  • additional_header > cabeçalhos adicionais(Com Cópia, Cópia Oculta, dentre outros cabeçalhos);
  • additional_parameters > usado para passar parametros para o programa que gerencia os e-mails.

Dentre estes campos, nós vamos nos preocupar com o to, o subject e o additional_header. Visto que os três são usados para incluir dados ao cabeçalho do e-mail.

Vamos a um exemplo, onde será mostrada a mensagem produzida pela execução da função mail:

mail('meiocodigo@gmail.com',$_GET['subject'],$_GET['message'],"From: ".$_GET['from']);

A função acima é largamente utilizada, visto que ele pega de um formulário o assunto, a mensagem e o remetente e envia por e-mail para um endereço fixo definido pelo progrador. Vamos supor que os valores de $_GET sejam como abaixo:

$_GET['subject'] = 'Post sobre Mail Injection';
$_GET['message'] = 'Pode tirar uma dúvida sobre o post sobre mail injection...';
$_GET['from'] = 'alguem@algumemail.com';

A mensagem produzida pela função supra-citada seria:

To: meiocodigo@gmail.com
Subject: Post sobre Mail Injection
From: alguem@algumemail.com

Pode tirar uma dúvida sobre o post sobre mail injection…
Note que o formato gerado é:

To: $to
Subject: $subject
$additional_headers

$message

Até aqui está tudo certo, nenhum problema com o nosso código. Mas imagine se alguem insere o seguinte valor para Subject: ‘Assunto%0ACc: outro@email.com%0ABcc: maisoutro@email.com’. Essa String tem o mesmo valor que:


Assunto
Cc: outro@email.com
Bcc: maisoutro@email.com

Colocando isso no texto criado pela função mail nós temos:


To: meiocodigo@gmail.com
Subject: Assunto
Cc: outro@email.com
Bcc: maisoutro@email.com
From: alguem@algumemail.com

Pode tirar uma dúvida sobre o post sobre mail injection…
Note que o arquivo gerado tem mais 2 itens no cabeçalho: um email para ser enviado como cópia; e outro como cópia oculta. É dessa forma que o formulário de e-mail é usado para fazer ataques de span. O detalhe é que o cabeçalho tem como separador a quebra de linha, ou seja, só é considerado um novo item do cabeçalho caso haja uma quebra de linha. Isso justifica o uso do %0A, que é o código hexadecimal da quebra de linha.

O que foi explicado acima se aplica a qualquer um dos três campos citados que fazem parte do cabeçalho.

Para resolver isso, eu criei uma função que checa se existem caracteres de quebra de linha nas strings de cabeçalho, retornando false, caso encontre:


function check_mail_injection($string){
if(strpos($string,'\n') !== false) return false;
if(strpos($string,'\r') !== false) return false;
if(strpos($string,'%') !== false) return false;
return true;
}

Quero dedicar os créditos dessa função ao meu amigo Edson Aníbal da Superintendência de Informática da UFRN, que foi quem fez o procedimento, eu apenas encapsulei em uma função.

Vamos entender a função, ela pega uma $string, e verifica a existência de um caractere ‘\n’, ‘\r’ ou ‘%’. Os dois primeiros representam quebra de linha. E o ‘%’ pode ser usado para representar o código hexadecimal da quebra de linha.

Só mais um detalhe, não é recomendável aplicar essa função ao corpo da mensagem, visto que a mesma pode conter quebras de linha.

Espero ter sido claro. Qualquer dúvida coloca nos comentários.