0x00 废话

DSXS是一个只有一百行代码的xss扫描器,其作者刚好就是写sqlmap的那位,下面来看一下其扫描逻辑。0x01部分文字较多,感觉写的有点啰嗦,如果看不下去的话就直接看最后的0x02的总结部分。

0x01 扫描逻辑

程序有两个非并行的逻辑,第一个逻辑是检测dom型xss,第二个逻辑是检测经过后端的xss。在执行两个逻辑之前,程序会先判断目标路径上是否有参数值为空的情况,有则赋为1,比如:baidu.com/?id=99&name=&age=转换成baidu.com/?id=99&name=1&age=1。转换完成后,进入xss检测逻辑部分。

第一个逻辑:dom型xss

首先根据dom_filter_regex去掉响应包中的内容,然后在响应中查找dom_patterns,如果存在,则提示可能存在dom-xss

第二个逻辑:经过后端的xss

首先要知道这里有一个核心的正则表达式list,一共有九个元组,每个元组都代表输出点在dom结点中的一个确定的位置,比如:script标签内、单引号内、注释内。。然后对应每个位置,还有对应的攻击方法,比如在单引号内就需要用单引号逃逸,即单引号在响应中不能被转义,如果被转义就完了。其中每个元组有四个元素,详细看下面:

REGULAR_PATTERNS = (                                                                        # each (regular pattern) item consists of (r"context regex", (prerequisite unfiltered characters), "info text", r"content removal regex") # 格式(匹配有可能存在xss的字符串的正则,攻击成功需要哪些字符未经过滤,说明(简易表达匹配格式),获取响应包后首先筛掉的字符的regexp)
(r"\A[^<>]*%(chars)s[^<>]*\Z", ('<', '>'), "\".xss.\", pure text response, %(filtering)s filtering", None),
(r"<!--[^>]*%(chars)s|%(chars)s[^<]*-->", ('<', '>'), "\"<!--.'.xss.'.-->\", inside the comment, %(filtering)s filtering", None),
(r"(?s)<script[^>]*>[^<]*?'[^<']*%(chars)s|%(chars)s[^<']*'[^<]*</script>", ('\'', ';'), "\"<script>.'.xss.'.</script>\", enclosed by <script> tags, inside single-quotes, %(filtering)s filtering", r"\\'"),
(r'(?s)<script[^>]*>[^<]*?"[^<"]*%(chars)s|%(chars)s[^<"]*"[^<]*</script>', ('"', ';'), "'<script>.\".xss.\".</script>', enclosed by <script> tags, inside double-quotes, %(filtering)s filtering", r'\\"'),
(r"(?s)<script[^>]*>[^<]*?%(chars)s|%(chars)s[^<]*</script>", (';',), "\"<script>.xss.</script>\", enclosed by <script> tags, %(filtering)s filtering", None),
(r">[^<]*%(chars)s[^<]*(<|\Z)", ('<', '>'), "\">.xss.<\", outside of tags, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->"),
(r"<[^>]*=\s*'[^>']*%(chars)s[^>']*'[^>]*>", ('\'',), "\"<.'.xss.'.>\", inside the tag, inside single-quotes, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->|\\"),
(r'<[^>]*=\s*"[^>"]*%(chars)s[^>"]*"[^>]*>', ('"',), "'<.\".xss.\".>', inside the tag, inside double-quotes, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->|\\"),
(r"<[^>]*%(chars)s[^>]*>", (), "\"<.xss.>\", inside the tag, outside of quotes, %(filtering)s filtering", r"(?s)<script.+?</script>|<!--.*?-->|=\s*'[^']*'|=\s*\"[^\"]*\""),
)

人话版如下:

这个表说了,下面说一下检测的大体流程。首先是发送payload,然后查找payload的输出点,接着再看这个输出点对应上边表中的哪个位置。找到对应的位置之后再看如果在这个位置要利用成功需要哪些字符不被转义,然后在响应中查找payload,确定payload中‘不可被转义的特殊字符’前是否被加上了反斜杠\,如果有则认为被转义,并继续往下找,直到每个不可被转义的字符至少在响应中未被转义地出现了一次,才会认为存在漏洞。

