Как стать автором
Обновить

Комментарии 80

Достаточно использовать не html-ный формат разметки, а bb-код или альтернативы ему.
Можно заменять в script «си» на «эс» русскую. Тоже и с mousover'ами и т.д.
НЛО прилетело и опубликовало эту надпись здесь
Я имел в виду как способ фильтрации.
НЛО прилетело и опубликовало эту надпись здесь
Чтобы эскейпить пользовательский ввод.
Смысл в том, что это по крайней мере безопасно и не требовательно к ресурсам. На хабра так по крайней мере раньше было сделано. К тому же невалидный мусор будет только там, где постараются кулхацкеры. Это не очень страшно, имхо.
Тут имеется в виду безопасность, а не отображение. То есть если мы поставим ваш код — он просто отобразится, а в случае с «нуль-кодом» он выполнится! Читайте внимательнее…
Несмотря на то как меня заминусовали, я вам отвечу.
Если заменить все вхождения слова script на sсript с русской с то:
1. Если кулхацкер попробует вставить <\0script>… <\script> то скрипт не выполнится. Потому что это будет не тег script, а «невалидный мусор», но безвредный.
2. Если добрый пользователь введет <\0strong>… <\strong> то увидит как и ожидал жирный текст. В статье ведь говорится, что обычные тэги хочется оставить?
Метод ОЧЕНЬ не затратный по ресурсам, если сравнивать его даже с регэкспами.
Что я прочитал недостаточно внимательно?)
Прочитайте еще раз.

1. Что мешает кулхацкеру вставить script с английской буквой?
2. В статье говорится, что если вырезать просто тег script, то \0script будет пропущен парсером и валиден для ИЕ. Значит, несмотря на защиту от тегов, кулхацкер сможет вставить тег в текст
Да… Постараюсь не матюгнуться. Ему мешает, то что весь ввод фильтруется. То есть вы ввели в поле script как надо, а он взял и заменился на сервере. Чудеса)
То есть если слово script было в тексте, читатель его прочитает как надо, потому что человек не отличит с русскую от английской. А браузер отличит и не воспримет это странный тег с запрещенными символами. Вот и все.
Никто на такое не пойдет — это же вывалиться из всех поисковиков, изза полного шлака на страницах.
Спасибо Вам. Идея — класс!

(Интересно, что плюсанувших намного меньше, чем заминусовавших)
Просто не все стали читать до конца и разбираться в его идее.
Я сам не сразу дошел. Но минусов все конечно налепить успели. Думаю выровняется вскоре все.
Да она конечно не очень хорошая, но если нужно быстро и надежно, сойдет=)
НЛО прилетело и опубликовало эту надпись здесь
Да ладно?
$x = str_replace('script', 'sсript', $x);
$x = str_replace('onmouse', 'оnmouse', $x);
$x = str_replace('onclick', 'оnclick', $x); (ну и другие on, если надо)

что еще например?
Я бы еще добавил style на всякий случай. А то всяких position:absolute и margin-top:-500px; понапихают=)
НЛО прилетело и опубликовало эту надпись здесь
Я знаю как работает str_replace и я точно знаю, что так получится безопасно. Я знаю как работают регулярки, с ними тоже получится безопасно, чаще всего, но не очень быстро. Я не знаю как внутри работает тот же simpleXML или strip_tags и не могу гарантировать, что он правильно обработает очередной хак типа \0. Копаться в исходниках? Можно, но сложно. На самом деле я не считаю, что вариант который я предложил — лучший. Я даже не уверен, что он хороший. Но он быстро и надежно работает. Это просто вариант. Плохой или хороший — зависит от ситуации. Вот и все.
НЛО прилетело и опубликовало эту надпись здесь
mb_string никто не отменял.
Мой вариант хорош, когда нужно за 20 минут сделать страничку которую можно комментировать, но не пригоден для серьезных проектов.
Другие варианты пригодны для серьезных проектов, но трудо- и ресурсоемки.
Договорились? =)

НЛО прилетело и опубликовало эту надпись здесь
>Достаточно одного незакрытого «безобидного» <b> — и ага, вся страница дальше изуродована.

Я у себя просто поступаю. Все разрешённые тэги преобразую в BB-код (<b> в [b]), а обратно уже не простой [регексповой] заменой, а конечными автоматами с точным учётом пар. Так что непарные тэги останутся неоттранслированными.

Точно также, например, YouTube-ссылки или YouTube-HTML-вставки транслируются в [youtube]ID ролика[/youtube] и уже из него — в валидный HTML.

