tp5.1注入分析

背景

上次遇到的盲猜的注入,其实我之前跟过流程,但是很明显的失败了

不知道为什么在cltphp中可以爆出数据库及一些数据

  • 最终结果是
    • cltphplinux下无法完成注入
    • Windows下可以完成,因为不区分大小写

但是在之前的测试中默认的配置是不存在notlike的注入问题的

故记录:

  • tp5.0tp5.1关于notlike的框架差异
  • cltphp和默认tp5.1的差异

分析

tp5.0和5.1差异

tp5.0中,notlike的注入支持#--+等符号来注释

如下

1609825952642

但是在tp5.1中,使用#或者--+都会出现参数绑定的问题

#绑定参数是出现错误

1609826036388

--+则是不匹配的问题

1609826061297

经过分析发现

tp5.0中在绑定参数是,bind为空,无需进行绑定

1609826414405

tp5.1中则是需要进行绑定

1609826489602

那么问题肯定就是出在对like表达式的处理上了

tp5.0like的处理

通过parseValue对传入的参数值进行处理,此时的item值依然为111'

1609826734078

跟进方法

可以发现,不存在:绑定符号,进入qoute方法进行处理

1609826841494

进入此方法后,只是通过PDO参数的类型进行了转义,并未进行bind之类的操作

1609826913739

所以返回的值直接为转义后的值,无需进行参数绑定

1609826961536

下面就是直接将logic拼接,所以在query方法中bind参数为空

1609827078945

tp5.1like的处理

tp5.1就很简单了,定义了parseLike方法,方法中进行了参数绑定的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected function parseLike(Query $query, $key, $exp, $value, $field, $bindType, $logic)
{
// 模糊匹配
if (is_array($value)) {
foreach ($value as $item) {
$name = $query->bind($item, $bindType);
$array[] = $key . ' ' . $exp . ' :' . $name;
}

$whereStr = '(' . implode(' ' . strtoupper($logic) . ' ', $array) . ')';
} else {
$whereStr = $key . ' ' . $exp . ' ' . $value;
}

return $whereStr;
}

tp5.1和cltphp配置差异

默认情况下,如下代码,未进行警告或者error

1
2
3
4
5
<?php
$a = array(0=>"a");
list($b,$c) = $a;
print_r($b);
print_r($c);

但是在默认的tp框架中会爆下标1不存在

1609828553930

原因:目标cms的配置文件中关闭了错误

1609828611410

end

结语:

  • tp5.1Request类去掉了表达式的过滤
    • 导致like可注入
  • tp5.1exists表达式的写法问题,可能导致注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
protected function parseWhereItem($logic, $field, $op, $condition, $param = [])
{
if (is_array($op)) {
// 同一字段多条件查询
array_unshift($param, $field);
$where = $param;
} elseif ($field && is_null($condition)) {
if (in_array(strtoupper($op), ['NULL', 'NOTNULL', 'NOT NULL'], true)) {
// null查询
$where = [$field, $op, ''];
} elseif (in_array($op, ['=', 'eq', 'EQ', null], true)) {
$where = [$field, 'NULL', ''];
} elseif (in_array($op, ['<>', 'neq', 'NEQ'], true)) {
$where = [$field, 'NOTNULL', ''];
} else {
// 字段相等查询
$where = [$field, '=', $op];
}
} elseif (in_array(strtoupper($op), ['EXISTS', 'NOT EXISTS', 'NOTEXISTS'], true)) {
$where = [$field, $op, is_string($condition) ? $this->raw($condition) : $condition];
} else {
$where = $field ? [$field, $op, $condition, isset($param[2]) ? $param[2] : null] : null;
}

return $where;
}