Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XSS(一) #96

Open
PyxYuYu opened this issue Mar 20, 2017 · 0 comments
Open

XSS(一) #96

PyxYuYu opened this issue Mar 20, 2017 · 0 comments
Labels

Comments

@PyxYuYu
Copy link
Owner

PyxYuYu commented Mar 20, 2017

A goal is a dream with a deadline.

0x01 XSS

  • 反射型XSS
    • 非持久化,需要欺骗用户自己去点击链接才能触发 XSS 代码,服务器中没有这样的页面和内容
    • 目前多数主流浏览器都有 XSS 过滤器(测试一般用 IE6IE7,或者更高级的手动关闭 XSS 筛选),所以常规的 反射型XSS 一般会被过滤,需要绕过
    • 在防范这类 XSS 时,通常可以在服务器段对传入的参数进行过滤,来防范这类攻击
  • DOM型XSS
    • DOM-based XSS 是基于文档对象模型 Document Object Model 的一种漏洞
      • DOM 是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问或更新文档内容、结构、样式,处理后的结果能够成为显示页面的一部分
      • DOM 中有很多对象,其中一些是用户可以操纵的,比如 form、referrer、location
      • 客户端的脚本程序(JavaScript)可以通过 DOM 动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得 DOM 中的数据在本地执行
      • 如果 DOM 中的数据没有经过严格确认,就会产生 DOM-based XSS 漏洞
    • DOM型XSS 输入点(即可能之后导致发生 XSS 的前提)-- JavaScript
      • location
        • location.href
        • location.search
          • IE 没有将 <> 进行 URL 编码
        • location.hash
        • location.pathname
      • window.name
      • document.cookie
      • localStorage
      • document.title
      • getAttribute
      • document.referrer
      • innerText
      • .value
      • .dataset
      • postMessage
        • 使用 \ 绕过初始检测
      • innerHTML
    • DOM型XSS 触发点(即可插入 XSS 代码处) -- JavaScript
      • location
        • location='javasc&#114ipt&#58alert&#40~1&#41'
      • eval
      • innerHTML
      • document.write
      • appendChild
      • Function
      • setTimeout
      • setInterval
      • createElement
        *
           with(document)body.appendChild(createElement('iframe onload=&#97&#108&#101&#114&#116(1)>'),body.innerHTML+="(IE)
        
    • 显示输出
      • URL 提交后,右键查看源代码可以看到输出的内容
      • innerHTML
         <div id="a">xxx</div>
         <script>
             document.getElementById("a").innerHTML="yyyy";
         </script>
      
      • innerHTML="[输出]",可以通过 JS 脚本改变 a 的值
        • [输出] 这里只能使用 <img src=1 onerror=alter(1)> 这种方式来触发 JS
        • 不能使用 <script>alert(1)</script> 来触发
        • IE 下可以使用 <script defer>alert(1)</script>
      • < 被过滤的话,可以使用 \u003c、\x3c 代替
      • > 被过滤的话,可以使用 \u003e、\x3e 代替
      • 空格可以使用 \u0020 代替
      • 所以上面的 Payload 可以写成 \x3cimg\u0020src=1\u0020onerror=alert(1)\x3e
      • 除了 innerHTML 只要与改变页面 HTML 内容相关的操作,都可能导致这种问题
      • 除了 JS,一些使用了第三方库,譬如 jQuery 也会: $("#x").html("yyyy")
    • 隐式输出
      • 输出操作在查看源代码中无法看见,通常发生在 JavaScript 代码中
        • 比如:var x=location.href;
        • JavaScript 进行了一个隐藏的输出操作,将 location.href 的内容输出到了变量 x
      • location.href
         function getParam(name){
             var x = locaton.search; //或者是 location.hash
             var v = x.match(new RegExp("[?&#]"+name+"=([^&]*)",""));
             return v?v[1]:"";
         }
      
      • 上面函数定义了一个利用正则匹配获取 URLname 参数后的参数值的方法
         <div id="nick">加载中...</div>
         <script>
             var a = getParam("name");  // 获取地址栏里的name参数值
             document.getElementById("nick").innerHTML = a;
         </script>
      
      • a 改写成 <img src=1 oneror=alert(1)> 即可触发 XSSa 就是从 getParam 函数通过 name 参数获得的参数值
      • Fuzz 步骤
        • 隐式输出,源代码中搜索不到参数值,F12 调试工具,搜索输出
        • 搜索到输出后,两种方法
          • 直接根据查看到的 HTML 代码,进行构造,注意闭合,注意过滤的情况
            • 优点:省时
            • 缺点:有过滤的情况,会比较难闭合
          • 查看 JavaScript 代码,寻找对应的函数,分析函数,是否进行了过滤,编码,解码,如果先编码,后解码,就等同于没有过滤
            • 优点:明白逻辑,可以进行复杂构造
            • 缺点:费时
        • 注意: Chrome 浏览器会自动对 "、>、< 进行转义成 %22、%3c、%3eIE 不会
    • eval
      • 显示输出隐式输出 最终 JavaScript 都会通过 document.writeinnerHTML 将内容输出到网页中,所以总是有办法可以查看到输出到哪里,但是如果没有通过它们,而是通过函数,利用 eval 来进行输出,就无法通过源代码或者 F12 调试工具查找
         var getarg = function()
         {
             var url = window.location.href;
             var allargs = url.split("?")[1];
             if (allargs!=null && allargs.index0f("=")>0)
             {
                 var args = allargs.split("&");
                 for(var i=0; i<args.length; i++)
                 {
                     var arg = args[i].split("=");
                     eval('this.'+arg[0]+'="'+arg[1]+'";');
                 }
             }
         }
      
      • 上面函数是获取 URL,之后将参数分割,分割后执行 eval
      • 如果这里 arg[0] 或者 arg[1] 可控的话,就可以插入 XSS 代码,导致漏洞产生
      • 原来的 eval 应该执行
         eval('this.a="bbb";')
      
      • arg[0] 就是 aarg[1] 就是 "bbb"
      • 修改 arg[0] 构造 XSS,即
         eval('this.a;alert(1);//="bbb";')
         // 需要加上等号,因为上面的代码逻辑是根据等号来分割,注释掉后面即可
         // arg[0] 为 a;alert(1);//
         // www.xxx.com/1.html?a;alert(1);//=bbb
      
      • 修改 arg[1] 构造 XSS,即
         eval('this.a="bbb";alert(1);//"')
         // " 是代码后面加上的,所以这里需要自己闭合前面的双引号,后面的双引号可以注释掉
         // www.xxx.com/1.html?a=bbb";alert(1);//
      
      • 注意:修改 arg[1] 这里自己闭合了双引号,在 Chrome 中双引号会被主动过滤,所以只有在 IE 下才会成功
    • iframe
      • <iframe src="[输出]"></iframe>
      • iframesrc 属性本来应该是一个网站,但是 iframe 可以使它同样可以执行 JavaScript,而且可以使用不同的姿势来执行,这一类问题,可以归为 [路径可控] 问题
      • onload 执行 JS
         <iframe onload="alert(1)"></iframe>
      
      • src 执行 JS
         <iframe src="javascript:alert(1)"></iframe>
      
      • IEsrc 执行 vbscript
         <iframe src="vbscript:msgbox(1)"></iframe>
      
      • Chromesrc 执行 data 协议
         <iframe src="data:text/html,<script>alert(1)</script>"></iframe>
         // 转义
         <iframe src="data:text/html,&lt;script&gt;alert(1)&lt;/script&gt;"></iframe>
      
      • Chromesrcdoc 执行 JS
         <iframe srcdoc="&lt;script&gt;alert(1)&lt;/script&gt;"></iframe>
      
      • Fuzz 步骤
        • F12 调试工具,查看有无可见输出
        • 查到参数被带入到 <iframe src="[参数]"></iframe> 之中
        • 查看相关函数,是否有一些过滤
           function OpenFrame(url) {
               if (url.toLowerCase().indexOf('http://') != '-1' || url.toLowerCase().indexOf('https://') != '-1' || url.toLowerCase().indexOf('javascript:') != '-1') return false;
                   document.getElementById("toolframe").src = url;
           }
        
        • 上面函数过滤了 http:// https:// javescript:
        • document.getElementById("toolframe").src = url; 这里导致了执行 XSS
        • url 参数可控制,过滤不完善,所以
          • IE 下,可以使用 vbscript 来执行代码,vbscript' 单引号表示注释,类似 JS 中的 //
             http://www.xxx.com/1.html?url=vbscript:msgbox(1)'&gid=yl
          
          • Chrome 下,可以使用 data 协议来执行 JS
             http://www.xxx.com/1.html?url=data:text/html,<script>alert(1)</script>//
          
    • 路径con
      • 同域的时候,可以使用 AJAX 动态地加载 json 数据,而有时候,数据所在域和当前页面所在域不同,所以需要跨域请求,跨域请求数据中,有一种方法叫做 JSONP
        • 用代码表示的话,就是
           somescript.src="http://otherdomain.com/xx?jsonp=callback"
        
        • 有时,程序员会在调用外部数据的时候带上可控的参数,这个可控参数就可能导致 XSS
           somescript.src="http://otherdomain.com/xx?jsonp=callback&id="+id;
        
      • 跨域请求
        • JSON 是一种基于文本的数据交换格式,或者称为数据描述格式
          • JSON 只有两种数据类型描述符,大括号和方括号,其余冒号是映射符,逗号是分隔符,双引号是定义符,对象表示为键值对
        • JSONPJSON with Padding
          • JSONPJSON 的一种使用模式,可以让网页从别的域名获取资料,即跨域读取数据
          • 由于同源策略的限制,XmlHttpRequest 只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过 script 标签实现跨域请求,然后在服务端输出 JSON 数据并执行回调函数,从而解决跨域的数据请求
          • Web 页面上调用 JS 文件不受是否跨域的影响,不仅如此,凡是拥有 src 这个属性的标签都拥有跨域的能力,比如 script、img、 iframe
          • JSONP 协议允许用户传递一个 callback 参数给服务端,然后服务端返回数据时会将这个 callback 参数作为函数名来包裹住 JSON 数据,这样客户端可以随意定制自己的函数来处理返回的数据(动态执行回调函数)
      • 跨域请求 src 地址可控可以分为三种
        • script src="[完全可控]"
          • 直接将地址换为 JS 地址
        • script src="/path/xxx/[路径可控]/1.js"
          • 路径可控,被利用的话,需要同域名下有可控的文件,可控文件分两类
            • 直接上传文本至同域名下,不一定要是 HTML 文件,需要上传点有过滤缺陷
            • 参数可控,利用可用的 JSON 接口
          • 最终变为 script src="/path/xxx/.../yyy/xx.json?callback=alert(1)"
        • script src="/xxxx/json.php?callback=xxxx&param1=yyy&param2=[参数可控]"
          • 类似上面的参数可控,如果参数可控,且 JSON 的参数没有做好过滤,就可以导致 XSS
      • Fuzz 步骤
        • F12 调试工具,刷新查看是否有加载外部 JS 文件
        • 修改原始 URL 中参数值,查看是否有参数被传入到外部 JS 文件中
        • 有参数传入的话,打开这个 JS 文件地址,修改地址内参数,查看哪些参数可控
        • 判断可控参数是否过滤 < > ,
        • callback 参数可控,且未被双引号包裹,所以这里可以构造
           http://xxx.xxx.com/comm.json?callback=alert(1);
        
        • 将原始页面调用上面的 JS 文件即可导致 XSS
        • callback 参数可以从之前探测出的传入到外部 JS 文件中的参数一起带入
        • 即将原始 URL 中的参数 param=xx 修改为 param=xx&callback=alert(1); 覆盖掉外部 JS 文件中的 callback
        • & 也可以写成 %26
        • 查看函数,明白参数是如何传递到 comm_json 接口
           var keyword = decodeURIComp($getQuery('keyword')),
        
        • 此处 decodeURIComp 解码,即 & 会变成 %26,便不是连接符了
        • 所以,最后应该为 %26 即:
           http://yyy.xxx.com/1.html?keyword=1%26callback=alert(1);&PTAG=2005.13.1
        
    • DOM型XSS 总结
      • 修改参数值,查看源代码,调试工具,是否有改变
      • 如果有,查看是否存在过滤 <、>、"、'
      • 查看参数值外是否有 DOM型XSS 的触发点
      • 如果有,根据上下文,尝试闭合语句,字符也可以用 Unicode 编码替换(此处需要 \ 未被过滤)
      • 构造完整 Payload
  • 存储型XSS
    • 存储型需要进入数据库,输出可能出现在任何用到数据的地方,不一定出现在输入的位置,输入大部分来自 POST/GET 请求
    • Fuzz 思路
      • 先找到输出点,猜测此处输出是否会被过滤
      • 如果觉得可能没过滤,再找这个输出是从哪输入的
      • 开始测试输入,看输出效果
      • 如果没过滤,那么 存储型XSS 成功
    • 富文本
      • 很多应用含有富文本内容,最典型的特性是具有编辑器,这类应用往往允许使用一定的 HTML 代码,为了在用户体验和安全之间寻找平衡,一般有两种方法
        • 白名单
          • 只允许使用白名单内的合法 HTML 标签
        • 黑名单
          • 厂商构建一个有危害的 HTML 标签、属性列表,通过分析用户提交的 HTML 代码,去除其中有害的部分
      • 黑名单这种方式往往会被绕过,白名单则安全的多
      • 通过抓包的方式,修改抓包内容,插入 XSS 代码,提交修改后的数据包,查看 XSS 代码是否被过滤
  • FlashXSS
    • FlashActionScript 脚本目前网络上存在两种版本,即 2.03.0
    • 利用 Google 搜索
      • site:xx.com filetype:swf inurl:下面的关键词
      • 已知存在缺陷的 Flash 文件名或参数名:如 swfuploadjwplayer
      • 多媒体功能的 Flash 文件名:如 uploadplayermusicvideo
      • 调用的外部配置或数据文件后缀:如: xmlphp
      • 前期经验积累下来的程序员特征参数名用词:如: callbackcbfunction
    • Flash 缺陷参数
      • Flash 提供相关的函数,可以执行 JS 代码
        • getURL(AS2)
        • navigateToURL(AS3)
        • ExternalInterface.call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant