静态xss检测

静态xss检测

一)前言

  静态xss检测是啥?静态xss检测相对区别于基于webkit的xss检测。
  完成依靠输出点情况的检测来判断是否存在xss漏洞。那么xss漏洞用webkit(http://blog.wils0n.cn/archives/18/)来检查就好了,为什么还要加上静态xss检测呢??
  个人认为是因为基于webkit的xss检测有的时候可能检查不到:

  1.script标签内多重闭合的情况。
  比如之前weibo发现一处xss是这样的:

  <script type="text/javascript">
         $('#qrcode_area').qrcode({
             //render:'table',
             width:300,
             height:300,
             text:"xxxxx{$输出点}"
         });
 </script>

  如果你的domxss漏洞检测payload没有这个:"});alert(1111);// 那这个就漏描了

  2.过滤了你的payload的某些关键字。
  比如payload为

<script>alert(111)<script>

  过滤了script,但是其它标签没有过滤,比如

 <img src=1 onerror=alert(1)>

  当然如果你的payload够丰富的话也可以。。。。

二)发现牛逼的DSXS

  这天突然发现自己的静态检查的逻辑出现误报了。原因是xss输出点在页面中多次出现。。比如http://www.sogou.com/sogou?query=wilson2333(89处输出点),想来想去没有好的解决办法。心中mmp。。。
  一般遇到解决不了的问题,我选择多去看别人的代码,打开全世界最大同性交友平台github,搜索xss scan,看了几个工程,就发现有一个工程DSXS(https://github.com/stamparm/DSXS/blob/master/dsxs.py)特别吸引人的注意力,这款由sqlmap原作者写的xss扫描器,检查思路巧妙,很多漂亮的正则表达规则,让人佩服。
  不过作者强行装逼,说:"Damn Small XSS Scanner (DSXS) is a fully functional Cross-site scripting vulnerability scanner (supporting GET and POST parameters) written in under 100 lines of code." 一定把代码写到99行,导致代码可读性极差!心中又一次mmp....

三)Damn Small XSS Scanner (DSXS)的检查逻辑

  硬着头皮把代码看下来,还是学到很多的。此外感谢@lightless解读一个点。
  首先DSXS会有一个domxss的正则匹配

