Jeff实际上在Sanitize HTML中发布了有关此内容的文章。 但是他的示例在C#中,而实际上我对Java版本更感兴趣。 有没有人有更好的Java版本? 他的示例足以将直接从C#转换为Java吗?
[更新]我悬赏这个问题,因为当我问这个问题时,SO不如今天(*)受欢迎。 至于与安全相关的任何事物,研究的人越多,它就越好!
(*)实际上,我认为它仍处于封闭测试阶段
不要使用正则表达式执行此操作。请记住,您并不是仅仅针对有效的HTML进行保护;您可以防止Web浏览器创建的DOM。可以诱骗浏览器很容易地从无效的HTML生成有效的DOM。
例如,请参阅此混淆的XSS攻击列表。您准备好准备一个正则表达式来防止这种针对IE6 / 7/8的Yahoo和Hotmail的真实攻击吗?
1 2 3 4 5
| <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")">
</BODY></HTML> |
如何在IE6上进行这种攻击?
1
| <TABLE BACKGROUND="javascript:alert('XSS')"> |
该网站未列出的攻击情况如何? Jeff的方法存在的问题是,它不是声称的白名单。正如该页面上的某人熟练地指出:
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调用更容易的是:
1 2 3 4 5 6 7
| 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();
} |
我不认为使用正则表达式是查找所有可疑代码的最佳方法。正则表达式在处理损坏的HTML时特别容易被欺骗。例如,在Sanitize HTML链接中列出的正则表达式将无法删除在元素名称和属性" href"之间具有属性的所有" a"元素:
删除恶意代码的一种更强大的方法是依靠可以处理所有HTML文档(Tidy,TagSoup等)的XML分析器,并选择要使用XPath表达式删除的元素。将HTML文档解析为DOM文档后,即可轻松安全地找到要复制的元素。使用XSLT甚至很容易做到。
我从NoScript最好的Anti-XSS插件中提取了它的Regex:
工作完美:
1
| <[^\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是一个定期更新的插件
这将验证字符,数字,空格以及标记。
如果您想增加风险,可以添加更多标签,例如
1 2 3
| ^(\s|\w|\d||
<ul>
|<\ul>)*?$ |
这个问题完美地说明了计算理论研究的巨大应用。 计算理论是一个致力于产生计算机数学表示形式的领域。
计算理论中一些最深刻的研究是证明各种语言之间关系的证明。
计算理论家已经证明的一些语言关系包括:
这表明上下文无关语言比常规语言更强大。 因此,如果一种语言明确地是上下文无关的(上下文无关且不是常规的),则任何正则表达式都不可能识别它。
JavaScript至少没有上下文限制,因此我们百分百确定地知道,设计一个能够捕获所有XSS的正则表达式(regex)是一项不可能的任务。
一个旧线程,但这可能对其他用户有用。有一个用于php的维护的安全层工具:https://github.com/PHPIDS/它基于一组正则表达式,您可以在这里找到:
https://github.com/PHPIDS/PHPIDS/blob/master/lib/IDS/default_filter.xml
[\s\w\.]*。如果不匹配,则说明您拥有XSS。也许。请注意,此表达式仅允许使用字母,数字和句点。出于对XSS的担心,它避免了所有符号,甚至是有用的符号。允许&后,您就不必担心了。仅用&替换&的所有实例是不够的。太难以信任了:P。显然,这将禁止使用许多合法的文本(您可以将所有不匹配的字符替换为!或其他内容),但是我认为它将杀死XSS。
仅将其解析为html并生成新的html的想法可能更好。
使用jeffs代码的最大问题是@,目前尚不可用。
如果需要,我可能会从jeffs代码中获取"原始"正则表达式并将其粘贴到
http://www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html
并看到需要逃生的东西逃脱然后再使用。
考虑到此正则表达式的用法,我个人将确保自己完全了解自己在做什么,如果我不成功,那么为什么以及在复制/粘贴任何内容(如其他答案)试图为您提供帮助之前会产生什么后果。
(对于任何复制/粘贴来说,这可能都是不错的建议)