为何LAMP应用的UNION注入Payload无效?是否需调整逻辑?
你的思路之所以行不通,是因为UNION注入只适用于有结果集返回的SELECT查询语句,而你当前的操作是增、改、删(INSERT/UPDATE/DELETE)这类DML语句——这类语句本身不返回查询结果,UNION SELECT的语法逻辑根本无法在DML语句中生效。
1. 新增查询功能实现UNION注入
要让UNION注入可用,必须给应用添加用户可控输入参与SELECT查询,且查询结果会回显到前端的逻辑。比如添加一个"按VIN查询里程"的功能,后端代码写成完全无防护的动态拼接形式:
// 前端传入查询用的VIN参数 $query_vin = $_POST['query_vin']; // 动态拼接SELECT语句 $sql = "SELECT vin, mileage FROM cars WHERE vin = '$query_vin'"; $result = mysqli_query($conn, $sql); // 将查询结果输出到前端页面 while ($row = mysqli_fetch_assoc($result)) { echo "VIN: {$row['vin']},里程:{$row['mileage']}<br>"; }
此时就可以构造有效UNION注入Payload了,比如输入:123' UNION SELECT user(), version()--
拼接后的SQL为:
SELECT vin, mileage FROM cars WHERE vin = '123' UNION SELECT user(), version()-- '
因为前后两个SELECT的列数一致(都是2列),数据库会合并结果集,前端就能直接显示出数据库用户名和版本信息,UNION注入成功。
2. 针对现有增改删语句实现其他类型注入
如果不想新增查询功能,也可以基于现有DML语句构造可利用的注入,比如:
报错注入
利用MySQL的报错函数(如updatexml)触发数据库报错,让敏感信息随错误提示泄露。比如在VIN参数中输入:123' OR updatexml(1, concat(0x7e, user(), 0x7e), 1)--
拼接后的SQL会触发报错,若前端显示数据库错误信息,就能直接看到当前数据库用户。
布尔盲注
通过构造条件判断语句,利用"插入成功/失败"的差异来猜解数据。比如判断数据库用户名首字符是否为'r':123' AND SUBSTRING(user(),1,1)='r'--
若条件为真,数据正常插入;若为假,插入失败。通过反复调整条件,就能逐步猜解出完整的敏感数据。
时间盲注
通过sleep()函数的延迟效果判断条件真假,比如:123' AND IF(SUBSTRING(user(),1,1)='r', sleep(5), 0)--
如果页面加载延迟5秒,说明条件成立,反之则不成立。
- 要确保PHP代码完全不做输入转义(比如不能用
mysqli_real_escape_string)、不使用预处理语句,否则注入会被阻断。 - MySQL 8.0中,
updatexml等报错函数仍可使用,但注意其返回内容有长度限制,过长的数据需要分段获取。 - 若前端不显示错误信息,盲注是唯一可行的方向,时间盲注无需页面回显差异,适用性更强。
内容的提问来源于stack exchange,提问作者Guy

