我有以下表格供用户填写:
<form name="form" action="" method="POST">
<table width="100%" border="0" cellpadding="2" cellspacing="2">
<tr>
<td width="25%" ><div align="right"><strong>Name:</strong></div></td>
<td width="75%" ><span id="sprytextfield1">
<input id="Cname"name="Name" type="text" placeholder="Please fill in your name">
<span class="textfieldRequiredMsg">A value is required.</span></span></td>
</tr>
<tr>
<td><div align="right"><strong>Email:</strong></div></td>
<td><span id="sprytextfield2">
<input id="Cemail"name="email" type="text" placeholder="e.g sales@company.co.uk">
<span class="textfieldRequiredMsg">A value is required.</span><span class="textfieldInvalidFormatMsg">Invalid format.</span></span></td>
</tr>
<tr>
<td><div align="right"><strong>Phone Number:</strong></div></td>
<td>
<input id="Cphone" name="Phone" type="text"placeholder="e.g. 5555-6666666">
</td>
</tr>
<tr>
<td> </td>
<td><input name="Manufacturer" type="hidden" value="<?php echo $row_emailProduct['Manufacturer']; ?>">
<input name="Model" type="hidden" value="<?php echo $row_emailProduct['Model']; ?>">
<input name="Color" type="hidden" value="<?php echo $row_emailProduct['Color']; ?>">
<input name="price" type="hidden" value="<?php echo $row_emailProduct['price']; ?>">
<input name="id" type="hidden" value="<?php echo htmlentities($_GET['id']); ?>">
<input name="insert" id="insert" type="submit" value="Send Request"></td>
</tr></tr>
</table>
</form>
Run Code Online (Sandbox Code Playgroud)
提交表单后,会发生以下情况:
if (isset($_POST["insert"])){
$OK=false;
$insertSQL = "INSERT INTO Item_intrest (Manufacturer, Model, Color, price, Name, Phone, email) VALUES (:Manufacturer, :Model, :Color, :price, :Name, :Phone, :email)";
$Result1 = $conn->prepare($insertSQL) or die(errorInfo());
$Result1->bindParam(':Manufacturer', htmlentities($_POST['Manufacturer']), PDO::PARAM_STR);
$Result1->bindParam(':Model', htmlentities($_POST['Model']), PDO::PARAM_STR);
$Result1->bindParam(':Color', htmlentities($_POST['Color']), PDO::PARAM_STR);
$Result1->bindParam(':price', htmlentities($_POST['price']), PDO::PARAM_STR);
$Result1->bindParam(':Name', htmlentities($_POST['Name']), PDO::PARAM_STR);
$Result1->bindParam(':Phone', htmlentities($_POST['Phone']), PDO::PARAM_STR);
$Result1->bindParam(':email', htmlentities($_POST['email']), PDO::PARAM_STR);
$Result1->execute();
$OK = $Result1->rowCount();
/*email to shop */
$emailsubject = 'Product Request';
$webmaster = 'sales@company.co.uk';
/*data collection */
$Name = htmlentities($_POST['Name']);
$email = htmlentities($_POST['email']);
$Phone = htmlentities($_POST['Phone']);
$item1 = htmlentities($_POST['Manufacturer']);
$item2 = htmlentities($_POST['Model']);
$item3 = htmlentities($_POST['Color']);
$Price = htmlentities($_POST['price']);
$Body = <<<EOD
<br><hr><br>
Name: $Name<br>
Email: $email<br>
Phone: $Phone<br>
Product:$item1, $item2,$item3<br>
Price: $Price<br>
EOD;
$headers = "From: $email\r\n";
$headers .= "content-type: text/html\r\n";
$succes = mail($webmaster, $emailsubject, $Body, $headers);
if($OK){
header('Location: /thankyourequest.php?id=' . htmlentities($_GET['id']). '');
exit;
}else {
$errorInfo = $Result1->errorInfo();
if(isset($errorInfo[2])){
$error = $errorInfo[2];
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于某种原因,当它被扫描时它返回
From: < [mailto:<]
Sent: 20 April 2015 10:04
To: sales@company.co.uk
Subject: Product Request
Name: <script>alert("xssvuln")</script>
Email: <script>alert("xssvuln")</script>
Phone: <script>alert("xssvuln")</script>
Product:<script>alert("xssvuln")</script>, <script>alert("xssvuln")</script>,<script>alert("xssvuln")</script>
Price: <script>alert("xssvuln")</script>
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我试图用 htmlentities 来防止这种情况发生,但这似乎还不够。欢迎任何帮助以防止这种情况
另请参阅:由 MySQL 列截断引起的 Wordpress 4.2 中存储的 XSS。对输出进行过滤可以防止这些情况。
相反,您想要做的只是使用准备好的语句并裸露数据。(当然,您仍然应该验证数据!确保他们在您要求时给了您一个电子邮件地址,等等。)
当您从数据库中提取数据以显示在网页上时,这就是您想要过滤的时候。并且您想这样做(假设您不需要允许用户提供一些 HTML):
echo htmlentities($row['column'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
Run Code Online (Sandbox Code Playgroud)
ENT_QUOTES | ENT_HTML5和'UTF-8'?我假设您的网页使用的是 HTML5(即<!DOCTYPE html>)并且您的字符集是 UTF-8(即在<meta>标签中以及在 HTTPContent-Type标头中)。如果您使用不同的东西,请进行调整。
我们指定ENT_QUOTES告诉htmlentities()转义引号字符("和')。这对于以下情况很有帮助:
<input type="text" name="field" value="<?php echo $escaped_value; ?>" />
Run Code Online (Sandbox Code Playgroud)
如果你没有指定ENT_QUOTES并且攻击者只需要通过" onload="alert('XSS');值作为值给该表单字段,那么,快!即时客户端代码执行。
我们指定'UTF-8'以便htmlentities()知道要使用的字符集。我们这样做的原因是,正如针对mysql_real_escape_string(),不正确的(尤其是攻击者控制的)字符编码可以击败基于字符串的转义策略。
请注意,这将转义所有 HTML 特殊字符并阻止用户提供任何标记。如果您需要允许一些HTML,我们概述了防止 XSS 的最佳策略。简而言之:
使用树枝?下面的例子是安全的。请注意使用{% autoescape %}块来指定默认策略,但使用|e('html')for覆盖它other_variable:
{% autoescape 'html_attr' %}
<p class="{{ variable }}" id="{{ var_two }}">
{{ other_variable|e('html') }}
</p>
{% endautoescape %}
Run Code Online (Sandbox Code Playgroud)