1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| from flask import Flask, request, make_response, render_template, redirect, url_for import jsonpickle import base64 import json import os import time
app = Flask(__name__) app.secret_key = os.urandom(24)
class Account: def __init__(self, uid, pwd): self.uid = uid self.pwd = pwd
class Session: def __init__(self, meta): self.meta = meta users_db = [ Account("admin", os.urandom(16).hex()), Account("guest", "guest") ] def register_user(username, password): for acc in users_db: if acc.uid == username: return False users_db.append(Account(username, password)) return True
FORBIDDEN = [ 'builtins', 'os', 'system', 'repr', '__class__', 'subprocess', 'popen', 'Popen', 'nt', 'code', 'reduce', 'compile', 'command', 'pty', 'platform', 'pdb', 'pickle', 'marshal', 'socket', 'threading', 'multiprocessing', 'signal', 'traceback', 'inspect', '\\\\', 'posix', 'render_template', 'jsonpickle', 'cgi', 'execfile', 'importlib', 'sys', 'shutil', 'state', 'import', 'ctypes', 'timeit', 'input', 'open', 'codecs', 'base64', 'jinja2', 're', 'json', 'file', 'write', 'read', 'globals', 'locals', 'getattr', 'setattr', 'delattr', 'uuid', '__import__', '__globals__', '__code__', '__closure__', '__func__', '__self__', 'pydoc', '__module__', '__dict__', '__mro__', '__subclasses__', '__init__', '__new__' ] def waf(serialized): try: data = json.loads(serialized) payload = json.dumps(data, ensure_ascii=False) for bad in FORBIDDEN: if bad in payload: return bad return None except: return "error" @app.route('/') def root(): return render_template('index.html') @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') confirm_password = request.form.get('confirm_password')
if not username or not password or not confirm_password: return render_template('register.html', error="所有字段都是必填的。")
if password != confirm_password: return render_template('register.html', error="密码不匹配。")
if len(username) < 4 or len(password) < 6: return render_template('register.html', error="用户名至少需要4个字符,密码至少需要6个字符。")
if register_user(username, password): return render_template('index.html', message="注册成功!请登录。") else: return render_template('register.html', error="用户名已存在。")
return render_template('register.html') @app.post('/auth') def auth(): u = request.form.get("u") p = request.form.get("p") for acc in users_db: if acc.uid == u and acc.pwd == p: sess_data = Session({'user': u, 'ts': int(time.time())}) token_raw = jsonpickle.encode(sess_data) b64_token = base64.b64encode(token_raw.encode()).decode() resp = make_response("登录成功。") resp.set_cookie("authz", b64_token) resp.status_code = 302 resp.headers['Location'] = '/panel' return resp return render_template('index.html', error="登录失败。用户名或密码无效。") @app.route('/panel') def panel(): token = request.cookies.get("authz") if not token: return redirect(url_for('root', error="缺少Token。"))
try: decoded = base64.b64decode(token.encode()).decode() except: return render_template('error.html', error="Token格式错误。")
ban = waf(decoded) if waf(decoded): return render_template('error.html', error=f"请不要黑客攻击!{ban}")
try: sess_obj = jsonpickle.decode(decoded, safe=True) meta = sess_obj.meta
if meta.get("user") != "admin": return render_template('user_panel.html', username=meta.get('user'))
return render_template('admin_panel.html') except Exception as e: return render_template('error.html', error=f"数据解码失败。") @app.route('/vault') def vault(): token = request.cookies.get("authz") if not token: return redirect(url_for('root'))
try: decoded = base64.b64decode(token.encode()).decode() if waf(decoded): return render_template('error.html', error="请不要尝试黑客攻击!") sess_obj = jsonpickle.decode(decoded, safe=True) meta = sess_obj.meta
if meta.get("user") != "admin": return render_template('error.html', error="访问被拒绝。只有管理员才能查看此页面。")
flag = "NepCTF{fake_flag_this_is_not_the_real_one}"
return render_template('vault.html', flag=flag) except: return redirect(url_for('root'))
if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=False)
|