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



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

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

<?php
function strip_crlf($string){ return str_replace("rn", "n", $string); }
?>

这取代了CRLF对的JUST回车。这能充分防止潜在的攻击吗?

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

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

<?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.">rn";
        return mail($to, $subject, $message, $header);
    }
    $uid = md5(uniqid(time()));
    // Build a MIME encoded message.
    $header .= "MIME-Version: 1.0rn";
    $header .= "Content-Type: multipart/mixed; boundary="$uid"rnrn";
    $header .= "This is a multi-part message in MIME format.rn";
    $header .= "--$uidrn";
    $header .= "Content-type:text/plain; charset=utf-8rn";
    $header .= "Content-Transfer-Encoding: 8bitrnrn";
    $header .= "$messagernrn";
    $header .= "--$uidrn";
    $header .= "Content-Type: $filetype; name="$filename"rn";
    $header .= "Content-Transfer-Encoding: base64rn";
    $header .= "Content-Disposition: attachment; filename="$filename"rnrn";
    $header .= "$filernrn";
    $header .= "--$uid--";
    // Send the mail.
    return mail($to, $subject, '', $header);
}
?>

如果您担心注入,那么不要构建自己的消息。使用Swiftmailer或PHPMailer,它们可以为您解决所有这些担忧。

不,仅仅替换CR是不够的——有足够多的邮件客户端只查看LF,可以利用它。当然,大多数头字段根本不需要换行符,所以您可以简单地从除$message之外的所有字段中删除CR和LF。对于$message,请确保它不能包含MIME分隔符(在本例中为--$uid(,或者将其编码为base64或其他类型。

相关内容

  • 没有找到相关文章

最新更新