我的PHP联系表单最近被用于发送垃圾邮件。此后已经实施了一些安全措施(请参阅下面的评论),我正在寻求其他人的集体智慧来审查代码并检查以确保它免受注入攻击。
提前感谢您抽出时间进行审核。
<?php
/* method for validate each input values in case any injection scripts it will ignore */
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
/* honeypot - if hidden field is completed discard form content */
if(!isset($_POST['honeypot']) || $_POST['honeypot'] != '')
{
die("You spammer!\n");
}
else
{
// define variables and set to empty values
$subject = $id = $subcategory = $subcategory = $subcategory_email = $to = $descError = $error =
$remarks = $response= $message= $name = $from = $phone ="";
if(isset($_REQUEST['category']) && $_REQUEST['category']!="")
{
//validate each input values for any injection attacks
$id = test_input($_REQUEST['category']);
$subcategory = test_input($_REQUEST['subcategory']);
$emails = array
(
array("0",""),
array("1","email1@yahoo.com","email2@yahoo.com"),
array("2","email1@yahoo.com","email2@yahoo.com"),
array("3","email1@yahoo.com","email2@yahoo.com"),
array("4","email1@yahoo.com","email2@yahoo.com"),
array("5","email1@yahoo.com","email2@yahoo.com")
);
$value = explode(",", $subcategory);
$subcategory_email = $emails[$id][$value[0]];
$remarks = test_input($_REQUEST['remarks']);
$message = '<html><body>';
$message .= '<table rules="all" style="border-color: #666;" border="1" cellpadding="10">';
$message .= "<tr style='background-color:#F5F5F5;'><th width=25%>Heading </th><th width=75%>Content</th></tr>";
$message .= "<tr><td><b>Category </b></td><td>".$category[$id-1]."</td></tr>";
$message .= "<tr><td><b>SubCategory </b></td><td>".$value[1]."</td></tr>";
$message .= "<tr><td><b>Comments</b></td><td><pre>".$remarks."</pre></td></tr>";
if($response==0)
{
$name = test_input($_REQUEST['name']);
$from = test_input($_REQUEST['email']);
if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$from))
{
$emailErr = "Invalid email format";
}
$phone = test_input($_REQUEST['phone']);
$message .= "<tr><td><b>Would you like a response? </b></td><td>Yes</td></tr>";
$message .= "<tr><td><b>Name</b></td><td>".$name."</td></tr>";
$message .= "<tr><td><b>E-Mail</b></td><td>".$from."</td></tr>";
$message .= "<tr><td><b>Telephone</b></td><td>".$phone."</td></tr>";
}
else
{
$from = "noreply@test.com";
$message .= "<tr><td><b>Would you like a response? </b></td><td>No</td></tr>";
}
$subject = "SubCategory ".$value[1];
//Normal headers
$headers = "From: " . strip_tags($from) . "\r\n";
$headers .= "Reply-To: ". strip_tags($subcategory_email) . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message .= "</table>";
if(mail($subcategory_email, $subject, $message, $headers))
{
include("thanks.php");
$error=6;
}
else
{
echo "mail not sent";
}
}
else
{
echo "<br/>";
$subject = "Sub Category";
$to = "Email1@yahoo.com";
if(empty($_REQUEST['remarks']))
{
$descError = "Enter Description";
$error = 5;
}
else
{
$remarks = test_input($_REQUEST['remarks']);
}
if(test_input($_REQUEST['response'])=="0")
{
$yesDIV = "checked";
$response = "Yes";
if(empty($_REQUEST['name']))
{
$nameError = "Name Required";
$error = 5;
}
else
{
$name = test_input($_REQUEST['name']);
}
$from = $_REQUEST['email'];
if(empty($_REQUEST['email']))
{
$emailError = "Email Required";
$error = 5;
}
else if (!filter_var($from, FILTER_VALIDATE_EMAIL)) {
$emailError = "Valid Email Required";
$error = 5;
}
}
else
{
$noDIV = "checked";
$response = "No";
$bodyDIV = "style='display:none;'";
}
if($error!=5)
{
$phone = test_input($_REQUEST['phone']);
$message = '<html><body>';
$message .= '<table rules="all" style="border-color: #666;" border="1" cellpadding="10">';
$message .= "<tr style='background-color:#F5F5F5;'><th width=25%>Heading </th><th width=75%>Content</th></tr>";
$message .= "<tr><td><b> Comments</b></td><td ><pre>".$remarks."</pre></td></tr>";
$message .= "<tr><td><b>Would you like a response? </b></td><td>".$response."</td></tr>";
$message .= "<tr><td><b>Name</b></td><td>".$name."</td></tr>";
$message .= "<tr><td><b>E-Mail</b></td><td>".$from."</td></tr>";
$message .= "<tr><td><b>Telephone</b></td><td>".$phone."</td></tr>";
$message .= "</table>";
//Normal headers
$headers = "From: noreply@test.com \r\n";
$headers .= "Reply-To: ". strip_tags($from) . "\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
if(mail($to, $subject, $message, $headers))
{
include("thanks.php");
$error=6;
}
else
{
echo "mail not sent";
}
}
}
}
?>
答案 0 :(得分:4)
术语“注入”是指代码注入,代码指的是任何计算机语言。由于每种计算机语言都不同,因此问题和解决方案也不同,需要以每种语言为基础进行处理。但是,您有一个通用函数,它试图立即阻止所有类型的注入,并且通常使用最糟糕的技术:删除用户数据。
例如:
$headers = "From: " . strip_tags($from) . "\r\n";
从电子邮件地址中删除HTML标记以撰写电子邮件标题会有什么意义?
$data = htmlspecialchars($data);
您将此应用于例如$_REQUEST['email']
。为什么要在电子邮件地址中插入HTML实体?
在您的代码中,我看到两个潜在的注入来源:
HTML - 当您将用户数据注入HTML时,您需要确保将用户数据作为纯文本处理(即,用户输入的任何内容都不会呈现为HTML)。您可以使用htmlspecialchars()
。你有点这样做,但确实很难确定。
电子邮件标题 - mail()
的第四个参数允许定义邮件标题。在那里注入原始用户输入(这可能是现在发生的事情)允许隐藏完整的消息体,用其他任何东西替换它,甚至选择新的接收者。你基本上必须剥离新的线条(再次,很难说你做得对吗......)。
使用PHP发送电子邮件很难。最好跳过好的旧mail()
并使用第三方库,如PHPMailer或Swift Mailer。