LACTF 2026 - pyjail
Challenge
Python 3.14 環境で、サブインタープリタ内で audit hook が設定された pyjail。
import concurrent.interpretersimport sys
def audit_hook(event, args): # 3回のauditイベントのみ許可 global audit_count audit_count += 1 if audit_count > 3: raise RuntimeError("Too many audit events")
sys.addaudithook(audit_hook)
interp = concurrent.interpreters.Interpreter()inp = input()[:67]
# 制限: 長さ67文字以下、printable ASCII のみ# 禁止文字: space, _, ., \, ", ', {}, #, =for c in inp: if c not in string.printable or c in ' _.\\"\'{#}=': exit()
interp.exec(f'print(eval("{inp}"))')Solution
concurrent.interpreters の悪用
Python 3.14 の concurrent.interpreters.Interpreter.call() はインタープリタ間でオブジェクトを pickle/unpickle する。audit hook はサブインタープリタ内にのみ存在するため、メインインタープリタでは監視されない。
__reduce_ex__ の上書き
exit オブジェクトの __reduce_ex__ を上書きしてシェルを実行:
# dir(0)[41] で '__' を取得# exit オブジェクトを操作ペイロード
禁止文字を避けながらペイロードを構築:
# dir(0)[41] は '__' を返す# これを使って dunder 属性にアクセスTechnical Details
Python 3.14 の新機能
concurrent.interpreters- サブインタープリタ間での通信- PEP 734 - Interpreter isolation
- pickle によるオブジェクト転送
audit hook の境界
# メインインタープリタsys.addaudithook(hook)
# サブインタープリタには継承されないinterp = concurrent.interpreters.Interpreter()interp.exec("...") # 別の audit 空間文字制限のバイパス
| 禁止 | 代替手段 |
|---|---|
_ | dir(0)[41] |
. | getattr() |
= | walrus := |
| スペース | 改行やタブ |
Flag
lactf{...}
References
- LACTF 2026 Official
- Python 3.14 concurrent.interpreters documentation