Да, а весь неоттранслированный входящий HTML тупо преобразуется по htmlentities.
НЛО прилетело и опубликовало эту надпись здесь
На самом деле, самое прекрасное решение — это отдавать поисковикам (Google bot, Yandex bot и другим, их не так много) нефильтрованный ввод
НЛО прилетело и опубликовало эту надпись здесь
Собственно. тольку упоминания, ничего, как вы выразились, «готового». А то, что есть готовое, тормозит так, что лучше бы его и не было.
И потом, проблема с поисковиками существует, только если сайт посвящен программерской тематике (то есть «безобидный script» может присутствовать на сайте в качестве примера скрипта например). Понятное дела, что для этих случаев кроме как дом-парсером проблему сложно решить, но для всех остальных случаев велосипед изобретать не обязательно, ценой потери ресурсов к тому же.
НЛО прилетело и опубликовало эту надпись здесь
И вообще можно все on заменять=) Потому что есть ведь еще дофига их…
еще примерно такой список:
onabort, onactivate, onafterprint, onafterupdate, onbeforeactivate, onbeforecopy, onbeforecut, onbeforedeactivate, onbeforeeditfocus, onbeforepaste, onbeforeprint, onbeforeunload, onbeforeupdate, onblur, onbounce, oncellchange, onchange, onclick, oncontextmenu, oncontrolselect, oncopy, oncut, ondataavailable, ondatasetchanged, ondatasetcomplete, ondblclick, ondeactivate, ondrag, ondragend, ondragenter, ondragleave, ondragover, ondragstart, ondrop, onerror, onerror, onerrorupdate, onfilterchange, onfinish, onfocus, onfocusin, onfocusout, onhashchange, onhelp, onkeydown, onkeypress, onkeyup, onlayoutcomplete, onload, onload, onlosecapture, onmessage, onmousedown, onmouseenter, onmouseleave, onmousemove, onmouseout, onmouseover, onmouseup, onmousewheel, onmove, onmoveend, onmovestart, onoffline, ononline, onpaste, onprogress, onpropertychange, onreadystatechange, onreadystatechange, onreset, onresize, onresizeend, onresizestart, onrowenter, onrowexit, onrowsdelete, onrowsinserted, onscroll, onselect, onselectionchange, onselectstart, onstart, onstop, onstorage, onstoragecommit, onsubmit, ontimeout, onunload
А не лучше ли заменять <> на html'ные коды?
Это Ящик Пандоры какой-то)

Напоминаю: речь идет о том, чтобы сохранить всю разметку , но пострипать все скрипты.
То есть один крутой парень, когда делал для первого(?) хабра парсер, сделал так=)
в php можно заюзать htmlspecialchars()
Чем она тут поможет?
Это в свою очередь значит, что удаление потенциально опасных элементов с помощью str_replace, preg_replace (PHP), s/<script/.../i (Perl, sed) и прочих replace() функций для других языков не даст желаемых результатов.

Если цитируемое зачем то нужно, то можно просто при выводе этих данных заглушить их функцией htmlspecialchars().
А если нужно html почистить от нечисти, сохранив разметку?
Т.е. чтобы html остался html, только безопасным?))
Ну тогда как ниже написали — strip_tags()
Он имеет в виду, что если пользователь вводить код, то он отображается как код, а не как слова из него.
Читайте внимательнее!
не поможет, надо оставить «правильные» теги, но нечисть можно в любой запихать.
По тексту очевидно же, что разметку нужно сохранить, убрав опасные теги.
Перед удалением тегов из html нормализуйте его с помощью tidy например.
tidy распознаёт нормально <a onclick=«var slash=\»slahing\";" >?
НЛО прилетело и опубликовало эту надпись здесь
Разпознает. Основы JS :)
НЛО прилетело и опубликовало эту надпись здесь
Был не прав. Каюсь
в php есть функция strip_tags()
Отлично вырезает такие теги.
Хех. С помощью этой техники был взломан Живой Журнал когда-то (вернее, запущен XSS-червь). Тут видео и комментарии.
И какие версии этому подвержены?
Не дождавшись ответа решил проверить сам. 6,7,8 подвержены.
Не вижу менее дурацкого способа обезопасить HTML, чем вычищать вручную подстроки script, style и т. д.
s/менее/более/, конечно.
Великий язык Perl :-))
Самый правильный подход, который не допустит подобных дыр в системе фильтрации, это оставлять только то, что явно разрешено, а всё остальное вырезать подчистую.
Жесткаааачь!
Такая хрень вне зависимости от доктайпа?
Ещё много подобных приколов, некоторые не только в IE работают: ha.ckers.org/xss.html
Вы вставляли нулевой символ в теги чтоб их убрать? Вы уж извените, но это как минимум глупо… И оп моему ИЕ правильно делает что игнорирует этот символ в HTML т.к. его участие в разметке и нафиг не нужно
Вообще говоря вот пример корректной работы.

Имеем:
$code = "<h2> Hello! </h2> 
 <h3> My Name</h3> <B>is</b> <\0b>bug</b>";
echo htmlspecialchars(strip_tags($code, "<h2><B>") );

