Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
427 views
in Technique[技术] by (71.8m points)

php - How to prevent cross site scripting

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 [email protected]">
    <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 = '[email protected]';
/*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
";
    $headers .= "content-type: text/html
";
    $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: [email protected]
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>

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.)

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');

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.

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; ?>" />

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.

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.

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:

  • 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 %}
    
  • If all else fails, use HTML Purifier.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...