关于tp5的一种注入场景
前言
在控制器中如果where方法的参数完全可控
Db::name('users')->where($_POST['a'])->select();
则存在多种形式的注入,但是这种场景基本不会出现
在这种模式下衍生的最舒服的注入形式莫过于
Db::name('users')->where('id='.$_POST['a'])->select();
这是很常规的一种拼接注入
今天遇到一种实际的场景,不存在于控制器中,存在于model中
实际代码
1 | $ck = json_decode(cookie('merchant'), true); |
分析
可以想到的是这里向get方法中传进的参数是完全可控的
跟进model的get方法
进入了parseQuery方法处理我们传入的data
跟进此方法后可以看到,当我们传入的参数是数组的时候,会进入where方法
跟进where方法
跟进parseWhereExp方法
我们传入的数组,会进入下面的分支中
处理完毕,置空data变量,并调用find方法
跟进find方法,这里有一处很重要的方法就是getpk方法
进入gettableinfo方法
这里会有一个获取数据哭的所有字段,并判断器绑定类型,保存在bind参数中
这里获取到的字段均为id
,username
等形式
接下来会进入build中
直接定位到parseWhereItem方法中
映入眼帘的是第二个关键点parseKey方法
跟进后可以发现,这里的处理方式不仅仅处理了id
或者username
的形式
同样处理了user.id
或者user.username
的形式
第三个关键点
这是第一次参数绑定的条件
之前的notlike注入就是没有进入这个条件
因为它不满足is_scalar($value)
条件
正常经过下exists是必进入这个条件的,但是现在可以去看第二个条件
array_key_exists($field, $binds)
此时bind参数的类型
1 | $bind = array( |
我们传入user.id
很明显不在这个数组中,直接跳过
完成拼接注入
复现
以上面的漏洞案例
测试结果如下
poc
1 | merchant={"id":{"user.id":["exists","select 1) and (updatexml(1,concat(0x7e,user()),1))-- 1"]}} |