过程解析:
姿势一:
通过以上测试,可以判断出后端sql语句很大可能如下: Select $_POST[‘query’] || flag from 相应的库名 那么这个相应的库名到底是什么呢,因为这里输入字符串后没有回显,而且后端动态sql如上,所以可以猜测这里可能存在推叠注入
在mysql中||实现的是逻辑or的功能,所以其实这里我们不需要关注它到底在什么库中,只需要通过构造 *,1 的payload即可获得flag。之所以是这样具体原理是:在mysql中,对于||来说,如果输入的是数字则非0即真(当判断结果为true时,mysql返回的结果为1);而若输入的是以’ ’或” ”包裹的字符串则会被默认你输入的是0即假(当判断结果为False时,mysql返回的结果为0);若你输入的字符串没有使用’ ’或” ”进行包裹则mysql会将其理解成你输入的是该表中的某一列的列名,而若该列名实际并不存在于该表中则mysql会报错,若存在如语句为uid||username时,mysql会以类似于python中for的逻辑来执行,即遍历该表中uid于username的值然后将其一一对应进行||的判断。而若只是执行select uid || username from users; 则mysql会回显一个以uid || username为列、以判断结果为值的列表,而users表中的其它字段的信息时不会回显的,除非你这样写:select username,uid || username from users.这样在回显时就会带出username字段中记录的所有值。
姿势二:
第一种其实是比较偏的解法,之所以说比较偏是因为姿势一并没有利用到这道题中的堆叠注入,其实就是没有利用所有可以利用的条件。当然因为这是平常做题所以尽可能的去探究更多的解法,而若是在其它场景中当然快、准、狠的解法就是好的解法。在姿势二开始之前需要了解以下知识点: || 在大多数的数据库中都表示的是字符串连接操作符,只有在mysql数据库中默认实现的是逻辑or的功能,所以解法二就是通过设置mysql的全局变量将 || 的功能更换为字符串连接操作符。具体payload如下: 1;set sql_mode=pipes_as_concat;select 1 之所以这里在末尾加上select 1是因为我发现它可能每一次的post请求更改数据库全局变量后等数据库执行完sql语句后会重置变量的值。
更改为字符串连接符后动态sql语句如下: Select 1 || flag from Flag 这里mysql的执行逻辑如下: (1)select 1 from Flag //先在Flag表中查询字段1,得到结果1
(2)Select flag from Flag //在Flag表中查询字段flag的值,得到flag
(3)将(1)和(2)中查询的结果拼接在一起然后作为以1 || flag为列名的值回显。
相关知识点:
(1)在mysql中 || 默认实现逻辑or的功能
(2)在mysql中可以通过设置sql_mode=pipes_as_concat 来将 || 的逻辑变成字符串连接操作符