【问题标题】:Best regex to catch XSS (Cross-site Scripting) attack (in Java)?捕获 XSS(跨站点脚本)攻击的最佳正则表达式(在 Java 中)?
【发布时间】:2010-09-06 16:28:15
【问题描述】:

Jeff 实际上在 Sanitize HTML 中发布了有关此问题的信息。但他的例子是用 C# 编写的,而我实际上对 Java 版本更感兴趣。有人有更好的Java版本吗?他的示例是否足以直接从 C# 转换为 Java?

[更新] 我对这个问题给予了赏金,因为当我问这个问题时,SO 并不像今天那样受欢迎 (*)。至于安全相关的东西,越多人看越好!

(*)其实我觉得还是内测

【问题讨论】:

  • 您还需要什么?答案对我来说很好。

标签: java html regex xss


【解决方案1】:

这个问题完美地说明了计算理论研究的一个很好的应用。计算理论是一个专注于生成和研究用于计算的数学表示的领域。

计算理论中一些最深刻的研究包括说明各种语言之间关系的证明。

计算理论家已经证明的一些语言关系包括:

这表明上下文无关语言比常规语言更强大。因此,如果一种语言是明确的上下文无关的(上下文无关而不是正则),那么 any 正则表达式就不可能识别它。

JavaScript 至少是上下文无关的,因此我们有 100% 的把握知道,设计一个能够捕获所有 XSS 的正则表达式 (regex) 在数学上是一项不可能完成的任务。

【讨论】:

    【解决方案2】:

    对于 java,我使用了以下正则表达式和 replaceAll,并为我工作

    value.replaceAll("(?i)(\\b)(on\\S+)(\\s*)=|javascript:|(<\\s*)(\\/*)script|style(\\s*)=|(<\\s*)meta", "");
    

    添加 (?i) 以忽略字母的大小写。

    【讨论】:

      【解决方案3】:

      一个旧线程,但也许这对其他用户有用。有一个为 php 维护的安全层工具:https://github.com/PHPIDS/ 它基于一组正则表达式,您可以在此处找到:

      https://github.com/PHPIDS/PHPIDS/blob/master/lib/IDS/default_filter.xml

      【讨论】:

        【解决方案4】:

        我从 NoScript 中提取了最好的 Anti-XSS 插件,这里是它的正则表达式: 完美无瑕:

        <[^\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 是一个定期更新的插件

        【讨论】:

        • 无法在 java 中编译:原因:java.util.regex.PatternSyntaxException:索引 525 附近的非法八进制转义序列
        • 我在那个 regex101 测试字符串中尝试了一个非常简单的 XSS,并在我第一次尝试时破坏了它。不是很完美。我所做的只是添加一个带有javascript: href 的链接。
        【解决方案5】:
        ^(\s|\w|\d|<br>)*?$ 
        

        这将验证字符、数字、空格以及&lt;br&gt; 标签。 如果您想要更多风险,您可以添加更多标签,例如

        ^(\s|\w|\d|<br>|<ul>|<\ul>)*?$
        

        【讨论】:

          【解决方案6】:

          [\s\w\.]*。如果不匹配,则说明您有 XSS。可能是。请注意,此表达式仅允许字母、数字和句点。出于对 XSS 的恐惧,它避免了所有符号,甚至是有用的符号。一旦你允许 &,你就会有后顾之忧。仅仅用&amp;amp; 替换所有& 的实例是不够的。太复杂而无法信任:P。显然,这将禁止大量合法文本(您可以将所有不匹配的字符替换为 ! 或其他内容),但我认为它会杀死 XSS。

          将其解析为 html 并生成新 html 的想法可能更好。

          【讨论】:

            【解决方案7】:

            不要用正则表达式来做这件事。请记住,您保护的不仅仅是有效的 HTML;您正在保护 Web 浏览器创建的 DOM。浏览器很容易被欺骗,从无效的 HTML 生成有效的 DOM。

            例如,请参阅此obfuscated XSS attacks 列表。您准备好定制一个正则表达式来防止这种现实世界对 IE6/7/8 上的Yahoo and 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&lt;SCRIPT DEFER&gt;alert(&quot;XSS&quot;)&lt;/SCRIPT&gt;">
            </BODY></HTML>
            

            这个在 IE6 上有效的攻击怎么样?

            <TABLE BACKGROUND="javascript:alert('XSS')">
            

            本网站未列出的攻击怎么样? Jeff 方法的问题在于它不是一个白名单,正如所声称的那样。正如that page 上的某人熟练地指出:

            它的问题在于html 必须干净。在某些情况下 你可以传入被黑的html,它 不匹配,在这种情况下它会 返回被黑的 html 字符串 不会匹配任何要替换的东西。这 不是严格的白名单。

            我建议使用像 AntiSamy 这样的专用工具。它通过实际解析 HTML,然后遍历 DOM 并删除不在 configurable 白名单中的任何内容来工作。主要区别在于能够优雅地处理格式错误的 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,然后使用已知良好的序列化,是迄今为止更明智的方法。
            • 我真的很喜欢这个答案,因为它不直接回答问题,而是解决问题!
            • 你的第二个链接失效了。
            【解决方案8】:

            我不相信使用正则表达式是查找所有可疑代码的最佳方法。在处理损坏的 HTML 时,正则表达式很容易被特别欺骗。例如,Sanitize HTML 链接中列出的正则表达式将无法删除所有在元素名称和属性“href”之间具有属性的“a”元素:

            删除恶意代码的一种更可靠的方法是依靠可以处理所有类型的 HTML 文档(Tidy、TagSoup 等)的 XML 解析器,并使用 XPath 表达式选择要删除的元素。一旦 HTML 文档被解析为 DOM 文档,就可以轻松安全地找到要删除的元素。使用 XSLT 甚至可以轻松做到这一点。

            【讨论】:

            • +1,请参阅我对真正做到这一点的真实 Java API 的回复
            【解决方案9】:

            使用 jeffs 代码的最大问题是 @ 目前不可用。

            如果我需要的话,我可能会从 jeffs 代码中获取“原始”正则表达式并将其粘贴到

            http://www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html

            看到需要逃跑的东西被逃跑了再使用。


            考虑到这个正则表达式的使用,我个人会确保我完全理解我在做什么,为什么以及如果我没有成功会产生什么后果,然后复制/粘贴任何东西,就像其他答案试图帮助你一样.

            (对于任何复制/粘贴来说,这可能是非常合理的建议)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-01
              • 2020-06-12
              • 2021-01-10
              • 2011-05-19
              • 2014-09-27
              • 2018-10-27
              相关资源
              最近更新 更多