DOM_PATTERNS = (                                                                            # each (dom pattern) item consists of r"recognition regex"
  r"(?s)<script[^>]*>[^<]*?(var|\n)\s*(\w+)\s*=[^;]*(document\.(location|URL|documentURI)|location\.(href|search)|window\.location)[^;]*;[^<]*(document\.write(ln)?\(|\.innerHTML\s*=|eval\(|setTimeout\(|setInterval\(|location\.(replace|assign)\(|setAttribute\()[^;]*\2.*?</script>",
  r"(?s)<script[^>]*>[^<]*?(document\.write\(|\.innerHTML\s*=|eval\(|setTimeout\(|setInterval\(|location\.(replace|assign)\(|setAttribute\()[^;]*(document\.(location|URL|documentURI)|location\.(href|search)|window\.location).*?</script>",
)

  不存在domxss漏洞再继续做下一步的xss漏洞检测。

  1.生成测试payload,并发包。
  测试payload有两种,一种是大范围的测试(''', '"', '>', '<', ';') 另外还有一种小范围的测试,('<', '>')。
  生成测试payload,payload前面和后面都会加上随机生成的prefix和suffix,它们两个用于正则更好的匹配到输出点的内容。

  取一个例子:

payload = rfzxg";'><bwhsj

  2.匹配全部输出点
  巧妙使用正则表达式:

re.finditer("rfzxg([^ ]+?)bwhsj")

  匹配全部输出点。  这里我们会得到输出点输出的内容,代码中变量为sample.group(0) [其中我们得到的内容就是rfzxg";'><bwhsj]。

  3.判断xss输出点属于什么类型
  xss输出点DSXS分为9种类型:

  \A[^<>]*%(chars)s[^<>]*\Z  # 纯文本的输出,无标签。开头不是<>结尾也不是<>。左右尖号没过滤就算xss漏洞
  <!--[^>]*%(chars)s|%(chars)s[^<]*--> # 注释里面输出。左右尖号没过滤就算xss漏洞
  (?s)<script[^>]*>[^<]*?'[^<']*%(chars)s|%(chars)s[^<']*'[^<]*</script> # script里面输出,并前面为单引号。单引号和封号没过滤就算xss漏洞
  (?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script> # script里面输出,并前面为双引号。双引号和封号没过滤就算xss漏洞
  (?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script> # script里面输出,前面无双引号和单引号。封号没过滤就算xss漏洞
  >[^<]*%(chars)s[^<]*(<|\Z) # 标签外面输出。左右尖号没过滤就算xss漏洞
  <[^>]*'[^>']*%(chars)s[^>']*'[^>]*>,# 标签里面value输出,并前面为单引号。单引号没过滤就算xss漏洞
  <[^>]*"[^>"]*%(chars)s[^>"]*"[^>]*># 标签里面value输出,并前面为双引号。双引号没过滤就算xss漏洞
  <[^>]*%(chars)s[^>]*># 标签里面输出,前面无双引号和单引号。就算一个漏洞

  chars关键字根据得到sample.group(0)[其中我们得到的内容就是rfzxg";'><bwhsj],生成判断位置的完整规则正则。

  4.确定xss漏洞存在
  对输出内容进行sample.group(1)[就是";'><]进行需要的关键字匹配。如果需要的关键字没有被过滤就认为是一个反射xss漏洞。比如类型5:script里面存在输出,前面无双引号和单引号,封号没过滤就算xss漏洞。

局限和误报

  使用它的代码进行xss扫描时候发现的局限性和误报都给作者提issues了(https://github.com/stamparm/DSXS/issues),不过作者貌似没时间理我 - -.....
  1.不支持在 find xss in href
egg:

<?php
$input= str_replace("\"", "&quot;" ,$_GET['xss']);
$input=str_replace(">","&lt;",$input);
$input=str_replace("<","&gt;",$input);
echo '<a href="';
print($input);
echo '">click<a/>';
?>

  http://127.0.0.1/2.php?xss=javascript:alert(1) when click it will has xss vuls,but DSXS can't find this。

  2.误报
  大部分误报是因为9种类型xss输出判断错误问题,导致误报。比如:

  demo.php:
  egg:

</main><script>
  var jobs = {
      log: {
          pj: 'jobs-social',
          qid: '',
          pn: 0
      },
      common: {
       query:'',
      cookieStr: 'iurl',
       selected : {"city":"<?php echo str_replace("\"", "\\\"" ,$_GET['xss']);?>"}
     }
  };
</script>

  这种把script标签的双引号内输出判断成这种把script标签的当引号内输出的,导致误报。不过这种定位标签情况太多,正则的确也难写。。@lightless师傅建议优化正则为下面内容可以解决该误报:

<script[^>]*>[^<]*?'[^<'\"]*%(chars)s|%(chars)s[^<'\"]*'[^<]*</script>
<script[^>]*>[^<]*?"[^<"\']*%(chars)s|%(chars)s[^<"\']*"[^<]*</script>

   但是总的来说,DSXS扫描器它误报率低,扫描准确,是一款体积小而优秀的xss扫描器。


  更新:
  作者回复我的issues。

   1.对于find xss in href,作者不作支持它。
   2.对于出现的几个误报的情况,作者优化了标签里面value输出的正则和script里面输出正则。
     2.1.正则优化让标签里面输出和标签里面value输出这两个正则区分清楚,让扫描无误报。
     2.2.script里面输出正则也做了优化。
  

  具体可看:https://github.com/stamparm/DSXS/issues/5

标签: none

已有 2 条评论

  1. taerge


    这种类型的正则的有误报,比如“ xxxabc-->” 后面的abc并不在注释中,但是还是会命中

    1. wilson

      这个静态的就会有误报。。不过误报比较低了。
      作者貌似认为这个工具只是自己写着玩的检查xss小工具,不打算做到高精度的扫描。(https://github.com/stamparm/DSXS/issues/5)

      你这误报的实例情况我看得不太懂,最好有例子,或者代码说明。

添加新评论