概述
不得不承认,Sqlmap是目前使用人数最多,功能最复杂的SQL注入工具。作为一款开源工具,开发者有意的让我们自行去阅读并对其进行扩充,从Github可以看出一直在更新的。对于渗透人员来说,阅读sqlmap源码是很有必要的,我们可以从它的源码之中学习到一些优秀的代码编写思维以及方式,应用到平时的渗透中去。
Sqlmap的结构
首先看看Sqlmap的目录结构:
目录说明:
|
|
Sqlmap的流程图如下所示:
概括起来就是当在命令行输入命令的时候,sqlmap首先会进行初始化的操作(版本检测、模块检测、命令行参数解析、Session读取等),之后便会简单的检测是否存在注入点,如果存在注入点便会进行进一步的注入,最后才是接管(takeover)操作。
Sqlmap初始化
大部分工具在进行攻击时都会进行初始化,Sqlmap也不例外。为了保证Sqlmap的正常运行首先需要进行python的版本、功能模块的自检。
|
|
在这之后才进入main()
函数,而main()
函数的开头便是检查环境(路径、版本)、输出banner信息、读取命令行参数。这里主要关注的是modulePath()
函数,为了方便在Windows以及Linux上运行,这里统一将操作系统的编码转化为Unicode编码后返回:
|
|
之后利用python的optionparser模块来对输入的参数进行分析,在此之前,提取出第一个参数前的内容,例python sqlmap.py作为参数传入OptionParser之后就是对参数进行分析了,首先是帮助、版本、log级有关参数。
|
|
主要显示如下:
接下来便是一个init()
函数,千万不要小看这个init()
函数,因为它做了很多很多的工作,当然它大部分与你输入的参数有关:
|
|
在初始化之后,便根据不同的需求运行不同的代码,如下所示:
前三个部分主要是软件的测试,和我们平时渗透没有多大关系,这里便不继续深究下去。
Sqlmap核心
数据库直连
sqlmap可以通过-d
参数来直接连接目标数据库,不过一般需要额外安装第三方模块。
|
|
读取Session
对一个网站进行sql注入测试的时候,sqlmap一般会在当前用户的目录下创建一个.sqlmap
目录,里面一般会保存目标网站的一些日志、注入点设置、session信息。session信息一般会以sqllite数据库文件的形式存储,里面主要是id、value两个字段,具体图如下:
它的value值一部分是以明文的形式存储,另一部是AttribDict
这个对象序列化后的以base64编码后的形式存储的。
注入标记符
接下来是检索注入标记符并给出提示询问是否对标记点检测注入,也就是我们常用的*
,来指定注入的位置。
|
|
action
sqlmap 的aciton比较简介,功能也比较清楚,主要就是根据我们的参数来dump相应的数据以及接管的操作,我稍微列举了几个有代表性的功能。
|
|
Waf指纹
接下来是加载WAF/IDS/IPS测试函数(可选参数),conf.identifyWaf对应的是--identify-waf
参数,sqlmap能够测试的WAF基本上是很齐全了,都在waf
目录中。
从上图中的右边代码可以清楚的看出,主要就是发送几个payload来查看服务器做出的回应。然后根据正则等方式进行waf的指纹匹配.
主要发送的payload我也看一下,由以下四部分组成:
|
|
crawl爬虫
sqlmap的爬虫模块主要--crawl
这个参数有关,可以收集潜在的可能存在漏洞的连接,后面跟的参数是爬行的深度。crawl函数在爬虫模块/lib/utils/crawler.py中。代码就不进行列举了,简单的说明下就是Sqlmap会创建一个visited队列和一个value队列,然后进行爬行,先将页面的url通过正则、sitemap之后放入value队列(去重),然后将爬过了url放入visited队列(去重),每次爬行时都会先看看是否已经visited。
接下来是--forms
,解析出页面的所有表单的功能实现。调用了/lib/core/common.py
中的findPageForms()
函数,而对于除了-u方式直接输入目标url的其他输入方式都采用先解析urls,再分别查表的方式
payload(核心)
Sqlmap最强大的就是它的注射技术,这也是它最为核心的部分。
Sqlmap启动后首先设置测试的level和risk,并识别受测试元素的类型,最终拼凑出相应的漏洞利用方案。
这里的payload它主要由boundaries
、payloads
、queries
这几部分组成,且都保存在xml目录下。
boundaries
boundaries.xml中保存了注入语句的前缀、后缀,主要就是用来闭合注入点处的前半部分和后半部分。举个例子来说: ?keyword=hello world
这里keyword
存在注入点,并且是搜索行注入,那么它在服务器端拼接成的语句就是:
|
|
所以sqlmap就需要闭合掉前面的引号和后面的引号,就可能会用到boundaries.xml的下列部分:
|
|
最终会闭合成:
|
|
payloads
xml/payloads
目标下保存着六种注入类型(基于布尔、基于时间、基于错误、union、内联、堆叠)的payload,一般以<test>
为结点,<test>
具有特定漏洞的全部信息,包括漏洞的level、risk,漏洞类型,利用的方法,检测方法等。主要格式如下:
|
|
queries
queries.xml主要就是具体的dump语句了:
|
|
example
在测试一个参数的时候sqlmap会遍历所有符合要求的test节点,会分别发送request与response节点下的payload,然后对服务器响应的数据包进行对比,看其是否存在差异,当确认存在注入的时候,就会以vector来加载queries.xml中的查询语句进行注入。
拿个实际注入的例子来说:
Tamper
Sqlmap 的Tamper模块主要就是用来绕waf用的,一般都保存在tamper
目录中,可以依据标准格式自定义,比如把payload用like替换等号,base64编码等…..,tamper都是具有一定的格式的,如果在渗透测试中发现sqlmap自带的tamper不符合,便可以依样画葫芦写个tamper出来:
下面是sqlmap自带的tamper,主要将等号替换成like的tamper:
|
|
Sqlmap接管
接下来是跟提权/后门/系统有关的模块,主要与takeover.py这类型的脚本有关。
下面是osCmd()
函数:
|
|
webshell
sqlmap自带了一部分的webshell,主要保存在shell
目录下,由stager(上传马)、backdoor(执行马),不过这些webshell被压缩过了:
php的上传马(stager):
php的执行马(backdoor):
各位有兴趣的可以改成自己的webshell,压缩的代码如下:
|
|
Sqlmap其他模块
文件粉碎
sqlmap自带了文件粉碎功能,可以安全删除文件,且无法恢复。主要由整理硬盘垃圾数据,获取文件句柄,填充垃圾数据,随机命名,最终删除这几个步骤组成。
|
|
Sqlmap api
如果我们要做二次开发,就可以直接利用这个sqlmap的api,通过进程通信的方式来完成sqlmap的功能,具体请参考这里。
异常汇报
在脚本运行中难免会碰到这样那样的错误,sqlmap因此做了很多异常捕获以及处理,如果sqlmap捕获到的异常它无法识别以及处理,便会上传到github上,因此来告知开发者对其进行bug的修复。
|
|
自动更新
这部分就不便多展开了,主要就是指sqlmap支持一键升级的功能:
总结
这几天大致阅读了Sqlmap的源码,才明白了Sqlmap的强大之处不仅仅在于它的注射功能,更在于它那优秀的代码编码方式、优秀的设计理念、Pythonic 的技巧、各种Python内置模块以及第三方模块的调用等等。也因此学习到了很多新的知识,比如临时文件的粉碎级别删除等等,看了它那优秀的编码后才明白自己平时渗透测试时写的脚本看上去狗爬一般。看来平时还得多抽空看看那些有些的渗透框架、工具,这样才可以尽量避免闭门造车,省去很多很多精力。