我可以通过更换CR来避免CRLF注入攻击吗?

时间:2011-06-29 22:03:21

标签: php security email sanitization newline

我有一个允许一个文件附件的表单,并生成一个硬编码地址的电子邮件。我想避免恶意用户输入自定义邮件头的可能性(CRLF注入,因为电子邮件头根据RFC以\ r \ n结尾,因此被调用)。

假设我对每个可能进入$additional_headers参数的数据运行以下函数:

<?php

function strip_crlf($string){ return str_replace("\r\n", "\n", $string); }

?>

它取代了CRLF对的回车一半。这会充分防止潜在的攻击吗?

通常我会用空字符串替换\ r \ n。但是这种特殊的形式允许一个附件,这意味着消息体实际上最终通过$ additional_headers参数传递,因为PHP没有用于构建多部分MIME编码电子邮件的本机函数(我知道)。 p>

如果有人关心,这是我邮寄附件的功能:

<?php
function mail_attachment($to, $from, $from_name, $subject, $message, $file = false, $filename = false, $filetype = false){

    // Remove CRLF sequences from everything that might go into a header
    $from = strip_crlf($from);
    $from_name = strip_crlf($from_name);
    $message = strip_crlf($message);
    if($filename){ $filename = strip_crlf($filename); }
    if($filetype){ $filetype = strip_crlf($filetype); }

    // $to and $subject escaping handled natively by mail();
    // $file is base64 encoded before mail_attachment() is called.

    $header = '';

    // No file attachment; just send a regular email.
    if(!$file){
        $header .= "From: ".$from_name." <".$from.">\r\n";
        return mail($to, $subject, $message, $header);
    }

    $uid = md5(uniqid(time()));

    // Build a MIME encoded message.
    $header .= "MIME-Version: 1.0\r\n";
    $header .= "Content-Type: multipart/mixed; boundary=\"$uid\"\r\n\r\n";
    $header .= "This is a multi-part message in MIME format.\r\n";
    $header .= "--$uid\r\n";
    $header .= "Content-type:text/plain; charset=utf-8\r\n";
    $header .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
    $header .= "$message\r\n\r\n";
    $header .= "--$uid\r\n";
    $header .= "Content-Type: $filetype; name=\"$filename\"\r\n";
    $header .= "Content-Transfer-Encoding: base64\r\n";
    $header .= "Content-Disposition: attachment; filename=\"$filename\"\r\n\r\n";
    $header .= "$file\r\n\r\n";
    $header .= "--$uid--";

    // Send the mail.
    return mail($to, $subject, '', $header);
}

?>

2 个答案:

答案 0 :(得分:5)

如果您担心注射,请不要构建自己的消息。使用SwiftmailerPHPMailer来处理所有这些担忧。

答案 1 :(得分:3)

不,仅替换CR是不够的 - 有足够的邮件客户端只能查看它可以被利用的LF。当然,大多数标题字段都不需要新行 ,因此您可以简单地从除$message之外的所有内容中删除CR和LF。对于$message,要么确保它不能包含您的MIME分隔符(在这种情况下为--$uid),要么将其编码为base64或其他内容。