Как предотвратить межсайтовый скриптинг

У меня есть следующая форма, которую пользователи заполняют:

<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="eg 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="eg 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> 

После отправки формы происходит следующее:

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

По какой-то причине при сканировании возвращается

 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, как бы то ни было, этого недостаточно. Любая помощь приветствуется, чтобы предотвратить это

Не пытайтесь предотвратить атаки XSS во время ввода. Всегда выходите на выход.

См. Также: Сохраненный XSS в WordPress 4.2, вызванный усечением столбца MySQL . Фильтрация на выходе предотвратила бы эти условия.

Вместо этого вы хотите просто использовать подготовленные инструкции и хранить данные голыми. (Вы должны все же проверить данные, конечно! Убедитесь, что они дали вам адрес электронной почты, когда вы попросили его, и т. Д.)

Когда вы извлекаете данные из базы данных для отображения на веб-странице, то есть когда вы хотите фильтровать. И вы хотите сделать это так (предполагая, что вам не нужно позволять пользователям предоставлять некоторый HTML-код):

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

Почему ENT_QUOTES | ENT_HTML5 ENT_QUOTES | ENT_HTML5 и 'UTF-8' ?

Я предполагаю, что ваша веб-страница использует HTML5 (т.е. <!DOCTYPE html> ), а ваша кодировка – UTF-8 (т. <meta> теге <meta> а также в заголовке HTTP Content-Type ). Пожалуйста, отрегулируйте, если вы используете что-то другое.

Мы указываем ENT_QUOTES чтобы сообщить htmlentities() чтобы избежать символов кавычек ( " и ' ). Это полезно для ситуаций, таких как:

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

Если вам не удалось указать ENT_QUOTES а злоумышленнику просто нужно передать " onload="alert('XSS'); как значение для этого поля формы и, прежде всего! Выполнение мгновенного клиентского кода.

Мы указываем 'UTF-8' поэтому htmlentities() знает, с каким персонажем работать. Причина, по которой мы это делаем, демонстрирует, что против mysql_real_escape_string() некорректная (особенно mysql_real_escape_string() ) кодировка символов может победить стратегии экранирования на основе строк.

Обратите внимание, что это позволит избежать всех специальных символов HTML и запретить пользователям предоставлять любую разметку. Если вам нужно разрешить некоторый HTML, мы наметили лучшие стратегии предотвращения XSS . В двух словах:

  • Использование Twig? Нижеприведенный пример безопасен. Обратите внимание на использование блоков {% autoescape %} для указания стратегии по умолчанию, но переопределяя ее с помощью |e('html') для other_variable :

     {% autoescape 'html_attr' %} <p class="{{ variable }}" id="{{ var_two }}"> {{ other_variable|e('html') }} </p> {% endautoescape %} 
  • Если все остальное не удается, используйте средство очистки HTML .

это называется проблемой безопасности. Межсайтовый скриптинг, у вас есть много способов избежать этого,

Каков наилучший метод для дезинфекции пользовательского ввода с помощью PHP?

Например, если у вас есть возможность ввести адрес электронной почты, вы должны проверить его, как показано ниже:

 <?php $email = filter_var($_POST['username'], FILTER_SANITIZE_EMAIL); ?> 

Если есть возможность ввести строку, вы должны подтвердить, как показано ниже.

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

В вашем случае вам нужно сделать что-то вроде ниже

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

Вместо вышеперечисленного следуйте методу очистки фильтра:

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