我可以通过仅替换 CR 来避免 CRLF 注入攻击吗?
我有一个表格,允许一个文件附件,并生成一封电子邮件到一个硬编码的地址。我想避免恶意用户输入自定义邮件标头的可能性(CRLF 注入,因为根据 RFC 电子邮件标头以 \r\n 结尾,所以称为 CRLF 注入)。
假设我对每条数据运行以下函数,这些数据可能会进入 $additional_headers 参数:
<?php
function strip_crlf($string){ return str_replace("\r\n", "\n", $string); }
?>
仅替换 CRLF 对的回车符一半。这能充分防止潜在的攻击吗?
通常我只是将 \r\n 替换为空字符串。但这种特殊形式允许一个附件,这意味着消息正文实际上最终会通过 $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.">\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);
}
?>
I have a form which allows one file attachment, and generates an email to a hard-coded address. I would like to avoid the possibility of malicious users entering custom mail headers (a CRLF injection, so called since email headers end in \r\n as per RFC).
Suppose I run the following function on every piece of data which might make it into the $additional_headers parameter:
<?php
function strip_crlf($string){ return str_replace("\r\n", "\n", $string); }
?>
That replaces JUST the carriage return half of the CRLF pair. Will that prevent potential attacks adequately?
Ordinarily I would just replace the \r\n with an empty string. But this particular form allows for one attachment, which means that the message body actually winds up getting passed through the $additional_headers parameter since PHP doesn't have a native function for building a multipart MIME encoded email (that I know of).
In case anyone cares, here's my function for mailing an attachment:
<?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);
}
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如果您担心注入,请不要构建自己的消息。使用 Swiftmailer 或 PHPMailer,为您解决所有这些后顾之忧。
If you're worried about injections, then don't build your own messages. Use Swiftmailer or PHPMailer, which take care of all those worries for you.