pyjail wiki

jailCTF 2025 - impossibler

Challenge

impossible の強化版。builtins が空。

import re
code = input()
# 許可: 小文字、コロン、アンダースコア、ドット、角括弧
if not re.match(r'^[a-z_:\.\[\]]+$', code):
exit()
eval(code, {'__builtins__': {}})

Solution

__typing_subst__ dunder (Python 3.11+)

Python 3.11 以降、型パラメータ構文で __typing_subst__ が呼ばれる:

# T[arg] で T.__typing_subst__(T, arg) が呼ばれる
# これを悪用して1引数の関数を呼び出し

サブクラスからの脱出

# builtins が空でもサブクラスチェーンは使える
().__class__.__bases__[0].__subclasses__()

完全なペイロード

# __typing_subst__ を使った関数呼び出し
# list comprehension で変数を設定
[x for x in ... if (setattr(...))]

Technical Details

__typing_subst__ の仕組み

Python 3.11 で導入された特殊メソッド:

from typing import TypeVar
T = TypeVar('T')
# T[int] は内部的に
T.__typing_subst__(T, int)
# を呼び出す

impossible との違い

項目impossibleimpossibler
builtinsありなし
難易度MediumHard
必要テクニック__getitem____typing_subst__ + subclasses

リスト内包表記での変数設定

# walrus 演算子は使えないが、for 文の変数は使える
[x for x in [target] for y in [setattr(...)]]

Alternative Solutions

別解1: generator の gi_frame

# フレームからbuiltinsにアクセス
(x for x in []).gi_frame.f_builtins

別解2: __class_getitem__

# 一部のクラスで使用可能
list[some_value]

Flag

jail{...}

References

  • jailCTF 2025 Official
  • Python 3.11 typing module changes