Джефф написал об этом в Очистить HTML. Но его пример написан на C#, и меня больше интересует версия для Java. У кого-нибудь есть версия получше для Явы? Достаточно ли хорош его пример, чтобы просто конвертировать прямо с C# на Java?
[Обновление] Я назначил награду за этот вопрос, потому что SO не был таким популярным, когда я задал вопрос, как сегодня (*). Что касается всего, что связано с безопасностью, чем больше людей в него заглядывают, тем лучше!
(*) На самом деле, я думаю, что это все еще было в закрытой бета-версии




Самая большая проблема при использовании кода jeffs - это @, который в настоящее время недоступен.
Я бы, вероятно, просто взял "сырое" регулярное выражение из кода Jeffs, если бы он мне понадобился, и вставил его в
http://www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html
и увидеть, как вещи, нуждающиеся в побеге, сбегают, а затем использовать это.
Принимая во внимание использование этого регулярного выражения, я бы лично удостоверился, что точно понимаю, что я делаю, почему и какие будут последствия, если я не добьюсь успеха, прежде чем копировать / вставлять что-либо, как и другие ответы, которые пытаются вам помочь.
(Это, вероятно, довольно хороший совет для любого копирования / вставки)
Я не уверен, что использование регулярного выражения - лучший способ найти весь подозрительный код. Регулярные выражения довольно легко обмануть, особенно при работе с неработающим HTML. Например, регулярное выражение, указанное в ссылке «Очистить HTML», не удалит все элементы «a», у которых есть атрибут между именем элемента и атрибутом «href»:
Более надежный способ удаления вредоносного кода - полагаться на анализатор XML, который может обрабатывать все виды HTML-документов (Tidy, TagSoup и т. д.), И выбирать элементы для удаления с помощью выражения XPath. После того, как HTML-документ преобразован в DOM-документ, элементы, которые нужно изменить, можно будет легко и безопасно найти. Это легко сделать даже с помощью XSLT.
+1, см. Мой ответ о реальном Java API, который делает именно это
Не делайте этого с регулярными выражениями. Помните, что вы защищаете не только от действительного HTML; вы защищаете от DOM, создаваемого веб-браузерами. Браузеры можно легко обманом заставить создать действительную модель DOM из недействительного HTML.
Например, см. Этот список запутанные XSS-атаки. Готовы ли вы настроить регулярное выражение, чтобы предотвратить настоящую атаку на Yahoo и Hotmail в IE6 / 7/8?
<HTML><BODY>
<?xml:namespace prefix = "t" ns = "urn:schemas-microsoft-com:time">
<?import namespace = "t" implementation = "#default#time2">
<t:set attributeName = "innerHTML" to = "XSS<SCRIPT DEFER>alert("XSS")</SCRIPT>">
</BODY></HTML>
Как насчет этой атаки, которая работает в IE6?
<TABLE BACKGROUND = "javascript:alert('XSS')">
Как насчет атак, которых нет на этом сайте? Проблема подхода Джеффа в том, что это не белый список, как утверждается. Кто-то из эта страница умело отмечает:
The problem with it, is that the html must be clean. There are cases where you can pass in hacked html, and it won't match it, in which case it'll return the hacked html string as it won't match anything to replace. This isn't strictly whitelisting.
Я бы предложил специальный инструмент, такой как AntiSamy. Он работает, фактически анализируя HTML, а затем просматривая DOM и удаляя все, что не находится в белом списке настраиваемый. Основное отличие - это возможность корректно обрабатывать искаженный HTML.
Самое приятное то, что это фактически модульные тесты для всех XSS-атак на указанном выше сайте. Кроме того, что может быть проще, чем этот вызов API:
public String toSafeHtml(String html) throws ScanException, PolicyException {
Policy policy = Policy.getInstance(POLICY_FILE);
AntiSamy antiSamy = new AntiSamy();
CleanResults cleanResults = antiSamy.scan(html, policy);
return cleanResults.getCleanHTML().trim();
}
AntiSamy отлично смотрится! Кроме того, использование разных политик - хорошая идея, поскольку они сохраняют правила очистки вне кода, что упрощает обслуживание. Это явно очень хороший подход. Престижность.
+1. Вы не можете надежно обрабатывать HTML с помощью регулярного выражения. Разбор его в легко фильтруемой модели DOM с последующим использованием заведомо хорошей сериализации - гораздо более разумный подход.
Мне очень нравится этот ответ, поскольку он не дает прямого ответа на вопрос, а вместо этого решает проблему!
Ваша вторая ссылка мертва.
[\s\w\.]*. Если не совпадает, у вас есть XSS. Может быть. Обратите внимание, что это выражение допускает только буквы, цифры и точки. Он избегает всех символов, даже полезных, из-за страха перед XSS. Как только вы позволите &, у вас появятся заботы. И простой замены всех экземпляров & на & недостаточно. Слишком сложно доверять: P. Очевидно, это запретит использование большого количества легитимного текста (вы можете просто заменить все несовпадающие символы на! Или что-то в этом роде), но я думаю, что это убьет XSS.
Идея просто разобрать его как html и сгенерировать новый html, вероятно, лучше.
^(\s|\w|\d|<br>)*?$
Это проверит символы, цифры, пробелы, а также тег <br>.
Если вы хотите большего риска, вы можете добавить больше тегов, например
^(\s|\w|\d|<br>|<ul>|<\ul>)*?$
Я извлек из NoScript лучший аддон Anti-XSS, вот его Regex: Безупречная работа:
<[^\w<>]*(?:[^<>"'\s]*:)?[^\w<>]*(?:\W*s\W*c\W*r\W*i\W*p\W*t|\W*f\W*o\W*r\W*m|\W*s\W*t\W*y\W*l\W*e|\W*s\W*v\W*g|\W*m\W*a\W*r\W*q\W*u\W*e\W*e|(?:\W*l\W*i\W*n\W*k|\W*o\W*b\W*j\W*e\W*c\W*t|\W*e\W*m\W*b\W*e\W*d|\W*a\W*p\W*p\W*l\W*e\W*t|\W*p\W*a\W*r\W*a\W*m|\W*i?\W*f\W*r\W*a\W*m\W*e|\W*b\W*a\W*s\W*e|\W*b\W*o\W*d\W*y|\W*m\W*e\W*t\W*a|\W*i\W*m\W*a?\W*g\W*e?|\W*v\W*i\W*d\W*e\W*o|\W*a\W*u\W*d\W*i\W*o|\W*b\W*i\W*n\W*d\W*i\W*n\W*g\W*s|\W*s\W*e\W*t|\W*i\W*s\W*i\W*n\W*d\W*e\W*x|\W*a\W*n\W*i\W*m\W*a\W*t\W*e)[^>\w])|(?:<\w[\s\S]*[\s\0/]|['"])(?:formaction|style|background|src|lowsrc|ping|on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)?|op)|i(?:s(?:c(?:hargingtimechange|onnect(?:ing|ed))|abled)|aling)|ata(?:setc(?:omplete|hanged)|(?:availabl|chang)e|error)|urationchange|ownloading|blclick)|Moz(?:M(?:agnifyGesture(?:Update|Start)?|ouse(?:PixelScroll|Hittest))|S(?:wipeGesture(?:Update|Start|End)?|crolledAreaChanged)|(?:(?:Press)?TapGestur|BeforeResiz)e|EdgeUI(?:C(?:omplet|ancel)|Start)ed|RotateGesture(?:Update|Start)?|A(?:udioAvailable|fterPaint))|c(?:o(?:m(?:p(?:osition(?:update|start|end)|lete)|mand(?:update)?)|n(?:t(?:rolselect|extmenu)|nect(?:ing|ed))|py)|a(?:(?:llschang|ch)ed|nplay(?:through)?|rdstatechange)|h(?:(?:arging(?:time)?ch)?ange|ecking)|(?:fstate|ell)change|u(?:echange|t)|l(?:ick|ose))|m(?:o(?:z(?:pointerlock(?:change|error)|(?:orientation|time)change|fullscreen(?:change|error)|network(?:down|up)load)|use(?:(?:lea|mo)ve|o(?:ver|ut)|enter|wheel|down|up)|ve(?:start|end)?)|essage|ark)|s(?:t(?:a(?:t(?:uschanged|echange)|lled|rt)|k(?:sessione|comma)nd|op)|e(?:ek(?:complete|ing|ed)|(?:lec(?:tstar)?)?t|n(?:ding|t))|u(?:ccess|spend|bmit)|peech(?:start|end)|ound(?:start|end)|croll|how)|b(?:e(?:for(?:e(?:(?:scriptexecu|activa)te|u(?:nload|pdate)|p(?:aste|rint)|c(?:opy|ut)|editfocus)|deactivate)|gin(?:Event)?)|oun(?:dary|ce)|l(?:ocked|ur)|roadcast|usy)|a(?:n(?:imation(?:iteration|start|end)|tennastatechange)|fter(?:(?:scriptexecu|upda)te|print)|udio(?:process|start|end)|d(?:apteradded|dtrack)|ctivate|lerting|bort)|DOM(?:Node(?:Inserted(?:IntoDocument)?|Removed(?:FromDocument)?)|(?:CharacterData|Subtree)Modified|A(?:ttrModified|ctivate)|Focus(?:Out|In)|MouseScroll)|r(?:e(?:s(?:u(?:m(?:ing|e)|lt)|ize|et)|adystatechange|pea(?:tEven)?t|movetrack|trieving|ceived)|ow(?:s(?:inserted|delete)|e(?:nter|xit))|atechange)|p(?:op(?:up(?:hid(?:den|ing)|show(?:ing|n))|state)|a(?:ge(?:hide|show)|(?:st|us)e|int)|ro(?:pertychange|gress)|lay(?:ing)?)|t(?:ouch(?:(?:lea|mo)ve|en(?:ter|d)|cancel|start)|ime(?:update|out)|ransitionend|ext)|u(?:s(?:erproximity|sdreceived)|p(?:gradeneeded|dateready)|n(?:derflow|load))|f(?:o(?:rm(?:change|input)|cus(?:out|in)?)|i(?:lterchange|nish)|ailed)|l(?:o(?:ad(?:e(?:d(?:meta)?data|nd)|start)?|secapture)|evelchange|y)|g(?:amepad(?:(?:dis)?connected|button(?:down|up)|axismove)|et)|e(?:n(?:d(?:Event|ed)?|abled|ter)|rror(?:update)?|mptied|xit)|i(?:cc(?:cardlockerror|infochange)|n(?:coming|valid|put))|o(?:(?:(?:ff|n)lin|bsolet)e|verflow(?:changed)?|pen)|SVG(?:(?:Unl|L)oad|Resize|Scroll|Abort|Error|Zoom)|h(?:e(?:adphoneschange|l[dp])|ashchange|olding)|v(?:o(?:lum|ic)e|ersion)change|w(?:a(?:it|rn)ing|heel)|key(?:press|down|up)|(?:AppComman|Loa)d|no(?:update|match)|Request|zoom))[\s\0]*=
Тест: http://regex101.com/r/rV7zK8
Я думаю, что он блокирует 99% XSS, потому что он является частью NoScript, дополнения, которое регулярно обновляется.
не компилируется в java: вызвано: java.util.regex.PatternSyntaxException: недопустимая восьмеричная escape-последовательность рядом с индексом 525
Я попробовал один чрезвычайно простой бит XSS в этой тестовой строке regex101 и сломал его с первой попытки. Не очень безупречно. Все, что я сделал, это добавил ссылку с javascript: href.
Старая ветка, но, возможно, это будет полезно для других пользователей. Для php существует поддерживаемый инструмент уровня безопасности: https://github.com/PHPIDS/ Он основан на наборе регулярных выражений, которые вы можете найти здесь:
https://github.com/PHPIDS/PHPIDS/blob/master/lib/IDS/default_filter.xml
Этот вопрос прекрасно иллюстрирует большое применение теории вычислений. Теория вычислений - это область, в которой основное внимание уделяется созданию и изучению математических представлений для вычислений.
Некоторые из наиболее глубоких исследований теории вычислений включают доказательства, иллюстрирующие взаимосвязь различных языков.
Некоторые из языковых отношений, которые доказали теоретики вычислений, включают:
Это показывает, что контекстно-свободные языки строго более мощные, чем обычные языки. Таким образом, если язык явно контекстно-свободный (контекстно-свободный и не регулярный), то регулярное выражение любой не может его распознать.
JavaScript, по крайней мере, не зависит от контекста, поэтому мы знаем со стопроцентной уверенностью, что создание регулярного выражения (regex), способного уловить все XSS, является математически невыполнимой задачей.
Для java я использовал следующее регулярное выражение с replaceAll и работал у меня
value.replaceAll("(?i)(\b)(on\S+)(\s*)=|javascript:|(<\s*)(/*)script|style(\s*)=|(<\s*)meta", "");
Добавлен (? I), чтобы игнорировать регистр букв.
Что еще тебе нужно? Мне нравятся ответы.