Feed e Twitter

Feed RSS Twitter

Busca

Por Lustosa em 28/12/2008 às 20:40

Muitas aplicações, e a maioria dos sites, qualquer que seja a linguagem em que tenha sido desenvolvido, precisa enviar emails, seja para contato do visitante, ou para enviar o link para um amigo, ou até mesmo como confirmação de um formulário qualquer.

Porém, se não forem tomados os devidos cuidados, sua aplicação pode ser explorada, e seu servidor pode passar a ser mais uma ferramente nas mãos dos spammers, pronto pra ficar enviando todo tipo de lixo pra meio mundo.

O principal problema com isso, além do fato do seu servidor passar a disseminar a praga que é o spam, é que seu servidor pode cair em algumas das listas negras, e com isso você passa a não conseguir mais enviar emails legítimos pra quem usa as tais listas pra se proteger contra o spam.

Resumindo: é uma dor de cabeça que você não quer ter.

Os cuidados que você precisa tomar no PHP pra não acabar com um problema desses é bem simples. Vamos ver, passo a passo, como normalmente é feito o envio de emails através do PHP, e onde podemos melhorá-lo.

Um formulário típico de contato de algum site, poderia ter a forma abaixo:

<form action="envia.php" method="post">
Nome: <input type="text" name="nome" /><br />
Email: <input type="text" name="email" /><br />
Mensagem: <textarea name="mensagem"></textarea><br />
<input type="submit" />
</form>

Ou seja, com o formulário acima, o usuário coloca seu nome, seu email, e a mensagem que deseja enviar. Ao se clicar no botão de submit, os dados são passados para o script envia.php, que tem a tarefa de enviar um email com a mensagem do usuário. Esse script, muitas vezes é implementado da seguinte forma, usando a função mail() do PHP:

<?php
$para = "equipe@site.com.br";
$assunto = "Contato do site";
$msg = $_POST['mensagem'];
$headers = "From: {$_POST['nome']} <{$_POST['email']}>";
mail($para, $assunto, $msg, $headers);
?>

Tudo muito bonito. O usuário envia seu nome, email e a mensagem, e o script PHP manda um email para equipe@site.com.br com o conteúdo do email. Estaria perfeito se não fosse pela montagem do cabeçalho From. O grande problema está em não tratar esses dados que foram enviados pelo usuário. Se o usuário faz o envio normalmente, teríamos um email mais ou menos assim (estou ignorando alguns cabeçalhos para simplificar o exemplo):

Nesse caso, postei meu nome, meu email, e a mensagem acima é enviada para a equipe do site. Porém, como o usuário tem o controle sobre o que entra no cabeçalho da mensagem, ele pode ser um pouco sacana, e colocar uma quebra de linha no nome dele, com algumas coisas depois. Por exemplo, se no lugar do meu nome eu coloco “Buy Viagra <xx@xx.com>nBcc: email1, email2, email3″ e na mensagem eu coloco algo sobre venda de viagra, teríamos o seguinte email montado:

Isso foi apenas um exemplo, mas dá pra combinar outras técnicas e conseguir por exemplo sobrescrever o assunto da mensagem. E hoje em dia, já existem robôs vasculhando formulários de sites buscando por vulnerabilidades desse tipo. Aconteceu em um código antigo da empresa onde estou trabalhando agora. Começamos a entrar em algumas listas negras e sem entender o porque. Quando fomos verificar a fila de emails esperando pra sair do servidor, eram mais de 30 mil spams sobre todo tipo de lixo. E vasculhando os logs do servidor web, chegamos ao script culpado.

É claro que isso NÃO É um problema do PHP. O PHP é tão seguro quanto uma pistola. Se o programador decide dar um tiro no próprio pé, não dá pra colocar a culpa na arma, não é? Esse é apenas mais um exemplo do tipo de problema que podemos enfrentar quando não validamos os dados enviados pelo usuário. Sempre que qualquer informação for enviada de um lugar não confiável, essa informação deve ser checada. Uma simples verificação em $_POST['nome'], buscando por quebras de linha, ou em $_POST['email'], verificando se se trata de um email válido, já resolveria esse problema.

A grande maioria dos problemas que vemos divulgados diariamente em todo tipo de script PHP se baseiam no fato de que os programadores não tem o hábito de programar pensando em segurança, e não fazem as checagens mais básicas, deixando os scripts vulneráveis a ataques como o descrito acima e outros.

Artigos relacionados

Arquivado em programação

Feed RSS para os comentários deste artigo.


2 comentários em “Segurança no envio de emails em PHP”

  1. marujo comentou:

    oi Bruno. estou me deparando com este problema. como deve ficar então o cabeçalho from? coloque por favor como é o ideal, pra ficar mais seguro, por favor.
    abs e obrigado!

  2. Bruno Lustosa comentou:

    Oi, Marujo. O problema não é exclusivamente com o cabeçalho “from”. Em qualquer cabeçalho onde você vá colocar dados fornecidos pelo usuário, você deve fazer a validação, pra evitar que esses dados contenham, por exemplo, quebras de linha.
    Por exemplo, se você tem o nome e o email do usuário em variáveis chamadas $nome e $email, você poderia fazer a checagem assim:


    if (strpos($nome, "\n")) {
    // quebra de linha detectada
    exit;
    }
    if (!Validate::email($email)) {
    // email inválido
    exit;
    }

    2 pontos:
    - Estou usando “exit” caso alguma entrada inválida tenha sido detectada, mas poderia exibir uma mensagem de erro, ou qualquer outra coisa. O importante é não deixar passar da forma que chegou.
    - A validação do email eu deixei a cargo da biblioteca PEAR Validate, que é uma classe bastante útil para validação de dados. Eu já escrevi um artigo sobre a classe PEAR Validate, sugiro que dê uma lida caso ainda não tenha visto:

    http://www.ataraxia.com.br/posts/validacao-de-dados-em-php

    Abraço!


Copyright 2009 Ataraxia!   Sinopse