sqlmap工具

2021/12/14 安全工具

sqlmap工具基本使用

1、sqlmap介绍

官网: https://sqlmap.org/

sqlmap是一个开源的渗透测试工具,它可以自动化检测和利用SQL注入漏洞并接管数据库服务器。它有一个强大的检测引擎,许多适合于终极渗透测试的良好特性和众多的操作选项,从数据库指纹、数据获取到访问底层文件系统、执行操作系统命令。

2、特点

全面支持MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase和SAP MaxDB数据库管理系统。

全面支持六种SQL注入技术:boolean-based盲注、time-based盲注、error-based、UNION查询、堆叠查询和带外查询。

通过提供DBMS凭证、IP地址、端口和数据库名,支持不通过SQL注入的直接连接数据库。

支持枚举用户、密码哈希、特权、角色、数据库、表和列。

自动识别密码哈希格式,支持基于字典的攻击破解。

支持完整转储数据库表,根据用户的选择转储一定范围内的条目或特定列。用户还可以选择只从每列中转储指定字符。

支持搜索特定的数据库名、表名,或跨表搜索特定的列名。这非常有用,例如,识别包含自定义应用程序凭证的表,其相关列名称可能包含name、pass等字符串。

支持通过数据库服务器所在的文件系统下载和上传任何文件,当数据库软件是MySQL, PostgreSQL或Microsoft SQL server时。

支持在攻击者机器和数据库服务器所在操作系统之间建立带外有状态的TCP连接,这个通道根据用户的选择可以是交互式命令行、Meterpreter会话或图形用户界面(VNC)。

支持通过Metasploit的getsystem命令实现数据库进程的用户权限升级。

SQLMAP支持的注入方式:

  1. Boolean-basedblindSQLinjection(布尔型注入)
  2. Error-basedSQLinjection(报错型注入)
  3. UNIONquerySQLinjection(可联合查询注入)
  4. StackedqueriesSQLinjection(可多语句查询注入)
  5. Time-basedblindSQLinjection(基于时间延迟注入)
  6. InlineSQLInjection(内联注入)

3、下载

git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap

kali自带sqlmap

更新:

python sqlmap.py --update

可能会遇到更新不成功的情况,cd到父目录,然后rm -rf sqlmap之后再重新安装下载就是最新的了

4、常见命令

sqlmap -u "http://192.168.3.16/06/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -v 1

攻击完之后目标会进行缓存,目录在/sqlmap/output/target.txt中,如果需要重新攻击不走缓存的话可以把这个删掉,或者在后面加上参数--flush-session

  • -u 和–url参数一样 都是代表填写测试的url连接 如果存在&符号需要添加把url放在双引号内
  • -v 表示 输出信息详细程度级别:0-6(默认为 1)
  1. 0:只显示Python回源(tracebacks),错误(error)和关键(criticle)信息。
  2. 1:同时显示信息(info)和警告信息(warning)(默认为1)
  3. 2: 同时显示调试信息(debug)
  4. 3:同时显示注入的有效载荷(payloads)
  5. 4:同时显示http请求
  6. 5:同时显示http响应头
  7. 6:同时显示http响应内容

4.1 指定目标

可以指定单个url之外,还可以指定多个目标的文件,或者其他的日志以及谷歌搜索等

指定单个url

sqlmap -u http://target.com?id=1 -v 1 

从文件中加载HTTP请求测试

sqlmap -r url.txt 

url.txt文件内容:

GET /06/vul/sqli/sqli_str.php?name=2&submit=%E6%9F%A5%E8%AF%A2 HTTP/1.1
Host: 192.168.3.16
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://192.168.3.16/06/vul/sqli/sqli_str.php?name=2&submit=%E6%9F%A5%E8%AF%A2
Cookie: PHPSESSID=hrk724meg7ech0d4mdus8agtl2
Upgrade-Insecure-Requests: 1

上面这个包是通过burp suite抓的,还可以使用sqlmap -l post.txt读取burpsuite或者日志的HTTP包

也可以从文本中读取多个目标进行扫描

sqlmap -m url.txt

# http://target.com?id=1 -v 1
# http://target.com?id=2 -v 1
# http://target.com?id=3 -v 1

sqlmap可以测试注入google的搜索结果中的get参数

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

4.2 http请求

http数据,参数 --data

此参数是把数据以post方式提交,sqlmap会自动检测post参数

sqlmap -u http://192.168.3.16/06/vul/sqli/sqli_id.php --data="id=1&submit=查询"

参数拆分字符,参数:–param-del

当GET或POST的数据需要用其他字符分割测试参数的时候需要用到此参数。

sqlmap -u "http://www.target.com/vuln.php" --data="query=foobar;id=1" --param-del=";"
# param-del=";" 表示参数--data="query=foobar;id=1"里面的分号是分隔符,不是参数的数据

4.3 cookie、头信息

cookie参数:--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头参数:--user-agent,--random-agent

可以使用–user-agent参数来修改,同时也可以使用–random-agent参数来随机的从./txt/user-agents.txt中获取。当–level参数设定为3或者3以上的时候,会尝试对User-Angent进行注入。

