8.1 新标签和新属性绕过黑名单策略
白名单和黑名单过滤器策略是防御XSS攻击的重要方法。对输入/输出的过滤而言,白名单的防御效果要强于黑名单。但白名单策略需要极其严格的编写方式,而且用户体验效果也不强。所以在现实中,防御XSS攻击使用黑名单策略仍占一大部分。
在传统的XSS黑名单策略中,会使用HTML的标签、属性和正则表达式作为关键字匹配。现在我们以开源Web应用防火墙Modsecurity和开源软件 Snort中的XSS检测为例,来看看HTML5中的新元素是如何突破这种规则策略的。
8.1.1 跨站中的黑名单策略
1. 对HTML标签做黑名单策略
常见的XSS中用到的HTML标签格式如下:
<a href=javascript:… <applet src="data:text/html;base64,PHNjcmlwdD5hbGVydCgvWFNTLyk8L3NjcmlwdD4"type=text/html> <base href=javascript:... <bgsound src=javascript:... <body background=javascript:... <frameset><frame src="javascript:..."></frameset> <iframe src=javascript:... <img src=x onerror=... <input type=image src=javascript:... <layer src=... <link href="javascript:..." rel="stylesheet" type="text/css" <meta http-equiv="refresh" content="0;url=javascript:..." <object type=text/x-scriptlet data=... <script>...</script> <style type=text/javascript>alert('xss')</style> <table background=javascript:... <td background=javascript: <button onmouseover="alert(/1/)" onclick="alert(/2/)"></button>
针对这样的XSS代码,Modsecurity中的检测规则可以写为:
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS| XML:/* "<(a|abbr|acronym| address|applet|area|audioscope|b|base| basefront|bdo|bgsound|big| blackface|blink|blockquote|body|bq|br|button| caption|center|cite| code|col|colgroup|comment|dd|del|dfn|dir|div| dl|dt|em|embed|fieldset |fn|font|form|frame|frameset|h1|head|hr|html| i|iframe|ilayer|img| input|ins|isindex|kdb|keygen|label|layer| legend|li|limittext|link| listing|map|marquee|menu|meta|multicol|nobr| noembed|noframes|noscript |nosmartquotes|object|ol|optgroup|option|p| param|plaintext|pre|q|rt| ruby|s|samp|script|select|server|shadow| sidebar|small|spacer|span| strike|strong|style|sub|sup|table|tbody|td| textarea|tfoot|th|thead| title|tr|tt|u|ul|var|wbr|xml|xmp)\W" \ "phase:2,rev:'2.0.5',id:'973300',capture,t:no ne,t:jsDecode, t:lowercase,pass,nolog,auditlog,msg:'Possible XSS Attack Detected - HTML Tag Handler',logdata:'%{TX.0}',setvar:'tx.msg= %{rule.msg}', setvar:tx.xss_score=+ %{tx.critical_anomaly_score},setvar:tx.anomaly _score=+ %{tx.critical_anomaly_score},setvar:tx. %{rule.id}-WEB_ ATTACK/XSS-%{matched_var_name}=%{tx.0}"
Snort中的检测规则可以写为:
alert tcp any any -> any 80 (msg:"XSS 攻击识别"; pcre:"/<(a|abbr| acronym|address|applet|area|audioscope|b| base|basefront|bdo|bgsound| big|blackface|blink|denyquote|body|bq|br| button|caption|center|cite| code|col|colgroup|comment|dd|del|dfn|dir|div| dl|dt|em|embed|fieldset| fn|font|form|frame|frameset|h1|head|hr|html| i|iframe|ilayer|img|input| ins|isindex|kdb|keygen|label|layer|legend|li| limittext|link|listing| map|marquee|menu|meta|multicol|nobr|noembed| noframes|noscript| nosmartquotes|object|ol|optgroup|option|p| param|plaintext|pre|q|rt| ruby|s|samp|script|select|server|shadow| sidebar|small|spacer|span| strike|strong|style|sub|sup|table|tbody|td| textarea|tfoot|th|thead| title|tr|tt|u|ul|var|wbr|xml|xmp)\W/iU"; sid:10001; rev:1;)
2. 对HTML标签属性做黑名单策略
下面以on打头的标签属性为例,格式如下:
<body onload=…> <img src=x onerror=...>
Modsecurity中的检测规则可以写为:
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS| XML:/* "\bon(abort|blur| change|click|dblclick|dragdrop|error|focus| keydown|keypress|keyup| load|mousedown|mousemove|mouseout|mouseover| mouseup|move|readystatechange |timeupdate)\b\W*?=(alert|document|location)/ iU"; sid:10002; rev:2;)
8.1.2 新元素突破黑名单策略
从8.1.1节中的Modsecurity和Snort规则不难发现,绕过这种黑名单策略,一种情况就是跨站师使用变形后的代码绕过正则表达式的语义范围,如果正则表达式书写非常严谨,那么就很难绕过。另一种情况是下面将要提到的,跨站师们可以轻松绕过跨站黑名单策略的又一利器——HTML5新标签和新属性。
1. 新标签
音频标签<audio>和视频标签<video>。在这些标签中可以执行XSS代码:
<video onerror=javascript:alert(1)><source> <audio onerror=javascript:alert(1)><source> <video><source onerror="javascript:alert(1)"> <audio><source onerror="javascript:alert(1)"> <video src="some_valid_video" onloadedmetadata="alert(1)" ondurationchanged ="alert(2)" ontimeupdate="alert(3)"></video>
2. 新属性
HTML5中可以利用到的新属性有formac-tion、onformchange、onforminput、autofocus等,在这些属性中可以执行XSS代码:
<form id="test" /><button form="test" formaction="javascript:alert(1)">X <form id=test onforminput=alert(1)><input></ form><button form=test onformchange=alert(2)>X <input onfocus=write(1) autofocus>
很明显,这些使用HTML5代码进行的XSS攻击,使用上面提到的Modsecurity和Snort规则是无法检测到的。
要了解更多跨站中用到的HTML5标签属性,可查看http://html5sec.org/。
8.2.1 pushState()和replaceState()
在HTML 4的History API中包含一个属性和三个方法。
· ength:返回浏览器历史列表中的URL数量。
· back():加载history列表中的前一个URL。
· forward():加载history列表中的后一个URL。
· go([delta]):加载history列表中的某个具体页面。
HTML5的History API中新增加了两个新方法pushState()和replaceState()。这两个方法可以在不刷新页面的情况下添加和修改历史条目。
pushState()的格式如下:
pushState(data, title [, url])
pushState()的作用是在浏览器历史列表的栈顶部添加一条记录。它需要三个参数,一个是状态对象,一个是标题(这个目前被忽略),一个是URL(可选,同域)。
replacdState()的格式如下:
replaceState(data, title [, url])
replaceState()的作用是更改当前页面的历史记录。其参数和pushState()相同。
8.2.2 短地址+History新方法=完美
隐藏URL恶意代码
短地址服务是指把一个冗长的网址转换成一个简洁的网址。随着Twitter等微博的兴起,短地址服务也渐渐流行起来。现在国内的微博中,都会使用短地址服务,毕竟一条微博只能输入140个字,短地址服务大大压缩了网址所占的空间。
使用bit.ly短地址服务可进行网址转换,如表8-1所示。
表8-1 短地址转换
不难发现,当用户单击短地址的时候,并不知道它指向哪里,此时攻击者就可以利用短地址这个特性,把注入恶意代码的网站转换为短地址,用户单击这个短地址后,就会遭到攻击。
例如,表8-2中的这个短地址转换,在恶意URL网址中,appid参数后面就是我们注入的跨站测试代码。为了隐藏URL中的跨站代码,可以使用短地址服务http://bit.ly/将其转换为短地址,转换后的短地址为http://bit.ly/qxJuSF。此时转换后的短地址已经看不出来是一个恶意网址了。
表8-2 恶意短地址转换
此时,你也许会认为这样的隐藏太完美了。其实它也存在不足,当用户单击http://bit.ly/ qxJuSF后,在浏览器的URL地址栏中仍会呈现http://mail.test.com/?userid=&appid=<script>document. write(1)</script>地址。只能说使用短地址服务隐藏恶意代码只隐藏了一半,用户始终可以看到注入的恶意代码。
接下来使用History的新方法来隐藏另一半,让恶意代码执行后,用户无法看到URL中的恶意代码。要说明的是,修改后的URL必须和当前的URL同域,这里把URL参数的位置写成loca-tion.href.split("?").shift()。
短地址转换前后如表8-3或表8-4所示。
表8-3 恶意短地址转换隐藏技巧1
表8-4 恶意短地址转换隐藏技巧2
当用户单击短地址链接后,看到浏览器中的URL将会被替换为http://www.mail.test.com/。参数appid后面的跨站代码document.write(1)此时也已经执行。
通过上面的分析知道,传统方式下隐藏URL中的恶意代码可以使用短地址服务。但这样隐藏后,当用户单击执行时,还是会在浏览器URL地址栏中看到恶意代码。现在可以利用History的新方法pushState()和replaceState(),在无刷新页面的情况下改变地址栏中的URL,用户就无法看到恶意代码。所以,通过以上两种方法的结合,可以完美地隐藏URL中的恶意代码。
8.2.3 伪造历史记录
在Chrome浏览器中打开以下脚本程序:
<script> for(i=0;i<=100;i++) {history.pushState({},"","/"+i+".html"); </script>
然后在Chrome浏览器中查看历史记录,可以看到有很多历史记录信息,如图8-1所示,而这些链接信息用户其实根本没有访问过。
图8-1 Chrome下伪造历史记录
通过这个例子我们可以看到,使用his-tory.pushState可以对浏览器的历史记录进行伪造,而且也可以对历史记录发起DoS攻击。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论