На выходе будет:
<h2> Hello! </h2> My Name <B>is</b> <b>bug</b> 

т.е РНР обработал «опасный» тег как надо… и оставил его…
А теперь посмотрим если в допустимых будет только <h2>

	$code = "<h2> Hello! </h2> 
 <h3> My Name</h3> <B>is</b> <\0b>bug</b>";
	echo htmlspecialchars(strip_tags($code, "<h2>") );


И на выходе имеем
<h2> Hello! </h2> My Name is bug


Теме "+" но особо проблем возникнуть не должно :)
Не всегда нужно вырезать запрещенные теги.
$w = array('& lt;b& gt;', '& lt;/b& gt;', '& lt;p& gt;', '& lt;/p& gt;'); // парсер - лох, пробелы после '&' лишние
$t = array('<b>', '</b>', '<p>', '</p>');
echo str_replace($w, $t, htmlspecialchars($user_html) );

Если нужны теги с параметрами, то можно использовать регулярки. Но это уже мелочи.
Главное, как сказал выше Xeon303, нужно в начале запрещать всё и только потом разрешать то что нужно.
Xeon, сказал.
Самый правильный подход, который не допустит подобных дыр в системе фильтрации, это оставлять только то, что явно разрешено, а всё остальное вырезать подчистую.

А теперь 2 вопроса:
1. Чем strip_tags неудовлетворяет? Он как раз оставляет то что разрешено, и удаляет все что нельзя.
2. Объясните мне смысл вашей фразы?
Главное, как сказал выше Xeon303, нужно в начале запрещать всё и только потом разрешать то что нужно.

Мне кажется вы не поняли смысла того что написал Xeon303, иначе бы не формулировали так предложение…
1. «Не всегда нужно вырезать запрещенные теги.» означает что логика приложения не всегда требует вырезать неразрешенные теги.
Пример:
$source = '<code>#include <stdio.h></code>';

var_dump(strip_tags($source, '<code>'));
=> string(11) "<code>#include </code>"

$w = array('& lt;code& gt;', '& lt;/code& gt;');
$t = array('<code>', '</code>');
var_dump( str_replace($w, $t, htmlspecialchars($source)));
=> string(39) "<code>#include & lt;stdio.h& gt;</code>"

Это я к тому что strip_tags меня вполне устраивает, но не всегда подходит :)

2. Смысл: всё что не разрешено — запрещено. Возможно формулировка хромает, это да…

p.s.: Я показаль альтернативное решение и не говорил что ваш пример плох.
НЛО прилетело и опубликовало эту надпись здесь
тут jevix, а он пропускает только те теги, которые разрешены
от < и > никак не спастись кулхацкерам :))
имеется ввиду & lt; и & gt; (хабрапарсер жжот)
Он какбы отобразил, то что вы написали. То есть вы написали сущность ♪ в коде, а он его так и вывел в браузер. А браузер его уже интерпретировал как сущность. :)

(♪♫♪♫♪ Так-то! :)

А самое интересное в том, что чтобы хабрапарсер не сожрал и мою сущность, я её заэкранировал два раза.
просто: ♪
1 экран: ♪
2 экран: ♪
3 экран: &#x266a;
4 экран: &amp;#x266a;

в предпросмотре третий экран заэкранировался.
У них разная локига! :)
предпросмотр != парсер :)

У предпросмотра второй экран не гасится, а после отправки он гасится! :)
Я об этом уже писал на сппорт, до сих пор не исправили.
НЛО прилетело и опубликовало эту надпись здесь
А не проще просто оставлять НОРМАЛЬНЫЕ теги?
<b>...</b> и другие.
А все остальные преобразовывать по правилу <abс> = & lt;abc& gt;
интересно, почему никто из комментаторов не сказал, что для фильтрации нужно использовать готовые библиотеки, которые знают о существовании не только этого, но и многих других трюков

пример — safehtml
Ещё раз убеждаюсь что единственно надёжный способ фильтрации HTML — это DOM parser + whilelist filtering. DOM парсер не обманешь незакрытыми кавычками и неправильными тегами, ему плевать на твои ухищрению по прятанью скрипта от регулярного выражения. Тег "%00b" входит в множество разрешённых тегов? Нет — вырезать его нафиг. Операция вставки обычно происходит значительно реже считывания, поэтому можно позволить себе запуск более тяжёлого (по сравнению с регулярным выражением) парсера и вырезать всё запрещённое один раз.
bbcode неплохая альтернатива
Объяните, пожалуйста, о каком символе с кодом 0 идёт речь? Я проверил на том, который моим скромным знаниями и должен быть тем самым символом — — но во всех версиях IE никаких проблем не возникло. Что фильтровать то? :)
Скрытый символ был амперсанд#00; — но предварительный просмотр не сработал, а дальше всё пропало, сорри :)
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации