代码审计
反序列化
解题 信息搜集首先打开是一个登录框,尝试sql无果
注册登录,发现一个文件上传页面
先试试文件上传,会将jpg文件转换为png,文件名随机生成
dirsearch扫一下目录,有备份文件www.tar.gz
解压后是一个tp5的框架
代码审计打开文件后有两个断点
application/web/controller/Index.php
在访问大部分页面时都会调用到login_check
方法,该方法将传入的用户信息反序列化,再到数据库中进行检查
application/web/controller/Register.php
析构方法,判断是否注册,未注册则跳转到主页
再查看一下文件上传部分的代码
application/web/controller/Profile.php
public function upload_img(){
if($this->checker){
if(!$this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
}
}
if(!empty($_FILES)){
$this->filename_tmp=$_FILES['upload_file']['tmp_name'];
$this->filename=md5($_FILES['upload_file']['name']).".png";
$this->ext_check();
}
if($this->ext) {
if(getimagesize($this->filename_tmp)) {
@copy($this->filename_tmp, $this->filename);
@unlink($this->filename_tmp);
$this->img="../upload/$this->upload_menu/$this->filename";
$this->update_img();
}else{
$this->error('Forbidden type!', url('../index'));
}
}else{
$this->error('Unknow file type!', url('../index'));
}
}
先检查是否登录,接着判断文件是否存在,再获取文件后缀,解析是否为正常图片,之后再将其从临时路径拷贝到目标路径
同时该文件下还有两个魔术方法
public function __get($name)
{
return $this->except[$name];
}
public function __call($name, $arguments)
{
if($this->{$name}){
$this->{$this->{$name}}($arguments);
}
}
我们可以利用反序列化和魔术方法来控制upload_img方法,从而任意更改文件名
首先构造一个Register类,通过反序列化调用析构函数,调用checker成员变量再调用index方法。
由于输出可控,我们将checker赋值为Profile对象,之后调用index方法就可以触发__call
方法
此时我们调用this->index
,访问一个不存在的属性就会触发__get
方法
而expect参数可控,我们将Profile的成员变量except赋值为以index为数组键,upload_img()为键值的数组$except=['index'=>'upload_img']
因此在__call
方法中,可以成功调用upload_img方法
public function upload_img(){
if($this->checker){
if(!$this->checker->login_check()){
$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
$this->redirect($curr_url,302);
exit();
}
}
if(!empty($_FILES)){
$this->filename_tmp=$_FILES['upload_file']['tmp_name'];
$this->filename=md5($_FILES['upload_file']['name']).".png";
$this->ext_check();
}
if($this->ext) {
if(getimagesize($this->filename_tmp)) {
@copy($this->filename_tmp, $this->filename);
@unlink($this->filename_tmp);
$this->img="../upload/$this->upload_menu/$this->filename";
$this->update_img();
}else{
$this->error('Forbidden type!', url('../index'));
}
}else{
$this->error('Unknow file type!', url('../index'));
}
}
进入函数,将checker赋值为0,绕过判断,再将ext赋值为1,此时把$filename_tmp
赋值为上传的图片马的路径,而覆盖的文件名$filename
赋值为以php结尾的文件
POC:
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?