Jeff 实际上在Sanitize HTML中对此进行了发布。但他的例子是用 C# 编写的,而我实际上对 Java 版本更感兴趣。有人有更好的Java版本吗?他的示例是否足以直接从 C# 转换为 Java?
[更新] 我对这个问题给予了赏金,因为当我问这个问题时,SO 并不像今天那样受欢迎(*)。和安全有关的事情,越多人看越好!
(*) 其实我觉得还是内测
Jeff 实际上在Sanitize HTML中对此进行了发布。但他的例子是用 C# 编写的,而我实际上对 Java 版本更感兴趣。有人有更好的Java版本吗?他的示例是否足以直接从 C# 转换为 Java?
[更新] 我对这个问题给予了赏金,因为当我问这个问题时,SO 并不像今天那样受欢迎(*)。和安全有关的事情,越多人看越好!
(*) 其实我觉得还是内测
不要使用正则表达式执行此操作。请记住,您保护的不仅仅是有效的 HTML;您正在保护 Web 浏览器创建的 DOM。浏览器很容易被欺骗,从无效的 HTML 生成有效的 DOM。
例如,请参阅此混淆 XSS 攻击列表。您准备好定制一个正则表达式来防止这种对 IE6/7/8上的Yahoo 和 Hotmail的真实攻击吗?
<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')">
本网站未列出的攻击怎么样?Jeff 方法的问题在于它不是一个白名单,正如所声称的那样。正如该页面上的某人熟练地指出的那样:
它的问题是html必须是干净的。在某些情况下,您可以传入被黑的 html,但它不会匹配它,在这种情况下,它将返回被黑的 html 字符串,因为它不会匹配要替换的任何内容。这不是严格的白名单。
我建议使用像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();
}
我从 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 的一部分,NoScript 是一个定期更新的插件
我不相信使用正则表达式是查找所有可疑代码的最佳方法。在处理损坏的 HTML 时,正则表达式很容易被特别欺骗。例如,Sanitize HTML 链接中列出的正则表达式将无法删除所有在元素名称和属性“href”之间具有属性的“a”元素:
<a alt="xss 注入" href="http://www.malicious.com/bad.php" >
删除恶意代码的一种更可靠的方法是依靠可以处理所有类型的 HTML 文档(Tidy、TagSoup 等)的 XML 解析器,并使用 XPath 表达式选择要删除的元素。一旦 HTML 文档被解析为 DOM 文档,就可以轻松安全地找到要删除的元素。使用 XSLT 甚至可以轻松做到这一点。
^(\s|\w|\d|<br>)*?$
这将验证字符、数字、空格以及<br>
标签。如果您想要更多风险,您可以添加更多标签,例如
^(\s|\w|\d|<br>|<ul>|<\ul>)*?$
使用 jeffs 代码的最大问题是当前不可用的 @。
如果需要,我可能会从 jeffs 代码中获取“原始”正则表达式并将其粘贴到
http://www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html
并看到需要逃跑的东西被逃跑了然后使用它。
考虑到这个正则表达式的使用,我个人会确保在复制/粘贴任何内容之前,我完全理解我在做什么,为什么以及如果我没有成功会产生什么后果,就像其他答案试图帮助你一样。
(对于任何复制/粘贴来说,这可能是非常合理的建议)
[\s\w\.]*
. 如果不匹配,则说明您有 XSS。也许。请注意,此表达式仅允许字母、数字和句点。出于对 XSS 的恐惧,它避免了所有符号,甚至是有用的符号。一旦你允许 &,你就会有后顾之忧。仅仅用 & 替换所有的实例&
是不够的。太复杂而无法信任:P。显然,这将禁止大量合法文本(您可以将所有不匹配的字符替换为 ! 或其他内容),但我认为它会杀死 XSS。
将其解析为 html 并生成新的 html 的想法可能更好。
一个旧线程,但也许这对其他用户有用。有一个为 php 维护的安全层工具:https ://github.com/PHPIDS/它基于一组正则表达式,您可以在此处找到:
https://github.com/PHPIDS/PHPIDS/blob/master/lib/IDS/default_filter.xml
对于java,我使用了以下正则表达式和replaceAll,并为我工作
value.replaceAll("(?i)(\\b)(on\\S+)(\\s*)=|javascript:|(<\\s*)(\\/*)script|style(\\s*)=|(<\\s*)meta", "");
添加 (?i) 以忽略字母的大小写。