El libro de Django 1.0

19.6. Inyección de cabeceras de email

La hermana menos conocida de la inyección de SQL, la inyección de cabeceras de email, toma control de formularios Web que envían emails. Un atacante puede usar esta técnica para enviar spam mediante tu servidor de email. Cualquier formulario que construya cabeceras de email a partir de datos de un formulario Web es vulnerable a este tipo de ataque.

Analicemos el formulario de contacto canónico que puede encontrarse en muchos sitios. Normalmente el mismo envía un mensaje a una dirección de email fija y, por lo tanto, a primera vista no parece ser vulnerable a abusos de spam.

Sin embargo, muchos de esos formularios permiten también que los usuarios escriban su propio asunto para el email (en conjunto con una dirección "de", el cuerpo del mensaje y a veces algunos otros campos). Este campo asunto es usado para construir la cabecera "subject" del mensaje de email.

Si dicha cabecera no es escapada cuando se construye el mensaje de email, un atacante podría enviar algo como "hello\ncc:[email protected]" (donde "\n" es un caracter de salto de línea). Eso haría que las cabeceras de email fueran:

To: [email protected]
Subject: hello
cc: [email protected]

Como en la inyección de SQL, si confiamos en la línea de asunto enviada por el usuario, estaremos permitiéndole construir un conjunto malicioso de cabeceras, y podrá usar nuestro formulario de contacto para enviar spam.

19.6.1. La solución

Podemos prevenir este ataque de la misma manera en la que prevenimos la inyección de SQL: escapando o verificando siempre el contenido enviado por el usuario.

Las funciones de mail incluidas en Django (en django.core.mail) simplemente no permiten saltos de línea en ninguno de los campos usados para construir cabeceras (las direcciones de y para, más el asunto). Si intentas usar django.core.mail.send_mail con un asunto que contenga saltos de línea, Django arrojará una excepción BadHeaderError.

Si no usas las funciones de email de Django para enviar email, necesitarás asegurarte de que los saltos de línea en las cabeceras o causan un error o son eliminados. Podrías querer examinar la clase SafeMIMEText en django.core.mail para ver cómo implementa esto Django.