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'))
@app.route('/about') def about(): return render_template('about.html')
if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=False)
|