Part1 技术研究过程
这个案例是源于之前测过的一个有奖活动介绍的Web页面,整个子域名只有两个html静态页面,通过burpsuite抓包发现没有任何动态交互,因而漏洞挖掘的难度非常大。查看当前html页面源码,分析了一下JS代码,发现了memberId的传值会在当前页面回显,也就意味着存在XSS漏洞的可能性,但是需要闭合双引号。输入测试payload 402881111”; window.open(); //,发现当前页面对XSS进行了防范,会对双引号进行转义而变成如下形式:var memberId=”402881111\”; window.open(); //”,导致XSS代码无法正常运行。经过测试发现这个页面的编码为GBK,由此想到了使用宽字节的方法吃掉\转义字符,从而使双引号继续运行。于是提交如下URL:index.html?memberId=1111%81%22;window.open();//&id=112233由于当前页面编号为GBK,%81与后面的 \ 被解析成一个字符变成%81%5C%22,经过GBK编码后造成 \ 被吃掉,也就是 %81%5C 变成一个乱码字符,从而使独立的双引号保留下来造成XSS漏洞。如下图所示,表明转义字符被吃掉,window.open();// 会被执行。
对于innerHTML内容可以自定义的情况,也可以传入Unicode编码的XSS测试语句,绕过各种过滤与拦截。
提交如下Unicode编码+URL编码后的XSS测试语句:
userID=%5Cu003c%5Cu002f%5Cu0066%5Cu006f%5Cu0072%5Cu006d%5Cu003e%5Cu003c%5Cu002f%5Cu0073%5Cu0070%5Cu0061%5Cu006e%5Cu003e%5Cu0064%5Cu0064%5Cu0064%5Cu0064%5Cu0064%5Cu0064%5Cu0064%5Cu003c%5Cu002f%5Cu0073%5Cu0070%5Cu0061%5Cu006e%5Cu003e%5Cu003c%5Cu0069%5Cu006d%5Cu0067%5Cu0020%5Cu0073%5Cu0072%5Cu0063%5Cu003d%5Cu0030%5Cu0020%5Cu006f%5Cu006e%5Cu0065%5Cu0072%5Cu0072%5Cu006f%5Cu0072%5Cu003d%5Cu0061%5Cu006c%5Cu0065%5Cu0072%5Cu0074%5Cu0028%5Cu0031%5Cu0031%5Cu0031%5Cu0031%5Cu0031%5Cu0029%5Cu003e&hciPasswordTypeEOSOperator%2Fpassword
对于一个URL,#后面的部分是片段标识符,通常用于页面内导航或者作为附加参数,不会直接发送给服务器,但在某些情况下会被客户端脚本读取和处理。如果目标页面未正确处理或过滤片段标识符中的内容,可能会将这段HTML片段直接插入到DOM中,从而执行嵌入的JavaScript代码。攻击者可以利用这种方法在受害者的浏览器中执行任意JavaScript代码,导致信息泄露、会话劫持、页面篡改等安全问题。由于#号后面的语句不经过服务端,因而此类型的DOM-XSS可以绕过一切的WAF拦截。测试语句:http://www.xxx.com/voiceSysWeb/error.html?errorInfo=00000#%3c%69%6d%67%20%73%72%63%3d%31%20%6f%6e%65%72%72%6f%72%3d%61%6c%65%72%74%28%31%31%31%31%31%31%31%29%3eself.location.href会接受浏览器完整的URL值,包括#后面的字符串。而%3c%69%6d%67%20%73%72%63%3d%31%20%6f%6e%65%72%72%6f%72%3d%61%6c%65%72%74%28%31%31%31%31%31%31%31%29%3e会被str.substring(n + 1, str.length)处理,进而被decodeURIComponent方法URL编码解码,变成<img src=1 onerror=alert(1111111)>,然后被Jquery组件的html解析执行。
遇到返回body体中的script标签内部的js代码,有字符串拼接相加的情况,可以试试使用setTimeout方法来触发XSS弹窗。测试语句:http://www.xxx.com/searchAll/searchByKeyWord.htm?keyWord=ddddd"+setTimeout(String.fromCharCode(97,108,101,114,116,40,49,49,49,41),0)+"String.fromCharCode方法用于将ASCII码转为字符串,97,108,101,114,116,40,49,49,49,41的ASCII码是alert(111),setTimeout在0毫秒后执行一个alert弹窗。
这个web应用的XSS漏洞存在的位置,限制了XSS payload的长度,但是经过测试,可以使用分段提交的办法绕过长度限制,用注释符拼接的方式,注释掉不同payload之间拼接过程中产生的额外字符。以下是很早之前的一个实战案例。以下是我的实战版本,用/*xxx*/的注释不可行,但是可以使用//的注释方式,最终仍然可以造成弹窗效果。
以下这个业务系统对XSS进行了一定的防范,对on事件进行了黑名单过滤。经过测试发现ondragstart没有在黑名单之内,是可以使用的;然后这个Web应用还对<>进行HTML实体编码,导致一切XSS漏洞均失效。但是我们通过另外的界面,通过搜索关键字查找我们刚刚提交的条目,发现了一个裂开的图片,这说明重新调用过程中,该应用又对其进行了HTML解码,导致继续产生XSS漏洞。
Part2 总结
1. 对用户提交的数据进行HTML编码以及各种关键字过滤,并慎用HTML解码,防止二次XSS的情况发生。2. 以#号开头的隐式DOM-XSS攻击语句不会经过服务端处理,因而所有的WAF均无法拦截。3. XSS漏洞的深入挖掘及利用,需要Javascript功底,因此,学好Javascript是重中之重。
该文章在 2024/10/31 10:08:58 编辑过