How to prevent cross-site scripting

I have the following form that users fill out:

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

      

After submitting the form, 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 scanning, 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>

      

As you can see, I tried to prevent this with htmlentities, however it is not enough. Any help is appreciated to prevent this.

+3


source to share


2 answers


Don't try to prevent XSS attacks while typing. Always go out.

See also: Saved XSS in Wordpress 4.2 Caused by MySQL Column Truncation . Output filtering would prevent these conditions.

Instead, you want to just use prepared statements and keep the data bare. (You have to check valid details , of course, make sure they gave you the email address when you asked for it, etc.)

When you retrieve data from a database for display on a web page, that is, when you want to filter. And you want to do it like this (assuming you don't need to let users provide some HTML):

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

      

Why ENT_QUOTES | ENT_HTML5

and 'UTF-8'

?

I am assuming that your web page is using HTML5 (i.e. <!DOCTYPE html>

) and your encoding is UTF-8 (i.e. in the tag <meta>

as well as in the HTTP header Content-Type

). Please customize if you are using something different for.



We indicate ENT_QUOTES

inform htmlentities()

to avoid the quotation marks ( "

and '

). This is useful for situations such as:

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

      

If you failed to specify ENT_QUOTES

, and the attacker just needs to pass " onload="alert('XSS');

as a value to this form field and, above all! Executing instant client code.

We will indicate 'UTF-8'

, therefore, he htmlentities()

knows which symbol he will work with. The reason why we do this is againstmysql_real_escape_string()

, an incorrect (especially attacked) character encoding can defeat string-based escaping strategies.

Please note that this will result in all HTML special characters and prevent users from getting any markup. If you need to allow some HTML, we've highlighted the best XSS prevention strategies . In a nutshell:

  • Using Twig? The example below is safe. Note the use of blocks {% autoescape %}

    to specify 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 the HTML Cleaner .
+3


source


this is called a security issue. Cross-site scripting, you have many ways to avoid this,

What is the best method to sanitize user input with PHP?

For example, if you have the option to enter an email address, you should check it as shown below:

<?php

$email = filter_var($_POST['username'], FILTER_SANITIZE_EMAIL);

?>

      

If it is possible to enter a string, you must confirm as shown below



<?php
            $password = trim(filter_var($_POST['password'], FILTER_SANITIZE_STRING));

?>

      

In your case, you need to do something like below

$Name = htmlentities($_POST['Name']);
$email = htmlentities($_POST['email']);

      

Instead of the above, follow the filter disinfection method:

$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$Name = trim(filter_var($_POST['Name'], FILTER_SANITIZE_STRING));

      

0


source







All Articles