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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
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)
# Database Models
class Account:
def __init__(self, uid, pwd):
self.uid = uid
self.pwd = pwd
class Session:
def __init__(self, meta):
self.meta = meta
# Mock Database
users_db = [
Account("admin", os.urandom(16).hex()),
Account("guest", "guest")
]
# Security Configuration
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__'
]
# Helper Functions
def register_user(username, password):
"""Register a new user if username doesn't exist"""
for acc in users_db:
if acc.uid == username:
return False
users_db.append(Account(username, password))
return True
def waf(serialized):
"""Web Application Firewall to prevent dangerous deserialization"""
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"
# Routes
@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 all([username, password, 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():
"""Authentication endpoint"""
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():
"""User control 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格式错误。")
if waf(decoded):
return render_template('error.html', error="请不要黑客攻击!")
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="数据解码失败。")
@app.route('/vault')
def vault():
"""Admin-only 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)
|