При получении пользовательского ввода в формах я хочу определить, не содержат ли поля, такие как «имя пользователя» или «адрес», разметку, которая имеет особое значение в XML (каналы RSS) или (X) HTML (при отображении).
Итак, какой из них является правильным способом определения, не содержит ли введенный ввод никаких специальных символов в контексте HTML и XML?
if (mb_strpos($data, '<') === FALSE AND mb_strpos($data, '>') === FALSE)
или
if (htmlspecialchars($data, ENT_NOQUOTES, 'UTF-8') === $data)
или
if (preg_match("/[^\p{L}\-.']/u", $text)) // problem: also caches symbols
Я пропустил что-нибудь еще, например, байтовые последовательности или другие хитрые способы получить разметку вокруг таких вещей, как "javascript:"? Насколько мне известно, все XSS и CSFR атаки требуют <
или >
вокруг значений, чтобы браузер мог выполнить код (по крайней мере, в любом случае из Internet Explorer 6 или более поздней версии) - это правильно?
Я не ищу что-то, чтобы уменьшить или отфильтровать ввод. Я просто хочу найти опасные последовательности символов при использовании в контексте XML или HTML. (strip_tags()
ужасно небезопасен. Как сказано в руководстве, он не проверяет наличие искаженного HTML.)
Обновление
Думаю, мне нужно уточнить, что многие люди принимают этот вопрос за вопрос об элементарной безопасности с помощью "экранирования" или "фильтрации" опасных символов. Это не тот вопрос, и большинство простых ответов в любом случае не решит эту проблему.
Обновление 2: пример
- Пользователь отправляет ввод
if (mb_strpos($data, '<') === FALSE AND mb_strpos($data, '>') === FALSE)
- Я сохраняю это
Теперь, когда данные находятся в моем приложении, я делаю с ними две вещи - 1) отображение в формате, подобном HTML - или 2) отображение внутри элемента формата для редактирования.
Первый безопасен в контексте XML и HTML
<h2><?php print $input; ?></h2>'
<xml><item><?php print $input; ?></item></xml>
Вторая форма более опасна, но все равно должна быть безопасной:
<input value="<?php print htmlspecialchars($input, ENT_QUOTES, 'UTF-8');?>">
Обновление 3: рабочий код
Вы можете загрузить созданную мной суть и запустить код в виде текстового или HTML-ответа, чтобы увидеть, о чем я говорю. Эта простая проверка проходит http://ha.ckers.org XSS Cheat Sheet , и я не могу найти ничего, что делает это все же. (Я игнорирую Internet Explorer 6 и ниже).
Я учредил еще одну награду, чтобы наградить кого-то, кто может показать проблему с этим подходом или слабость в его реализации.
Обновление 4: спросите DOM
Это DOM, который мы хотим защитить - так почему бы просто не спросить его? Ответ Тимура приведет к этому:
function not_markup($string)
{
libxml_use_internal_errors(true);
if ($xml = simplexml_load_string("<root>$string</root>"))
{
return $xml->children()->count() === 0;
}
}
if (not_markup($_POST['title'])) ...