如何防止跨站点脚本 [英] How to prevent cross site scripting

查看:115
本文介绍了如何防止跨站点脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我填写了以下用户表格:

I have the following form that users fill in:

<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>&nbsp;</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>

提交表单后,将发生以下情况:

Once the form is submitted the following happens:

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];
        }
}
}

由于某种原因,在扫描时它会返回

For some reason when it is scan it returns

From: &lt [mailto:&lt] 
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>

如您所见,我试图用htmlentities阻止这种情况,但这似乎还不够. 欢迎任何帮助以防止出现这种情况

As you can see I've tried to prevent this with htmlentities how ever that does not seem to be enough. Any help welcome to prevent this

推荐答案

请勿在输入期间尝试防止XSS攻击.始终在输出时转义.

另请参见:由于MySQL列被截断而在Wordpress 4.2中存储了XSS .对输出进行过滤会避免这些情况.

Do not attempt to prevent XSS attacks during input. Always escape on output.

See also: Stored XSS in Wordpress 4.2 caused by MySQL column truncation. Filtering on output would have prevented these conditions.

相反,您要做的只是使用准备好的语句并将数据裸存储. (当然,您仍然应该验证数据!请确保他们在您要求输入电子邮件地址时给了您一个电子邮件地址,等等.)

Instead, what you want to do is just use prepared statements and store the data naked. (You should still validate the data of course! Make sure they've given you an email address when you asked for one, etc.)

从数据库中提取数据以显示在网页上时,即要过滤时.并且您想要这样做(假设您不需要允许用户提供一些HTML):

When you are pulling the data from the database to display on a webpage, that is when you want to filter. And you want to do it like this (assuming you don't need to allow users to provide some HTML):

echo htmlentities($row['column'], ENT_QUOTES | ENT_HTML5, 'UTF-8');

为什么ENT_QUOTES | ENT_HTML5'UTF-8'?

我假设您的网页使用的是HTML5(即<!DOCTYPE html>),而您的字符集为UTF-8(即在<meta>标记以及HTTP Content-Type标头中).如果两者都使用其他内容,请进行调整.

Why ENT_QUOTES | ENT_HTML5 and 'UTF-8'?

I'm assuming your web page is using HTML5 (i.e. <!DOCTYPE html>) and your charset is UTF-8 (i.e. in the <meta> tag as well as in the HTTP Content-Type header). Please adjust if you're using something different for either.

我们指定ENT_QUOTES告诉htmlentities()转义引号字符("').这对于以下情况很有用:

We specify ENT_QUOTES to tell htmlentities() to escape quote characters (" and '). This is helpful for situations such as:

<input type="text" name="field" value="<?php echo $escaped_value; ?>" />

如果您未能指定ENT_QUOTES并且攻击者只需要将" onload="alert('XSS');作为值传递给该表单字段,就可以了!即时客户端代码执行.

If you failed to specify ENT_QUOTES and attacker simply needs to pass " onload="alert('XSS'); as a value to that form field and, presto! Instant client-side code execution.

我们指定'UTF-8',所以htmlentities()知道要使用的字符集.我们这样做的原因是,如针对mysql_real_escape_string() 演示了,错误的(尤其是由攻击者控制的)字符编码可能会失败基于字符串的转义策略.

We specify 'UTF-8' so htmlentities() knows what character set to work with. The reason we do this is, as demonstrated against mysql_real_escape_string(), an incorrect (especially attacker-controlled) character encoding can defeat string-based escaping strategies.

请注意,这将转义所有HTML特殊字符,并阻止用户提供任何标记.如果您需要允许某些 HTML,我们概述了防止XSS的最佳策略.简而言之:

Note that this will escape all HTML special characters and prevent users from supplying any markup. If you need to allow some HTML, we outlined the best strategies for preventing XSS. In a nutshell:

  • 使用树枝吗?以下示例是安全的.请注意,使用{% autoescape %}块指定默认策略,但对于other_variable,将其用|e('html')覆盖:

  • Using Twig? The below example is safe. Note the use of {% autoescape %} blocks for specifying the default strategy, but overriding it with |e('html') for other_variable:

{% autoescape 'html_attr' %}
<p class="{{ variable }}" id="{{ var_two }}">
    {{ other_variable|e('html') }}
</p>
{% endautoescape %}

  • 如果其他所有方法均失败,请使用 HTML净化器.
  • If all else fails, use HTML Purifier.
  • 这篇关于如何防止跨站点脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