Вопрос : предотвращает ли XSS (межсайтовый скриптинг) простое использование strip_tags
для любых сохраненных полей ввода и запускает htmlspecialchars
для любого отображаемого вывода … и предотвращает SQL Injection с помощью подготовленных инструкций PHP PDO?
Вот пример:
// INPUT: Input a persons favorite color and save to database // this should prevent SQL injection ( by using prepared statement) // and help prevent XSS (by using strip_tags) $sql = 'INSERT INTO TABLE favorite (person_name, color) VALUES (?,?)'; $sth = $conn->prepare($sql); $sth->execute(array(strip_tags($_POST['person_name']), strip_tags($_POST['color']))); // OUTPUT: Output a persons favorite color from the database // this should prevent XSS (by using htmlspecialchars) when displaying $sql = 'SELECT color FROM favorite WHERE person_name = ?'; $sth = $conn->prepare($sql); $sth->execute(array(strip_tags($_POST['person_name']))); $sth->setFetchMode(PDO::FETCH_BOTH); while($color = $sth->fetch()){ echo htmlspecialchars($color, ENT_QUOTES, 'UTF-8'); }
Это еще проще. Просто htmlspecialchars()
(с типом цитаты и набором символов) на пользовательском входе достаточно. strip_tags()
полезен только в том случае, если вы уже хотите дезинформировать данные до обработки / сохранения в базе данных, которые часто не используются в реальном мире. HTML-код не наносит вреда в PHP-источнике, но PHP-код может это сделать, если вы используете eval()
для не-санированного пользовательского ввода или такого злого материала.
Однако это не избавляет вас от инъекций SQL , но это уже другая история.
Обновление : чтобы получить чистый пользовательский ввод из запроса, чтобы избежать магических кавычек в управляемом пользователем входом, вы можете использовать следующую функцию:
function get_string($array, $index, $default = null) { if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) { return get_magic_quotes_gpc() ? stripslashes($value) : $value; } else { return $default; } }
который может использоваться как:
$username = get_string($_POST, "username"); $password = get_string($_POST, "password");
(вы можете сделать simliar для get_number
, get_boolean
, get_array
и т. д.)
Чтобы подготовить SQL-запрос, чтобы избежать инъекций SQL , выполните:
$sql = sprintf( "SELECT id FROM user WHERE username = '%s' AND password = MD5('%s')", mysql_real_escape_string($user), mysql_real_escape_string($password) );
Чтобы отображать управляемые пользователем входные данные, чтобы избежать XSS, выполните следующие действия:
echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
Это зависит от того, где и как вы хотите использовать пользовательские данные. Вам нужно знать контекст, в который вы хотите вставить свои данные, и метасимволы этого контекста.
Если вы просто хотите разрешить пользователю htmlspecialchars
текст на свой сайт, достаточно htmlspecialchars
чтобы избежать метасимволов HTML. Но если вы хотите разрешить определенный HTML или хотите вставлять пользовательские данные в существующие HTML-элементы (например, URL-адрес в элемент A
/ IMG
), htmlspecialchars
недостаточно, поскольку вы больше не находитесь в контексте HTML, но в контексте URL.
Таким образом, <script>alert("xss")</script>
в поле URL-адреса изображения даст:
<img src="<script>alert("xss")</script>" />
Но ввод javascript:alert("xss")
будет успешным:
<img src="javascript:alert("xss")" />
Здесь вы должны взглянуть на сказочный чит-лист XSS (Cross Site Scripting), чтобы узнать, в каких контекстах могут быть введены ваши пользовательские данные.
strip_tags не требуется. В большинстве случаев strip_tags просто раздражает, потому что некоторые из ваших пользователей могут использовать <
и >
в своих текстах. Просто используйте htmlspecialchars (или htmlentities, если хотите), прежде чем эхо текста в браузере.
(Не забудьте mysql_real_esacpe_string, прежде чем вставлять что-либо в вашу базу данных!)
Общее правило / meme – «Input Filter, Escape Output». Использование strip_tags
на вашем входе для удаления любого HTML – хорошая идея для фильтрации ввода, но вы должны быть максимально строгими в том, что вы позволяете. Например, если входной параметр должен быть только целым числом, принимать только числовой ввод и всегда преобразовывать его в целое число, прежде чем что- либо делать с ним. Хорошо проверенная библиотека фильтрации входных данных поможет вам многое здесь; тот, который не является специфическим для конкретной структуры, – это Inspekt (который я написал, поэтому я немного предвзятый).
Для вывода htmlspecialchars
должны быть способны избежать атак XSS, но только если вы передадите правильные параметры . Вы должны передать стиль экранирования цитаты и кодировку.
В общем, это должно устранить атаки XSS:
$safer_str = htmlspecialchars($unsafe_str, ENT_QUOTES, 'UTF-8');
Не передавая ENT_QUOTES
в качестве второго параметра, символы одной кавычки не кодируются. Кроме того, атаки XSS были продемонстрированы, когда правильная кодировка не передана (как правило, UTF-8 будет достаточным). htmlspecialchars
следует всегда вызывать с помощью ENT_QUOTES и параметра charset.
Обратите внимание, что PHP 5.2.12 содержит исправление для многобайтовой атаки XSS .
Вы можете найти порт OWASP ESAPI PHP интересным и полезным, хотя версия PHP не является полной AFAIK.
Да, используя подготовленные PDO заявления, защищает от SQL-инъекции. Атака SQL-инъекций основана на том факте, что данные, представленные злоумышленником, рассматриваются как часть запроса. Например, злоумышленник представляет строку «a» или «a» = «a» в качестве своего пароля. Вместо того, чтобы вся строка сравнивалась с паролями в базе данных, она включается в запрос, поэтому запрос становится «SELECT * FROM users WHERE login = 'joe' AND password = 'a' или 'a' = 'a' ». Часть входа атакующего интерпретируется как часть запроса. Однако в случае подготовленных инструкций вы специально указываете SQL-движок, какая часть запроса и какая часть данных (путем установки параметров), поэтому такая путаница невозможна.
Нет, использование strip_tags не всегда защитит вас от межсайтового скриптинга. Рассмотрим следующий пример. Скажем, ваша страница содержит:
<script> location.href='newpage_<?php echo strip_tags($_GET['language']); ?>.html'; </script>
Нападающий отправляет запрос с «языком», установленным в «», «somethingevil ();»). strip_tags () возвращает эти данные как есть (в нем нет меток). Созданный код страницы становится:
<script> location.href='newpage_';somethingevil();'.html'; </script>
somethingevil () выполняется. Замените somethingevil () фактическим кодом эксплойта XSS.
Ваш последний пример с htmlspecialchars () будет защищать от этого, потому что он избежит одиночных кавычек. Однако я видел даже более странные случаи данных, предоставленных пользователем, внутри кода JavaScript, где он даже не входит в строку с кавычками. Я думаю, что это было в имени переменной или функции. В этом последнем случае вряд ли удастся ускользнуть. Я верю, что лучше избегать использования пользовательского ввода для генерации кода JavaScript.
Простой ответ: нет
Более длительный ответ: Есть способы вставить xss, что PHP strip_stags не может избежать.
Для лучшей защиты попробуйте очиститель HTML