Referer头 参数:--referer

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

额外的HTTP头 参数:--headers

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

HTTP认证保护 参数:--auth-type,--auth-cred

这些参数可以用来登陆HTTP的认证保护支持三种方式:

  1. Basic
  2. Digest
  3. NTLM
sqlmap -u "http://192.168.136.131/sqlmap/mysql/basic/get_int.php?id=1" --auth-type Basic --auth-cred "testuser:testpass"

4.4 HTTP协议的证书认证

参数:--auth-cert

当Web服务器需要客户端证书进行身份验证时,需要提供两个文件:key_file,cert_file。

key_file是格式为PEM文件,包含着你的私钥,cert_file是格式为PEM的连接文件。

4.5 HTTP(S)代理

参数:--proxy,--proxy-cred--ignore-proxy

使用–proxy代理是格式为:http://url:port

当HTTP(S)代理需要认证是可以使用–proxy-cred参数:username:password。

–ignore-proxy拒绝使用本地局域网的HTTP(S)代理。

4.6 HTTP请求延迟

参数:--delay

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

4.7 设定超时时间

参数:--timeout

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

4.8 设定重试超时

参数:--retries

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

4.9 设定随机改变的参数值

参数:--randomize

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

4.10 利用正则过滤目标网址

参数:–scope

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

4.11 避免过多的错误请求被屏蔽

参数:--safe-url,--safe-freq

有的web应用程序会在你多次访问错误的请求时屏蔽掉你以后的所有请求,这样在sqlmap进行探测或者注入的时候可能造成错误请求而触发这个策略,导致以后无法进行。

绕过这个策略有两种方式:

  1. --safe-url:提供一个安全不错误的连接,每隔一段时间都会去访问一下。
  2. --safe-freq:提供一个安全不错误的连接,每次测试请求之后都会再访问一边安全连接。

4.12 关掉URL参数值编码

参数:--skip-urlencode

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

4.13 每次请求时候执行自定义的python代码

参数:--eval

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

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

上面的请求就是每次请求时根据id参数值,做一次md5后作为hash参数的值。

5、注入

5.1 测试参数

参数:-p,--skip

sqlmap默认测试所有的GET和POST参数,当–level的值大于等于2的时候也会测试HTTP Cookie头的值,当大于等于3的时候也会测试User-Agent和HTTP Referer头的值。但是你可以手动用-p参数设置想要测试的参数。例如: -p "id,user-anget"

当你使用–level的值很大但是有个别参数不想测试的时候可以使用–skip参数。例如:--skip="user-angent.referer"

在有些时候web服务器使用了URL重写,导致无法直接使用sqlmap测试参数,可以在想测试的参数后面加*,例如:

sqlmap -u "http://targeturl/param1/value1*/param2/value2/"

sqlmap将会测试value1的位置是否可注入。

5.2 指定数据库

参数:--dbms

默认情况系sqlmap会自动的探测web应用后端的数据库是什么,sqlmap支持的数据库有

MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access、SQLite、Firebird、Sybase、SAP MaxDB、DB2

5.3 指定数据库服务器系统

参数:--os

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

5.4 指定无效的大数字

参数:--invalid-bignum

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

5.5 指定无效的逻辑

参数:--invalid-logical

可以指定id=13把原来的id=-13的报错改成id=13 AND 18=19。

5.6 注入payload

参数:--prefix,--suffix

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

例如,代码中是这样调用数据库的:

$query = "SELECT * FROM users WHERE id=(’" . $_GET[id] . "’) LIMIT 0, 1";

这时你就需要–prefix和–suffix参数了:

sqlmap -u "http://192.168.136.131/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "’)" --suffix "AND (’abc’=’abc"

这样执行的SQL语句变成:

$query = "SELECT * FROM users WHERE id=(’1’) <PAYLOAD> AND (’abc’=’abc’) LIMIT 0, 1";

5.7 修改注入的数据

参数:--tamper

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

6、探测

6.1 探测等级

参数:--level

共有五个等级,默认为1,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload。

这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试。

总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值。

6.2 风险等级

参数:–risk

共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。

在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。

测试的语句同样可以在xml/payloads.xml中找到,你也可以自行添加payload。

6.3 页面比较

参数:–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标签中不同)。

7、注入技术

7.1 测试是否是注入

参数:--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(基于时间延迟注入) 

7.2 设定延迟注入的时间

参数:--time-sec

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

7.3 设定UNION查询字段数

参数:--union-cols

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

7.4 设定UNION查询使用的字符

参数:--union-char

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

7.5 二阶SQL注入

参数:--second-order

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

8、列数据

8.1 标志

参数:-b,--banner

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

8.2 用户

参数:-current-user

在大多数据库中可以获取到管理数据的用户。

8.3 当前数据库

参数:--current-db

返还当前连接的数据库。

8.4 当前用户是否为管理用

参数:--is-dba

判断当前的用户是否为管理,是的话会返回True。

8.5 列数据库管理用户

参数:--users

