Kap0k的老大哥们豪🐂,加油啊
d3pythonhttp
I love using various Python web frameworks to create my projects~
nc 106.14.121.29:31084
文档里有压缩包
阅读源码
frontend
- jwt的kid绕过,目录遍历(或者可读都可以)或者使用sql注入
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
111from flask import Flask, request, redirect, render_template_string, make_response
import jwt
import json
import http.client
app = Flask(__name__)
login_form = """
<form method="post">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Login">
</form>
"""
# 签名可通过,登录后才可以访问
def index():
token = request.cookies.get('token')
if token and verify_token(token):
# options是指定jwt.decode的选项,verify_signature为False表示不验证签名,但是verify_token中会验证
return "Hello " + jwt.decode(token, algorithms=["HS256"], options={"verify_signature": False})["username"]
else:
return redirect("/login", code=302)
# 可以用来设置token
def login():
if request.method == "POST":
user_info = {"username": request.form["username"], "isadmin": False}
key = get_key("frontend_key") # 我们要获取key啊
token = jwt.encode(user_info, key, algorithm="HS256", headers={"kid": "frontend_key"})
resp = make_response(redirect("/", code=302))
resp.set_cookie("token", token)
return resp
else:
return render_template_string(login_form)
def proxy_to_backend():
forward_url = "python-backend:8080"
conn = http.client.HTTPConnection(forward_url)
method = request.method
# 难道有原型链污染?没有哥们,想多了
headers = {key: value for (key, value) in request.headers if key != "Host"}
data = request.data
path = "/"
if request.query_string:
path += "?" + request.query_string.decode()
conn.request(method, path, body=data, headers=headers) # 单纯进行转发(要看后端处理逻辑,头部等都用了) --> 加特殊头?
response = conn.getresponse()
return response.read()
# 需要isadmin,有转发到后端 --> 具体还要看后端
def admin():
token = request.cookies.get('token')
if token and verify_token(token):
if request.method == 'POST':
# 不对签名验证,但是需要设置isadmin为true
if jwt.decode(token, algorithms=['HS256'], options={"verify_signature": False})['isadmin']:
forward_url = "python-backend:8080"
conn = http.client.HTTPConnection(forward_url)
method = request.method
headers = {key: value for (key, value) in request.headers if key != 'Host'}
data = request.data
path = "/"
if request.query_string:
path += "?" + request.query_string.decode()
if headers.get("Transfer-Encoding", "").lower() == "chunked": # 这个是特殊操作 --> 了解一下
data = "{}\r\n{}\r\n0\r\n\r\n".format(hex(len(data))[2:], data.decode()) # 会在data发送时加上长度并构造http的post请求
if "BackdoorPasswordOnlyForAdmin" not in data: # data中需要有特殊字符串
return "You are not an admin!"
conn.request(method, "/backdoor", body=data, headers=headers)
return "Done!"
else:
return "You are not an admin!"
else:
if jwt.decode(token, algorithms=['HS256'], options={"verify_signature": False})['isadmin']:
return "Welcome admin!"
else:
return "You are not an admin!"
else:
return redirect("/login", code=302)
def get_key(kid):
key = ""
dir = "/app/"
try:
with open(dir+kid, "r") as f:
key = f.read()
except:
pass
print(key)
return key
# jwt --> kid绕过
def verify_token(token):
header = jwt.get_unverified_header(token)
kid = header["kid"]
key = get_key(kid)
try:
payload = jwt.decode(token, key, algorithms=["HS256"])
return True
except:
return False
if __name__ == "__main__":
app.run(host = "0.0.0.0", port = 8081, debug=False)backend
- backend和frontend一个需要BackdoorPasswordOnlyForAdmin一个不需要,了解一下Transfer-Encoding,可以拿来做东西
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
32import web # web模块的,有点意思
import pickle
import base64
urls = (
'/', 'index',
'/backdoor', 'backdoor'
)
web.config.debug = False # 非debug模式
app = web.application(urls, globals())
class index:
def GET(self):
return "welcome to the backend!"
class backdoor:
def POST(self):
data = web.data()
# fix this backdoor
if b"BackdoorPasswordOnlyForAdmin" in data: # 特征值检测
return "You are an admin!"
else:
# 打pickle
data = base64.b64decode(data)
pickle.loads(data)
return "Done!"
if __name__ == "__main__":
app.run()
看一下web模块的内容