下面根据代码说一下。

62-65行是dom-xss检测,是属于上面的第一个逻辑,这里就不再展开。从67行往下看,首先是分别进行GET和POST请求,然后到了69行。

这里在url和post-data中查找键值对(参数)的位置,然后对每个参数进行以下的测试。

从72行可以看到,首先赋值两个长度为5的随机字符的字符串:prefix和suffix

然后使用一个for循环,针对larger_char_pool和smaller_char_pool进行单独的测试(这两个list分别是:(''', '"', '>', '<', ';') 和('<', '>')。之所以要用两个list的原因是防止后端使用waf/ids时对payload进行拦截,所以使用了一个smaller_payload来避免过于明显的payload[即有较少的特殊字符]) 。

进入75行,这里先构造payload,payload格式为prefix+pool中所有字符的随机排序+suffix,如果这个pool是larger_char_pool,则这里在payload之前加一个单引号'原因如下:

1) .试图触发xss

2) .故意构造一个错误的sql语句用于报错,试图在报错信息中寻找触发点

这里暂且把prefix与suffix中间的部分称为vector。构造完payload之后直接发送,然后获取返回内容。如果这个pool是larger_char_pool,那么这里就要去掉prefix之前的单引号',这个单引号的作用刚刚已经说了,至此已经完成了它的使命,这里自然要从响应中去掉,防止干扰。

然后到77行,下面开始使用regular_patterns对相应内容进行测试,首先根据content_removal_regex去掉响应中的内容(因为payload有重合部分,所以要通过这种方式来避免重合的检测,即表中每个元组的第四个元素),然后在响应中寻找(prefix+...+suffix) [注:这里的规则大致是prefix.*suffix,不指定中间的部分为vector,因为vector有可能被后端转义掉了],暂时称之为response-payload。

如果可以找到,就说明这个参数的值是会被输出到响应中的(先不管有没有过滤),下面的逻辑就要检测这个参数是否可以利用。首先需要确定response-payload的输出点在哪个位置(script标签内?注释内?引号内?等等,详见REGULAR_PATTERNS),然后再根据输出点来确定在这个位置利用成功需要哪些字符不被过滤。

ok,逻辑大概理清楚了,下面是程序的实现。首先是输出点定位,在第80行,程序将response-payload插入到regular_patterns的regex(每个元组的第一个元素)中的chars位置,如果可以在响应中匹配到regex,就说明定位成功。然后下一步就是检查字符过滤情况,程序通过在82行调用_contains函数来确定“不可被过滤的字符”在响应中是否被过滤(即判断这些字符前是否有反斜杠\),对prefix和suffix中vector位置的字符串进行检测,_contains代码如下:

这里如果没有被过滤,这认为可能存在漏洞。

0x02 总结

至此,这个代码分析结束。来个总结,dom xss的检测方法就是通过正则表达式来对一些有可能造成危害的函数进行匹配,并且匹配其参数是否可控。至于经过后端型xss,这里先是通过正则判断输出点在dom树中的位置,然后确定如果想要触发xss需要哪些字符不被过滤,接着再根据响应包中的payload中的特殊字符前是否有反斜杠来确定其是否被过滤从而确定是否满足上面的条件,满足则存在漏洞。

只有一百行的xss扫描工具——DSXS源码分析的更多相关文章

  1. 并发工具CyclicBarrier源码分析及应用

      本文首发于微信公众号[猿灯塔],转载引用请说明出处 今天呢!灯塔君跟大家讲: 并发工具CyclicBarrier源码分析及应用 一.CyclicBarrier简介 1.简介 CyclicBarri ...

  2. [软件测试]网站压测工具Webbench源码分析

    一.我与webbench二三事 Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能.Webbench ...

  3. bootstrap_栅格系统_响应式工具_源码分析

    -----------------------------------------------------------------------------margin 为负 ​使盒子重叠 ​等高 等高 ...

  4. 网站(Web)压测工具Webbench源码分析

    一.我与webbench二三事 Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能.Webbench ...

  5. 云实例初始化工具cloud-init源码分析

    源码分析 代码结构 cloud-init的代码结构如下: cloud-init ├── bash_completion # bash自动补全文件 │   └── cloud-init ├── Chan ...

  6. 并发工具CountDownLatch源码分析

    CountDownLatch的作用类似于Thread.join()方法,但比join()更加灵活.它可以等待多个线程(取决于实例化时声明的数量)都达到预期状态或者完成工作以后,通知其他正在等待的线程继 ...

  7. 多渠道打包工具Walle源码分析

    一.背景 首先了解多渠道打包工具Walle之前,我们需要先明确一个概念,什么是渠道包. 我们要知道在国内有无数大大小小的APP Store,每一个APP Store就是一个渠道.当我们把APP上传到A ...

  8. React躬行记(16)——React源码分析

    React可大致分为三部分:Core.Reconciler和Renderer,在阅读源码之前,首先需要搭建测试环境,为了方便起见,本文直接采用了网友搭建好的环境,React版本是16.8.6,与最新版 ...

  9. Node.js躬行记(19)——KOA源码分析(上)

    本次分析的KOA版本是2.13.1,它非常轻量,诸如路由.模板等功能默认都不提供,需要自己引入相关的中间件. 源码的目录结构比较简单,主要分为3部分,__tests__,lib和docs,从名称中就可 ...

随机推荐

  1. mysql 关于表与字段的增删改查操作

    1.mysql 命令登陆 形式: mysql -u用户名 -p密码 mysql -uroot -proot 2.mysql 显示数据库 形式: show databases; 3.mysql 进入某一 ...

  2. C#读取shp文件并获取图形保存到sde要素类中(不使用ESRI的类库,纯c#实现)

    说明:首先要将sde要素类发布成对应的要素服务,通过对要素服务的操作,实现数据在sde要素类中的增删 //向服务器发出请求 public string getPostData(string postS ...

  3. 二叉树,AVL树和红黑树

    为了接下来能更好的学习TreeMap和TreeSet,讲解一下二叉树,AVL树和红黑树. 1. 二叉查找树 2. AVL树 2.1. 树旋转 2.1.1. 左旋和右旋 2.1.2. 左左,右右,左右, ...

  4. Effective C++ 读书笔记(13-32)

    条款一十三:以对象管理资源 1.把资源放进对象内,我们便可依赖C++的“析构函数自动调用机制“确保资源被释放. 2.auto_ptr是个”类指针对象“,也就是所谓”智能指针“,其析构函数自动对其所指对 ...

  5. python爬虫入门(四)利用多线程爬虫

    多线程爬虫 先回顾前面学过的一些知识 1.一个cpu一次只能执行一个任务,多个cpu同时可以执行多个任务2.一个cpu一次只能执行一个进程,其它进程处于非运行状态3.进程里包含的执行单元叫线程,一个进 ...

  6. Java中的String类型

    1.基本类型和引用类型 在C语言里面,是有指针这么一个变量类型的,指针变量保存的就是所要指向内容的地址.在Java里面,没有了指针的这么个说法,而是换了一个词:引用类型变量. 先说Java里面的基本类 ...

  7. JS——函数

    一.函数的种类 1.无参函数 function showName() { alert("我是无参函数"); } 2.有参函数 在函数中的参数为"形式参数" 形式 ...

  8. Python_marshal模块操作二进制文件

    import marshal #导入模块 x1=30 #待序列化的对象 x2=5.0 x3=[1,2,3] x4=(4,5,6) x5={'a':1,'b':2,'c':3} x6={7,8,9} x ...

  9. Python_自定义有向图

    directedGraph.py class DirectedGraph(object): def __init__(self,d): if isinstance(d,dict): self.__gr ...

  10. android studio 在使用图片的时候会检测图片的合法性

    1.当android studio 在使用png格式的时候,会报一系列的错误,甚至会显示找不到R文件,这是因为Android studio 不支持png格式的图片,检测图片的合法性的时候会报错 解决方 ...