pyjail wiki

UIUCTF 2024 - ASTea

Challenge

AST ベースのフィルタで特定のノードタイプが禁止された pyjail。

import ast
FORBIDDEN = {
ast.Import, ast.ImportFrom, ast.Call,
ast.Attribute, ast.Subscript
}
code = input()
tree = ast.parse(code)
for node in ast.walk(tree):
if type(node) in FORBIDDEN:
print("Forbidden!")
exit()
exec(code)

Solution

license() の利用

license() は対話的なページャーを起動する。ページャー (less など) からシェルコマンドを実行可能:

# less 内で
!sh

ただし Call が禁止されているため、直接呼び出せない。

AnnAssign (アノテーション付き代入)

# 変数アノテーション
x: int = 1
# AST では ast.AnnAssign
# annotation は通常の式として評価されない

デコレータの悪用

デコレータは関数呼び出しを生成するが、クラス定義と組み合わせて使用:

@decorator
class X: pass

実際のペイロード

Call を使わずにコードを実行:

# match 文を使用 (Python 3.10+)
match __builtins__:
case x:
# x から属性にアクセス

Technical Details

AST ノードタイプ

ノード
ast.Callf()
ast.Attributex.y
ast.Subscriptx[0]
ast.AnnAssignx: int = 1
ast.Matchmatch x:

禁止されていないノード

  • ast.Name - 名前参照
  • ast.BinOp - 二項演算
  • ast.Compare - 比較演算
  • ast.Match - パターンマッチ

Alternative Solutions

別解1: walrus 演算子

# := は NamedExpr
[x := something for _ in [1]]

別解2: f-string

# f-string は JoinedStr
f"{...}"

Flag

uiuctf{...}

References

  • UIUCTF 2024 Official
  • Python AST documentation