sqli-labs靶场通关笔记:第17关 POST请求的密码重置
一、审题
这关显示是密码重置的界面。在用户名的输入框内测试,发现注入语句都没有效果。
二、思考
查看一下源码,发现用户名输入框使用check_input()函数进行了过滤。
function check_input($value)
{// 1. 输入值非空检查if(!empty($value)) {// 2. 输入长度截断 (最多15字符)$value = substr($value,0,15);}// 3. 魔术引号处理if (get_magic_quotes_gpc()) {// 4. 移除自动添加的反斜杠$value = stripslashes($value);}// 5. 数字类型判断if (!ctype_digit($value)) {// 6. 非数字处理:转义+单引号包裹$value = "'" . mysql_real_escape_string($value) . "'";} else {// 7. 数字处理:转换为整数$value = intval($value);}return $value;
}
也就是说,必须输入真实有效的用户名,才能进行密码修改的操作,但是密码输入框没有做过滤。用户名输入admin,密码输入123456,提示修改成功。再修改密码,输入单引号,页面回显报错。
那么测试一下报错注入,发现是可以成功注入。
这里还需要注意一个问题,更新密码的操作是update,为数据操作语言(DML),而select是数据查询语言(DQL),两个不能在同一语句中执行,所以查询users表中字段数据会报错。
-1' and updatexml(1,concat(0x7e,(select group_concat(username,password) from users)),1) #
解决的办法就是,创建一个独立的子查询,将结果集作为一张临时表,然后通过查询临时表获取数据。
-1' and updatexml(1,concat(0x7e,(select group_concat(username,password) from (select username,password from users)a)),1)#
这里的(select username,password from users)a意思是执行一个独立的子查询作为临时表,别名为a,再将其整合到update语句中。
对于报错回显字符有限制的局限,可以使用字符串截断函数进行截断回显。
三、做法
爆数据库名,爆表名,爆字段,爆数据。