零、前言
这篇文章是学习Sqlmap的用法时做的笔记,记录了Sqlmap的常见、基础用法。
一、Sqlmap是什么
Sqlmap是开源的自动化SQL注入工具,由Python写成,具有如下特点:
- 完全支持MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、IBM DB2、SQLite、Firebird、Sybase、SAP MaxDB、HSQLDB和Informix等多种数据库管理系统。
- 完全支持布尔型盲注、时间型盲注、基于错误信息的注入、联合查询注入和堆查询注入。
- 在数据库证书、IP地址、端口和数据库名等条件允许的情况下支持不通过SQL注入点而直接连接数据库。
- 支持枚举用户、密码、哈希、权限、角色、数据库、数据表和列。
- 支持自动识别密码哈希格式并通过字典破解密码哈希。
- 支持完全地下载某个数据库中的某个表,也可以只下载某个表中的某几列,甚至只下载某一列中的部分数据,这完全取决于用户的选择。
- 支持在数据库管理系统中搜索指定的数据库名、表名或列名
- 当数据库管理系统是MySQL、PostgreSQL或Microsoft SQL Server时支持下载或上传文件。
- 当数据库管理系统是MySQL、PostgreSQL或Microsoft SQL Server时支持执行任意命令并回现标准输出。
二、安装Sqlmap
Sqlmap的开源项目,托管在github,最简单的安装方式便是使用git,执行如下命令:
git clone https://github.com/sqlmapproject/sqlmap.git
片刻后命令执行完毕,可以看到当前目录中多了一个名为“sqlmap”的目录, 该目录中保存着Sqlmap的Python源码、配置文件和文档。 由于Python是解释执行的语言,不用编译,所以至此最新版的Sqlmap已经安装完成。 cd到“sqlmap”目录中,用命令“python sqlmap”启动Sqlmap,如下图所示:
当想要更新Sqlmap时,进入到“sqlmap”目录中执行命令“git pull”即可。
三、输出级别(Output verbosity)
参数:-v
Sqlmap的输出信息按从简到繁共分为7个级别(和葫芦娃一样多),依次为0、1、2、3、4、5和6。使用参数“-v <级别>”来指定某个等级,如使用参数“-v 6”来指定输出级别为6。默认输出级别为1。各个输出级别的描述如下:
- 0:只显示Python的tracebacks信息、错误信息[ERROR]和关键信息[CRITICAL];
- 1:同时显示普通信息[INFO]和警告信息[WARNING];
- 2:同时显示调试信息[DEBUG];
- 3:同时显示注入使用的攻击荷载;
- 4:同时显示HTTP请求;
- 5:同时显示HTTP响应头;
- 6:同时显示HTTP响应体。
各个级别输出的信息详细到什么程度,还需要自己尝试下,亲眼见到,才会有明确的认识。
四、指定目标
Sqlmap运行时必须指定至少一个目标,支持一次指定多个目标。有以下几种指定目标的方式:
1.直接连接数据库
参数:-d
使用参数“-d”直接连接数据库,该参数后跟一个表示数据库的字符串,该字符串有以下两种格式:
(1).当数据库管理系统是MySQL、Oracle、Microsoft SQL Server或PostgreSQL等时格式为:
DBMS://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME
(2).当数据库管理系统是SQLite、Microsoft Access或Firebird等时格式为:
DBMS://DATABASE_FILEPATH
我用如下命令连接装在本机上的Mysql:
python sqlmap.py -d "mysql://root:root@127.0.0.1:3306/DISSchool"
却出现了错误,错误为:
[CRITICAL] sqlmap requires 'python-pymysql' third-party library in order to directly connect to the DBMS 'MySQL'. You can download it from 'https://github.com/petehunt/PyMySQL/'. Alternative is to use a package 'python-sqlalchemy' with support for dialect 'mysql' installed
意思是我没有安装Python连接Mysql用的第三方库python-pymysql。虽然我安装了python-mysqldb可以使Python连接Mysql,但显然Sqlmap使用的是python-pymysql而不是python-mysqldb。使用如下命令安装python-pymysql:
git clone https://github.com/petehunt/PyMySQL/
cd PyMySQL/
sudo python setup.py install
安装好python-pymysql后再执行命令:
python sqlmap.py -d "mysql://root:root@127.0.0.1:3306/DISSchool"
这次没有报错,成功的连接到了数据库。只是除了检测数据库确实是Mysql版本号大于等于5.0.0之外便什么都没有做。让Sqlmap做点什么需要用其他参数指定,这些参数我们稍晚些再学习。
2.指定目标URL
参数:-u 或 --url
使用参数“-u”或“--url”指定一个URL作为目标,该参数后跟一个表示URL的字符串,可以是http协议也可以是https协议,还可以指定端口,如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php?id=0"
3.从Burp或WebScarab的代理日志中解析目标
参数:-l
使用参数“-l”指定一个Burp或WebScarab的代理日志文件,Sqlmap将从日志文件中解析出可能的攻击目标,并逐个尝试进行注入。该参数后跟一个表示日志文件的路径。
WebScarab我没有用过,Burp倒是常常会用。Burp默认不记录日志,想要记录日志需要手动开启,设置方法如下图所示:
只用勾选代理中的请求数据就足够了,日志文件路径可随意设置,这里我设置日志文件名为proxy.log,放在用户主目录中。
设置浏览器的代理为Burp,随便浏览几个网页后发现proxy.log竟然已经有70多K大,查看其内容,部分输出如下:
werner@Yasser:~$ more proxy.log
======================================================
7:22:52 PM http://ocsp.digicert.com:80 [117.18.237.29]
======================================================
POST / HTTP/1.1
Host: ocsp.digicert.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Length: 83
Content-Type: application/ocsp-request
DNT: 1
Connection: close
0Q0O0M0K0I0 +
�ǝ��Pr�Tz�
======================================================
======================================================
7:23:00 PM http://blog.csdn.net:80 [47.95.49.160]
======================================================
GET /pyufftj/article/details/21469201 HTTP/1.1
Host: blog.csdn.net
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
...
可以看到该日志文件不仅记录了GET参数,还记录了cookie和POST参数。现在使用如下命令让Sqlmap解析该日志文件,自动寻找目标,检测注入漏洞:
python sqlmap.py -l ../proxy.log
注意日志文件的路径要写正确。执行该命令时,每找到一个可能的攻击目标,Sqlmap都会询问是否要检测该目标。,默认回答为“Y”,想要测试该目标,直接按回车键就行。
当日志较大时会有很多可能目标,虽然有询问机制但依旧麻烦,因为不能一路按回车而要进行判断。若是可以对日志进行过滤就好了!确实是可以的,参数为“--scope”,详情见“五.18”。
4.从站点地图文件中解析目标
参数:-x
为便于搜索引擎收录,许多网站专门为搜索引擎生成了xml格式的站点地图,如[百度Sitemap支持xml格式][Sitemap_xml]。Sqlmap可以直接解析xml格式的站点地图,从中提取攻击目标,对一个网站全方位无死角地进行注入检测,此时使用的参数是“-x”,如:
python sqlmap.py -x http://www.6eat.com/sitemap.xml
但执行该命令的结果却是:
[WARNING] no usable links found (with GET parameters)
没有找到有GET参数的可用链接。就我有限的经验而言,站点地图中的URL很少包含GET参数,POST参数就更不用说了。所以Sqlmap的这一功能似乎有些鸡肋。
5.从文本文件中解析目标
参数:-m
参数“-u”一次只能指定一个URL,若有多个URL需要测试就显得很不方便,我们可用将多个URL以一行一个的格式保存在文本文件中,然后使用参数“-m”,后跟该文本文件路径,让Sqlmap依次读取文件中的URL作为攻击目标。
如我们有文件url.txt,内容为:
www.target1.com/vuln1.php?q=foobar
www.target2.com/vuln2.asp?id=1
www.target3.com/vuln3/id/1*
然后可用使用如下命令让Sqlmap测试这些URL是否存在注入漏洞:
python sqlmap.py -m url.txt
同样,执行该命令时,Sqlmap会很贴心地一个个询问:“do you want to test this URL?”
6.从文件载入HTTP请求
参数:-r
可以将一个HTTP请求保存在文件中,然后使用参数“-r”加载该文件,Sqlmap会解析该文件,从该文件分析目标并进行测试。
设有如下所示的HTTP请求保存在文件get.txt中:
GET /user.php?id=1 HTTP/1.1
Host: 192.168.56.101:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
则使用如下命令让Sqlmap解析该文件,以该文件中HTTP请求目标为攻击目标进行测试:
python sqlmap.py -r get.txt
7.将Google搜索结果作为攻击目标
参数:-g
Sqlmap能自动获取Google搜索的前一百个结果,对其中有GET参数的URL进行注入测试。当然,所处的网络环境要能访问Google才行。下面是Sqlmap手册中“-g”参数的例子:
python sqlmap.py -g "inurl:\".php?id=1\""
8.从配置文件中载入攻击目标
参数:-c
使用参数“-c”指定一个配置文件(如:sqlmap.conf),Sqlmap会解析该配置文件,按照该配置文件的配置执行动作。配置文件中可以指定攻击目标,实际上除了攻击目标外,配置文件还可以指定各种参数的值。
Sqlmap的按照目录中有一个名为sqlmap.conf的文件,该文件是配置文件的模板,看看该文件内容,就能明白配置文件是什么意思了。
五、请求
HTTP是一个复杂的协议。HTTP请求有很多种方法(method),可以在不同位置(GET、POST、cookie和User-Agent等)携带不同参数。往往只有在特定位置携带了特定参数以特定方法发起的请求才是合法有效的请求。Sqlmap运行时除了需要指定目标,有时还需要指定HTTP请求的一些细节。下面这些参数都用于指定HTTP请求细节。
1.HTTP方法
参数:--method
一般来说,Sqlmap能自动判断出是使用GET方法还是POST方法,但在某些情况下需要的可能是PUT等很少见的方法,此时就需要用参数“--method”来指定方法。如:“--method=PUT”。
2.POST数据
参数:--data
该参数指定的数据会被作为POST数据提交,Sqlmap也会检测该参数指定数据是否存在注入漏洞。如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php" --data="id=0&name=werner"
3.指定分隔符
参数:--param-del
上一个例子中“--data”的数据“id=0&name=werner”其实由两个部分组成:“id=0”和“name=werner”,默认地以“&”作为分隔符。我们可以使用“--param-del”来指定分隔符,如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php" --data="id=0;name=werner" --param-del=";"
4.cookie
参数:--cookie、--cookie-del、--drop-set-cookie和--load-cookies
有两种情况会用到这些参数:
- 要测试的页面只有在登录状态下才能访问,登录状态用cookie识别
- 想要检测是否存在cookie注入
当“--level”设置为2或更高时,Sqlmap会检测cookie是否存在注入漏洞,关于“--level”的更多信息见下文。
(1).“--cookie”和“--cookie-del”
在浏览器中登录目标网站后复制出维持登录状态的cookie,用参数“--cookie”来指定这些cookie,如:
python sqlmap.py -u "http://192.168.56.102:8080/user.php" --cookie "JSESSIONID=E5D6C8C81;NAME=werner;"
与POST参数不同,cookie默认的分隔符为“;”,想要指定cookie中的分隔符,使用参数“--cookie-del”。
(2).“--drop-set-cookie”
若HTTP响应头中有“Set-Cookie”,Sqlmap会自动设置“Set-Cookie”设置的cookie,并对这些cookie进行检测。若不想让Sqlmap这么做,添加参数“--drop-set-cookie”即可,这样,Sqlmap会忽略“Set-Cookie”。
(3).“--load-cookies”
该参数用于从文件中载入Netscape或wget格式的cookie。
wget可以保存和载入cookie,示例如下:
# Log in to the server. This can be done only once.
wget --save-cookies cookies.txt \
--post-data 'user=foo&password=bar' \
http://server.com/auth.php
# Now grab the page or pages we care about.
wget --load-cookies cookies.txt \
-p http://server.com/interesting/article.php
5.User-Agent
参数:--user-agent和--random-agent
默认情况下Sqlmap发送的HTTP请求中的User-Agent值为:
sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org)
使用参数“--user-agent”可以指定一个User-Agent值。但正常的User-Agent值长什么样我们可能并不记得,所以有了参数“--random-agent”,使用该参数,Sqlmap会从文件./txt/user-agents.txt中随机地取一个User-Agent。注意,在一次会话中只有使用同一个User-Agent,并不是每发一个HTTP请求包,都随机一个User-Agent。
用如下命令统计user-agents.txt行数:
cat sqlmap/txt/user-agents.txt | wc -l
结果为4211,当然其中还包含空行、注释等,但总的来说该文件中存储的User-Agent也有4千多个。
当“--level”设置为3或更高时,Sqlmap会检测User-Agent是否存在注入漏洞,关于“--level”的更多信息见下文。
6.Host
参数:--host
使用该参数可以手动指定HTTP头中的Host值。
当“--level”设置为5或更高时,Sqlmap会检测Host是否存在注入漏洞,关于“--level”的更多信息见下文。
7.Referer
参数:--referer
使用该参数可以指定HTTP头中的Referer值。Sqlmap发送的HTTP请求头部默认无Referer字段。
当“--level”设置为3或更高时,Sqlmap会检测Referer是否存在注入漏洞,关于“--level”的更多信息见下文。
8.额外的HTTP头
参数:--headers
使用该参数可以在Sqlmap发送的HTTP请求报文头部添加字段,若添加多个字段,用“\n”分隔。如命令:
python sqlmap.py -u "http://192.168.56.101:8080/" -v 5 --headers "X-A:A\nX-B: B"
发送的HTTP请求包为:
GET / HTTP/1.1
X-B: B
Host: 192.168.56.101:8080
Accept-encoding: gzip,deflate
X-A: A
Accept: */*
User-agent: sqlmap/1.1.10#stable (http://sqlmap.org)
Connection: close
加参数“-v 5”是为了让Sqlamp输出发送的HTTP请求包,便于我们观察。
9.身份认证
参数:--auth-type和--auth-cred
这些参数用于进行身份认证。“--auth-type”用于指定认证方式,支持以下三种身份认证方式:
- Basic
- Digest
- NTLM
“--auth-cred”用于给出身份认证的凭证,格式是“username:password”。
如:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id=1" --auth-type Basic --auth-cred "testuser:testpass"
10.基于证书的身份认证
参数:--auth-file
若Web服务器要求客户端提供证书则可以使用此参数指定一个PEM格式的证书文件。我们知道SSL协议的客户端认证是可选的,实践中一般都只用服务器端提供自己的证书供客户端验证,很少要求客户端提供自己的证书。
11.忽略401
参数:--ignore-401
使用该参数忽略401错误(未认证)。
12.HTTP(S)代理
参数:--proxy、--proxy-cred、--proxy-file和--ignore-proxy
使用参数“--proxy”来设置一个HTTP(S)代理,格式是“http(s)/url:port”。若代理需要认证,使用参数“--proxy-cred”来提供认证凭证,格式是“username:password”。
使用参数“--proxy-file”指定一个存储着代理列表的文件,Sqlmap会依次使用文件中的代理,当某个代理有任何连接问题时就会被弃用而换下一个代理。
使用参数“--ignore-proxy”忽略本地代理设置。
13.Tor匿名网络
参数:--tor、--tor-type、--tor-port和--check-tor
不管出于什么原因,如果想要保持匿名状态与其使用单个的HTTP(S)代理,不如安装类似Privoxy这样的软件按照[Tor的安装指导][Tor]配置一个Tor客户端。设置好后使用参数“--tor”让Sqlmap自动设置使用Tor代理。
如果想要手动指定Tor的类型和端口可以使用参数“--tor-type”和“--tor-port”,如:
--tor-type=SOCKS5 --tor-port 9050
如果要求高度的匿名性可以使用参数“--check-tor”,加上该参数后Sqlmap会确保所有流量都走Tor代理,若Tor代理失效,Sqlmap会发出警告并退出。检测方法是访问[Are you using Tor?][Are you using Tor]。
14.HTTP请求之间添加延迟
参数:--delay
过于频繁地发送请求可能会被网站察觉或有其他不良后果。使用参数“--delay”来指定HTTP请求之间的延迟,单位为秒,类型是浮点数,如“--delay 1.5”表示延迟1.5秒。默认是没有延迟的。
15.超时
参数:--timeout
超时时间默认为30秒,可以用参数“--timeout”指定超时时间,如“--timeout 44.5”表示设置超时时间为44.5秒。
16.超时后最大重试次数
参数:--retries
超时后Sqlmap会进行重试,最大重试次数默认为3,可以用参数“--retries”指定最大重试次数。
17.随机化参数值
参数:--randomize
使用该参数,Sqlmap会随机生成每次HTTP请求中参数的值,值的类型和长度依照于原始值。
18.用正则表达式过滤代理日志
参数:--scope
指定一个Python正则表达式对代理日志进行过滤,只测试符合正则表达式的目标,如:
python sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"
19.避免错误请求过多而被屏蔽
参数:--safe-url、--safe-post、--safe-req和--safe-freq
有时服务器检测到某个客户端错误请求过多会对其进行屏蔽,而Sqlmap的测试往往会产生大量错误请求,为避免被屏蔽,可以时不时的产生几个正常请求以迷惑服务器。有以下四个参数与这一机制有关:
- --safe-url: 隔一会就访问一下的安全URL
- --safe-post: 访问安全URL时携带的POST数据
- --safe-req: 从文件中载入安全HTTP请求
- --safe-freq: 每次测试请求之后都会访问一下的安全URL
这里所谓的安全URL是指访问会返回200、没有任何报错的URL。相应地,Sqlmap也不会对安全URL进行任何注入测试。
20.关闭URL编码
参数:--skip-urlencode
Sqlmap默认会对URL进行URL编码,可以使用该参数关闭URL编码。
21.绕过CSRF保护
参数:--csrf-token和--csrf-url
现在有很多网站通过在表单中添加值为随机生成的token的隐藏字段来防止CSRF攻击,Sqlmap会自动识别出这种保护方式并绕过。但自动识别有可能失效,此时就要用到这两个参数。
“--csrf-token”用于指定包含token的隐藏字段名,若这个字段名不是常见的防止CSRF攻击的字段名Sqlmap可能不能自动识别出,需要手动指定。如Django中该字段名为“csrfmiddlewaretoken”,明显与CSRF攻击有关。
“--csrf-url”用于从任意的URL中回收token值。若最初有漏洞的目标URL中没有包含token值而又要求在其他地址提取token值时该参数就很有用。
22.强制使用SSL
参数:--force-ssl
23.在每次请求前执行特定Python代码
参数:--eval
直接看例子:
python sqlmap.py -u "http://www.target.com/vuln.php?id=1&hash=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"
每次返送请求前,Sqlmap都会依据id值重新计算hash值并更新GET请求中的hash值