Когда дело доходит до запросов к базе данных, всегда старайтесь использовать подготовленные параметризованные запросы. Библиотеки mysqli
и PDO
поддерживают это. Это намного безопаснее, чем использование функций экранирования, таких как mysql_real_escape_string
.
Да, mysql_real_escape_string
по сути, это просто функция экранирования строки. Это не волшебная пуля. Все, что он будет делать, - это экранировать опасные символы, чтобы их можно было безопасно использовать в одной строке запроса. Однако, если вы не дезинфицируете свои входные данные заранее, вы будете уязвимы для определенных векторов атак.
Представьте себе следующий SQL:
$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);
Вы должны увидеть, что это уязвимо для использования.
Представьте, что id
параметр содержит общий вектор атаки:
1 OR 1=1
Здесь нет опасных символов для кодирования, поэтому он будет проходить прямо через экранирующий фильтр. Оставляя нас:
SELECT fields FROM table WHERE id= 1 OR 1=1
Это прекрасный вектор SQL-инъекций, позволяющий злоумышленнику вернуть все строки. Или
1 or is_admin=1 order by id limit 1
который производит
SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1
Это позволяет злоумышленнику вернуть данные первого администратора в этом полностью вымышленном примере.
Хотя эти функции полезны, их следует использовать с осторожностью. Вам необходимо убедиться, что все веб-входы в какой-то степени проверены. В этом случае мы видим, что нас могут использовать, потому что мы не проверили, что переменная, которую мы использовали в качестве числа, на самом деле была числовой. В PHP вам следует широко использовать набор функций для проверки того, что входные данные являются целыми числами, числами с плавающей запятой, буквенно-цифровыми и т. Д. Но когда дело доходит до SQL, обратите внимание на значение подготовленного оператора. Приведенный выше код был бы безопасным, если бы это был подготовленный оператор, поскольку функции базы данных знали бы, что 1 OR 1=1
это недопустимый литерал.
Что касается htmlspecialchars()
. Это собственное минное поле.
Реальная проблема в PHP состоит в том, что в нем есть целый набор различных функций экранирования, связанных с HTML, и нет четких указаний о том, какие именно функции что делают.
Во-первых, если вы находитесь внутри тега HTML, у вас большие проблемы. смотреть на
echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';
Мы уже внутри HTML-тега, поэтому нам не нужны <или>, чтобы делать что-нибудь опасное. Наш вектор атаки может быть простоjavascript:alert(document.cookie)
Теперь результирующий HTML выглядит как
<img src= "javascript:alert(document.cookie)" />
Атака проходит прямо.
Становится хуже. Зачем? потому что htmlspecialchars
(при таком вызове) кодирует только двойные кавычки, а не одиночные. Итак, если бы у нас было
echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";
Наш злой злоумышленник теперь может вводить совершенно новые параметры
pic.png' onclick='location.href=xxx' onmouseover='...
дает нам
<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />
В этих случаях волшебной пули нет, вам просто нужно самостоятельно обработать ввод. Если вы попытаетесь отфильтровать плохие символы, у вас наверняка ничего не получится. Используйте белый список и пропускайте только те символы, которые подходят. Взгляните на шпаргалку XSS, чтобы увидеть, насколько разнообразными могут быть векторы.
Даже если вы используете htmlspecialchars($string)
не HTML-теги, вы все равно уязвимы для векторов атаки с использованием многобайтовых кодировок.
Наиболее эффективным может быть использование комбинации mb_convert_encoding и htmlentities следующим образом.
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');
Даже это оставляет IE6 уязвимым из-за способа обработки UTF. Однако вы можете вернуться к более ограниченной кодировке, такой как ISO-8859-1, пока использование IE6 не прекратится.
Для более глубокого изучения многобайтовых проблем см. Https://stackoverflow.com/a/12118602/1820.