当前用户有权限读取包含所有用户的表的权限时,就可以列出所有管理用户。

8.6 列出并破解数据库用户的hash

参数:--passwords

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

例子:

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --passwords -v 1
[...]
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不仅勒出数据库的用户跟密码,同时也识别出是PostgreSQL数据库,并询问用户是否采用字典爆破的方式进行破解,这个爆破已经支持Oracle和Microsoft SQL Server。

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

8.7 列出数据库管理员权限

参数:--privileges

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

8.8 列出数据库管理员角色

参数:--roles

当前用户有权限读取包含所有用户的表的权限时,很可能列举出每个用户的角色,也可以用-U参数指定你想看哪个用户的角色。

仅适用于当前数据库是Oracle的时候。

8.9 列出数据库系统的数据库

参数:--dbs

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

8.10 列举数据库表

参数:--tables,--exclude-sysdbs,-D

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

如果你不提供-D参数来列指定的一个数据的时候,sqlmap会列出数据库所有库的所有表。

--exclude-sysdbs参数是指包含了所有的系统数据库。

需要注意的是在Oracle中你需要提供的是TABLESPACE_NAME而不是数据库名称。

8.11 列举数据库表中的字段

参数:--columns,-C,-T,-D

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

如果没有使用-D参数指定数据库时,默认会使用当前数据库。

列举一个SQLite的例子:

sqlmap -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" --columns -D testdb -T users -C name
[...]
Database: SQLite_masterdb
Table: users
[3 columns]
+---------+---------+
| Column  | Type    |
+---------+---------+
| id      | INTEGER |
| name    | TEXT    |
| surname | TEXT    |
+---------+---------+

8.12 列举数据库系统的架构

参数:--schema,--exclude-sysdbs

用户可以用此参数获取数据库的架构,包含所有的数据库,表和字段,以及各自的类型。

加上–exclude-sysdbs参数,将不会获取数据库自带的系统库内容。

sqlmap -u "http://192.168.48.130/sqlmap/mysql/get_int.php?id=1" --schema --batch --exclude-sysdbs

8.13 获取表中数据个数

参数:--count

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

sqlmap -u "http://192.168.21.129/sqlmap/mssql/iis/get_int.asp?id=1" --count -D testdb

8.14 获取整个表的数据

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

如果当前管理员有权限读取数据库其中的一个表的话,那么就能获取真个表的所有内容。

使用-D,-T参数指定想要获取哪个库的哪个表,不适用-D参数时,默认使用当前库。

sqlmap -u "http://192.168.136.131/sqlmap/firebird/get_int.php?id=1" --dump -T users
[...]
Database: Firebird_masterdb
Table: USERS
[4 entries]
+----+--------+------------+
| ID | NAME   | SURNAME    |
+----+--------+------------+
| 1  | luther | blisset    |
| 2  | fluffy | bunny      |
| 3  | wu     | ming       |
| 4  | NULL   | nameisnull |
+----+--------+------------+

可以获取指定库中的所有表的内容,只用-dump跟-D参数(不使用-T与-C参数)。

也可以用-dump跟-C获取指定的字段内容。

sqlmap为每个表生成了一个CSV文件。

如果你只想获取一段数据,可以使用–start和–stop参数,例如,你只想获取第一段数据可hi使用–stop 1,如果想获取第二段与第三段数据,使用参数 –start 1 –stop 3。

也可以用–first与–last参数,获取第几个字符到第几个字符的内容,如果你想获取字段中地三个字符到第五个字符的内容,使用–first 3 –last 5,只在盲注的时候使用,因为其他方式可以准确的获取注入内容,不需要一个字符一个字符的猜解。

8.15 获取所有数据库表的内容

参数:--dump-all,--exclude-sysdbs

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

8.16 搜索字段,表,数据库

参数:--search,-C,-T,-D

–search可以用来寻找特定的数据库名,所有数据库中的特定表名,所有数据库表中的特定字段。

可以在一下三种情况下使用:

  1. -C后跟着用逗号分割的列名,将会在所有数据库表中搜索指定的列名。
  2. -T后跟着用逗号分割的表名,将会在所有数据库中搜索指定的表名
  3. -D后跟着用逗号分割的库名,将会在所有数据库中搜索指定的库名。

8.17 运行自定义的SQL语句

参数:--sql-query,--sql-shell

sqlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句。

如果是SELECT查询语句,sqlap将会输出结果。如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句。

sqlmap -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --sql-query "SELECT 'foo'" -v 1

9、爆破

9.1 暴力破解表名

参数:--common-tables

当使用–tables无法获取到数据库的表时,可以使用此参数。

通常是如下情况:

  1. MySQL数据库版本小于5.0,没有information_schema表。
  2. 数据库是Microssoft Access,系统表MSysObjects是不可读的(默认)。
  3. 当前用户没有权限读取系统中保存数据结构的表的权限。

暴力破解的表在txt/common-tables.txt文件中,你可以自己添加。

9.2 暴力破解列名

参数:--common-columns

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

10、用户自定义函数注入

参数:--udf-inject,--shared-lib

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

Search

    Table of Contents