【问题标题】:Preventing mail injection in php intercepting some characters \r, \n, %0A, %0D防止php中的邮件注入拦截一些字符\r、\n、%0A、%0D
【发布时间】:2016-02-24 09:33:07
【问题描述】:

我想阻止人们在 php 中使用用于邮件注入的特殊字符发送垃圾邮件。例如\n\r 用于连接多个标头,因此也可以与%0A%0D 连接。所以我写了一个正则表达式来匹配它们。但我怀疑我的正则表达式效率不高......有些东西让我觉得我正在写一些无法使用的东西......感谢任何帮助,谢谢。

这是我想做的一个基本示例......

if (!preg_match('/^[^\s]./', $_POST['name']) || (preg_match('/(%0A|%0D|\\n+|\\r+|;|mime-version:|content-type:|content-transfer-encoding:|subject:|to:|cc:|bcc:)/i', $_POST['name'])) || !(strpos($_POST['name'],'\r') === false) || !(strpos($_POST['name'],'\n') === false)) {
  exit("Warning: your Name contains illegal characters! This mail will not be sent!");
} elseif (!preg_match('/^[^\s]./', $_POST['subject']) || (preg_match('/(%0A|%0D|\\n+|\\r+|;|mime-version:|content-type:|content-transfer-encoding:|subject:|to:|cc:|bcc:)/i', $_POST['subject'])) || !(strpos($_POST['subject'],'\r') === false) || !(strpos($_POST['subject'],'\n') === false)) {
  exit("Warning: your Subject contains illegal characters! This mail will not be sent!");
} elseif (!preg_match('/^[a-zA-Z0-9]+([_\\.-][a-zA-Z0-9]+)*'.'@([a-zA-Z0-9]+([\.-][a-zA-Z0-9]+))+$/', $_POST['mail'])) {
  exit("Warning: your Mail contains no valid email address! This mail will not be sent!");
} elseif (!preg_match('/^[^\s]./', $_POST['message'])) {
  exit("Warning: your Message connot be empty! This mail will not be sent!");
} else {
  $name = $_POST['name'];
  $mail = $_POST['mail'];
  $subject = $_POST['subject'];
  $message = $_POST['message'];
  mail($to, $subject, $message, $headers, "-f$mail") {
  exit("Your Mail is sent! Thanks!");
}

为了匹配\n\r%0A%0D,我应该如何编写我的正则表达式?

!(strpos($_POST['subject'],'\r') === false)!(strpos($_POST['subject'],'\n') === false)

还不错?

谢谢。

【问题讨论】:

  • 看看this,是关于现场消毒
  • 我正在使用我的正则表达式验证邮件地址:if (!preg_match('/^[a-zA-Z0-9]+([_\\.-][a-zA-Z0-9]+)*'.'@([a-zA-Z0-9]+([\.-][a-zA-Z0-9]+))+$/', stripslashes($_POST['fmail']))) { 谢谢,我需要在我的主题中修复我的正则表达式,我对 FILTER_SANITIZE_EMAIL 不感兴趣。
  • 如果stripslashes() 意味着您启用了魔术引号,那么您的服务器已经过时了。你可能有比这更糟糕的问题需要关心。在任何情况下,发送电子邮件都很难(真的!),而且通常不值得自己付出努力。只需安装任何第三方库,如 Swift Mailer 或 PhpMailer。 ——
  • 谢谢,我正在运行 apache 2.4 和 php 5.6.17 但由于我有一个脚本可以提供给其他人,我不知道这些人是在运行现代 php 版本还是过时的版本。我为运行旧版本 php 的人添加了stripslashes。因为我不知道我的脚本会用在哪里……

标签: php regex email code-injection spam


【解决方案1】:

我做了一个测试。测试结果是成功的!我用不同的方法直接在localhost 中测试了正则表达式:

<?php
$test = "the dog \n was \r sleeping on the floor";
if (preg_match_all('/(%0A|%0D|\\n+|\\r+|;|mime-version:|content-type:|content-transfer-encoding:|subject:|to:|cc:|bcc:)/i', $test, $tmp)) {
  echo "I found this character: '";
  print_r($tmp[1]);
  echo "'";
} else {
  echo "I cannot find any string searched";
}
?>

结果:

I found this character: 'Array ( [0] => [1] => ) '

查看源代码我可以看到 \n 和 \r

I found this character: 'Array
(
    [0] => 

    [1] => 
)
'

所以我认为正则表达式构建得很好。

还有我用strpos()做的其他测试:

if !(strpos($_POST['subject'],'\n') === false)) {

用单引号失败,而用双引号找到 \n...

if !(strpos($_POST['subject'],"\n") === false)) {

结论:正则表达式格式正确,strpos() 需要 "" 来匹配 \n 或 \r。

【讨论】:

    【解决方案2】:

    我对正则表达式不是很彻底,但我可以通过为您的问题提供替代技巧解决方案来帮助您。

    您可以使用以下代码来解决您的目的。

    <?php
    
    function sanitize_strings($raw_string) {
        return preg_replace("/[^0-9a-zA-Z_\-\\\%]+/", "", $raw_string);
    }
    
    if( $raw_string == sanitize_strings($raw_string) )
    {
        echo "No illegal characters found.";
    }
    else
    {
        echo "Illegal characters found.";
    }
    
    ?>
    

    希望这对你有用。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      • 2021-04-25
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多