thinkphp 5.1.x 反序列化漏洞分析.md
利用链1
1 |
|
存在__destruct()
方法
跟进removeFiles(),file_exists在处理filename时会当成字符串处理,只要让构造$this->files
为包含类的数组就可以调用__toString()
1 |
|
存在_toString()
toJson()
调用toArray()
toArray()
需要让$this->visible
为空,$this->hidden
为空,调用getAttr()
。$data
由$this->data
和$this->merge
合并而成。
getAttr()
满足条件isset($this->withAttr[$fieldName])
即可命令执行,参数可控
1 |
|
getData()
,需要满足第二个条件$this->data
数组中存在$name
键,即可返回$this->data[$name]
1 |
|
Loader::parseName
parseName会把大写字母转为小写并在前面加上_,如A
变成_a
,不影响payload的构造
函数名为$closure = $this->withAttr[$fieldName];
,$fieldName
来源于经过Loader::parseName
函数处理的getAttr()
函数参数$name
,而getAttr()
函数参数等于$data
的键名$key
,$data
由$this->data
和$this->merge
合并而成。最终等于$this->withAttr[$key]
。让数组$this->withAttr
与$this->data
有相同的键名即可
执行命令:$value=$this->getData($name)
,$name
为getAttr()
参数,在getData()
函数中只要满足array_key_exists($name, $this->data
)就会返回$this->data[$name]
,$name
为传入参数等于键值$key,最终等于$this->data[$key]
。
利用
构造exp
1 |
|
利用链2
前面的触发点都一样,区别在toArray()
这里
toArray()
调用_call()
方法,首先遍历数组$this->append
,当键值$name
为数组时满足is_array($name)
。让$relation
等于类名即可触发_call()
在这之前按需要满足3个条件
1 |
|
getRelation()
满足array_key_exists($name, $this->relation)
就会返回$this->relation[$name]
。$name
就是$this->append
数组中的键名。需要让$this->relation[$name]
等于空才能满足!$relation
执行下面的语句。
getAttr()
返回$value,也就是经过getData()
处理的参数$key
getData()
,$name
就是$this->append
数组中的键名$key
,最终返回$this->data[$name]
,让它等于一个存在__call()
方法且不存在visable()
方法的类即可调用__call
1 |
|
__call()
,由于array_unshift()
会修改参数数组,造成执行命令不可控,所以没办法直接利用这个call_user_func_array
,只能寻找新的利用点
filterValue()
函数中存在call_user_func
,但是$value
不可控,不能直接利用
input()
函数中调用了filterValue()
,参数不可控不能直接利用
param()
函数调用input()
,执行$this->input($this->param, $name, $default, $filter);
,参数仍不可控。
isAjax()
调用param()
,参数$this->config['var_ajax']
可控,这样param()
函数中的$name
参数可控,这样input()
函数中的$name
可控。param()
函数可以接收$_GET
数组赋值给$this->param
,这样input()
函数的前两个参数$this->param
和$name
都可控了
回到input()
函数,传入filterValue()
函数的第一个参数$data
和第三个$filter
是执行命令的关键。$data等于$this->getData($data,$name)
,两个函数参数就是input()
传入的参数$this->param
和$name
。而$filter
等于$this->getFilter($filter, $default);
getData()
,最终$data
= $data[$val]
= $data[$name]
,也就是$this->param[$this->config['var_ajax']]
getFilter()
,$filter
来源于$this->filter
利用
构造exp
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!