这是一个(几千个可能的例子):
使用这个简单的 XSS 输入:
<script>alert('XSS');</script>
//Now we URI encode it:
%3Cscript%3Ealert(%27XSS%27)%3B%3C%2Fscript%3E
//Now we URI encode it again:
%253Cscript%253Ealert(%2527XSS%2527)%253B%253C%252Fscript%253E
对已编码一次的输入进行规范化将产生原始输入,但在 ESAPI 的情况下,第三个输入将抛出一个,IntrusionException
因为从来没有一个有效的用例,用户输入将被 URI 编码多次。在这个特定的例子中,规范化意味着“所有的 URI 数据都将被简化为其实际的字符表示”。ESAPI 实际上不仅仅是 URI 解码,顺便说一句。如果您希望使用正则表达式(大多数应用程序中正则表达式的主要用途)执行安全性和/或业务验证,这一点很重要。
至少,规范化可以很好地保证将恶意输入偷偷带入应用程序并不容易:目标是限制已知良好的值(白名单)并拒绝其他所有内容。
关于您在这里不明智的评论:
We are not encoding output given that after the input validation, data becomes trusted.
这是一个肮脏的事实:Javascript、XML、JSON 和 HTML 不是“常规语言”。它们是不确定的。这实际上意味着在数学上不可能编写一个正则表达式来拒绝所有将 HTML 或 Javascript 插入应用程序的尝试。看看我在上面发布的那个 XSS 过滤器规避备忘单。
您的应用程序使用 jquery 吗?以下输入是恶意的:
$=''|'',_=$+!"",__=_+_,___=__+_,($)[_$=($$=(_$=""+{})[__+__+_])+_$[_]+(""+_$[-__])[_]+(""+!_)[___]+($_=(_$=""+!$)[$])+_$[_]+_$[__]+$$+$_+(""+{})[_]+_$[_]][_$]((_$=""+!_)[_]+_$[__]+_$[__+__]+(_$=""+!$)[_]+_$[$]+"("+_+")")()
因此,当输出给用户时,您必须对所有数据进行编码,以获得适当的上下文,这意味着如果要先将数据块输入到 javascript 函数中,然后显示为 HTML,您需要先编码为 Javascript,然后再编码为 HTML . 如果将其输出到 HTML 数据字段(例如默认输入框)中,则将其编码为 HTML 属性。
实际上,在保护 XSS 方面,进行输出编码比进行输入过滤更重要。(如果我只能选择一个......)
您希望在 Web 开发中遵循的模式是,任何来自外部世界的输入在任何时候都被视为恶意输入。任何时候你都在向动态解释器进行编码。