原理
邮件的结构,分为信封(MAIL FROM、RCPT TO)、头部(From,To,Subject、CC、BCC等)、主体(message)。
所谓的邮件头注入,其实就是针对头部的部分。对于邮件头部的字段其实就是换行符0x0A或者0x0D0x0A分割 ,在绝大部分系统里面不是\n 就是\r\n,所以就可以注入了。例如在一段没有过滤的FROM字段里面输入,就可以添加一个收件人。
邮件格式
- return-path:邮件的回复地址。
- from:发件人地址。
- to:收件人地址。
- subject:邮件主题,即邮件名。
- body:邮件内容。
- date:邮件发送日期。
- cc:抄送。
- bcc:密送。
分类
一般我们可以控制3个部分,一是发件人,二是主题,三是内容,因此可以按照这三类进行。发件人处的注入危害比较大,姿势也比较多。主要有以下5类:
1、看邮件服务器针对多个from是如何实现的,是取第一个,还是取最后一个,还是两个都取?
from=admin%40domain.com%0Afrom:eval%40domain.com
2、CC(抄送)注入、BBC(密送)注入
在发送者字段(sender)后注入Cc和Bcc参数
from:sender%40domain.com%0ACc%3Arecipient%40domain.com%0ABcc%3Arecipient1@domain.com
3、参数注射
消息将被发送到原来的收件人和攻击者帐户。
From:sender@domain.com%0ATo:attacker@domain.com
4、邮件主题注入
攻击者注入的假的主题subject将被添加到原来的主题中并且在某些情况下将取代原本的主题subject。这取决于邮件服务行为。即代码编写的容错性,当参数中出现两个subject的时候代码是选择丢弃还是后者覆盖。
From:sender@domain.com%0ASubject:This’s%20Fake%20Subject
5、改变消息的主体body
要注意SMTP的Mail格式,消息主题和头部Header之间有两个换行符(和HTTP是一样的)。
From:sender@domain.com%0A%0AMy%20New%20%0Fake%20Message.
PHP函数
当mail()函数中的参数可控的时候,且没有任何过滤的时候,漏洞就可能存在。
mail():
http://www.php.net/manual/en/function.mail.php
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
修复建议
1. 永远不要信任用户的输入字段。所有用户输入应该被认为是不可信的和潜在的恶意。应用程序不受信任的输入过程可能会变得容易受到诸如缓冲区溢出攻击、SQL注入,OS指令注入、拒绝服务和电子邮件注入。
2. 使用正则表达式来过滤用用户提交的数据。例如,我们可以在输入字符串中搜索(r 或 n)。
3. 使用外部组件和库,提供防范这个问题像 ZEND mail、PEAR mail和swift mailer。
4. ModSecurity可以阻止服务器级别的电子邮件注入。利用ModSecurity,我们可以检测通过POST或GET提交的CC, BCC或目的地址,并且拒绝任何包含这些字母请求。