PHP电子邮件注入预防


PHP Email Injection Prevention

下面是我用于一个简单联系人表单的代码。我们的代码似乎被操纵了,有人正在使用联系人表单进行电子邮件注入。我对PHP还比较陌生,我试过在网上进行研究,但目前我并不高兴。

有人有什么建议吗?

<?php
// get posted data into local variables
$EmailFrom = Trim(stripslashes($_POST['EmailFrom'])); 
$EmailTo = "email@email.com";
$Subject = "subject";
//$Title = Trim(stripslashes($_POST['Title'])); 
$First = Trim(stripslashes($_POST['First'])); 
//$Surname = Trim(stripslashes($_POST['Surname']));
//$Company = Trim(stripslashes($_POST['Company']));
//$Address = Trim(stripslashes($_POST['Address']));
//$Address2 = Trim(stripslashes($_POST['Address2']));
//$Address3 = Trim(stripslashes($_POST['Address3']));
//$Area = Trim(stripslashes($_POST['Area']));
//$County = Trim(stripslashes($_POST['County']));
//$Postcode = Trim(stripslashes($_POST['Postcode']));
$Telephone = Trim(stripslashes($_POST['Telephone']));
//$Fax = Trim(stripslashes($_POST['Fax']));
$EmailFrom = Trim(stripslashes($_POST['EmailFrom'])); 
$AmountOwed = Trim(stripslashes($_POST['AmountOwed']));
$ip = Trim(stripslashes($_POST['ip']));
//$Marketing = Trim(stripslashes($_POST['Marketing'])); 
//$Contact = Trim(stripslashes($_POST['Contact'])); 
$Details = Trim(stripslashes($_POST['Details'])); 
// validation
$validationOK=true;
if (Trim($EmailFrom)=="Your email: (required)") $validationOK=false;
if (!$validationOK) {
  print "<meta http-equiv='"refresh'" content='"0;URL=error.php'">";
  exit;
};
if (Trim($Telephone)=="Your Telephone: (required)") $validationOK=false;
if (!$validationOK) {
  print "<meta http-equiv='"refresh'" content='"0;URL=error.php'">";
  exit;
};
if (Trim($First)=="Your name: (required)") $validationOK=false;
if (!$validationOK) {
  print "<meta http-equiv='"refresh'" content='"0;URL=error.php'">";
  exit;
}
// prepare email body text
$Body = "";
//$Body .= "Title: ";
//$Body .= $Title;
//$Body .= "'n";
$Body .= "First: ";
$Body .= $First;
$Body .= "'n";
//$Body .= "Surname: ";
//$Body .= $Surname;
//$Body .= "'n";
//$Body .= "Company: ";
//$Body .= $Company;
//$Body .= "'n";
//$Body .= "Address: ";
//$Body .= $Address;
//$Body .= "'n";
//$Body .= "Address2: ";
//$Body .= $Address2;
//$Body .= "'n";
//$Body .= "Address3: ";
//$Body .= $Address3;
//$Body .= "'n";
//$Body .= "Area: ";
//$Body .= $Area;
//$Body .= "'n";
//$Body .= "County: ";
//$Body .= $County;
//$Body .= "'n";
//$Body .= "Postcode: ";
//$Body .= $Postcode;
//$Body .= "'n";
$Body .= "Telephone: ";
$Body .= $Telephone;
$Body .= "'n";
//$Body .= "Fax: ";
//$Body .= $Fax;
//$Body .= "'n";
$Body .= "EmailFrom: ";
$Body .= $EmailFrom;
$Body .= "'n";
$Body .= "AmountOwed: ";
$Body .= $AmountOwed;
$Body .= "'n";
$Body .= "ip: ";
$Body .= $ip;
$Body .= "'n";
//$Body .= "Marketing: ";
//$Body .= $Marketing;
//$Body .= "'n";
//$Body .= "Contact: ";
//$Body .= $Contact;
//$Body .= "'n";
$Body .= "Details: ";
$Body .= $Details;
$Body .= "'n";
// send email 
$success = mail($EmailTo, $Subject, $Body, "From: <$EmailFrom>");
// redirect to success page 
if ($success){
  print "<meta http-equiv='"refresh'" content='"0;URL=thankyou.php'">";
}
else{
  print "<meta http-equiv='"refresh'" content='"0;URL=error.php'">";
}
?>

我会从查看开始http://securephpwiki.com/index.php/Email_Injection#Using_php_mail.28.29_function了解实际发生了什么。

在输入时,验证输入,例如,检查输入的电子邮件实际上是一个电子邮件地址:

if (!filter_var($EmailFrom, FILTER_VALIDATE_EMAIL)) {
    // This isn't actually an email address
}

我建议您使用(simple?)正则表达式来验证您从在线模块接受的所有字段。

举个例子,您可以使用类似的东西来检查电子邮件地址是否符合RFC822

if (!preg_match('^'S+@'S+'.'S+$/',$EmailFrom)) { # this is bad

您也可以将此特定PECL函数用于该特定任务:http://php.net/manual/en/function.mailparse-rfc822-parse-addresses.php

重点是避免接受攻击者的控制字符(例如换行符),因此定义一个严格的正则表达式,并根据已知模式验证所有输入。

PHP的邮件功能极易受到攻击。有很多向量需要注意,但最有可能的是标头注入:

$success = mail($EmailTo, $Subject, $Body, "From: <$EmailFrom>");

在上面的代码中,您将headers字段指定为"From: <$EmailFrom>"

如果$EmailFrom包含一个有效的电子邮件地址,而没有其他内容,那么这是完全可以的。然而,黑客所需要做的就是向其添加换行符,然后他就可以开始添加额外的头了。一旦你可以在电子邮件中插入任意的标题,你基本上就可以重写整个电子邮件。

你目前没有对电子邮件地址进行任何验证,所以黑客很容易将他喜欢的东西注入这个领域。

因此,简单的答案是要更加小心地验证提交的电子邮件地址实际上是有效的电子邮件地址。

然而,正如我已经说过的,这并不是PHP的mail()函数的唯一问题,所以从长远来看,你应该认真考虑用更强大的解决方案来取代它,比如phpMailer或SwiftMailer库。这些库通过添加一层强大的安全功能,解决了在PHP中发送邮件的安全问题。它们还使使用更高级的电子邮件功能(如html电子邮件和附件)变得更容易。

如果您在PHP中遇到安全问题,您应该做的另一件事是确保您使用的是最新版本。如果你的PHP版本低于5.4.45(截至本答案发布之日),那么无论你的实际代码有多好,你都应该认为它有已知的安全漏洞,可以被删除。你还没有提到你使用的版本,但请检查并在必要时考虑升级。

最后,我注意到您正在对输入数据执行trim(stripslashes(...))。请注意,这是完全无用的。PHP的较新版本根本不需要您这样做。PHP的旧版本有一个设置,可以自动在输入数据中添加斜线;然后在代码中使用stripslashes()来删除它们。然而,这个功能在几年前就从PHP中删除了,所以如果您使用的是最新的PHP版本,stripslashes()函数将无法实现任何功能。但更重要的是,即使在必要的时候,它也肯定无法验证字段的内容或使其免受攻击。