SVGのサニタイズに関する悩み
16時間前原文(muffin.ink)
概要
- ScratchはSVG関連の脆弱性を長年抱えている
- SVGのサニタイズ対策は毎年新たな問題が発覚し続けている
- XSSやHTTPリークなど多様な攻撃手法が発見されてきた
- 複雑化するサニタイズ処理でも完全な安全性は実現できていない
- 今後も新たな脆弱性が発生し続ける可能性が高い
ScratchにおけるSVGサニタイズの歴史と課題
- Scratchはユーザー生成SVGをDOMに挿入し、信頼性の高いバウンディングボックス計測などの目的で利用
- SVGのDOM挿入はどんなに短時間でも根本的に危険な操作
- サニタイズのために複雑なパーサやフィルタを増築するアプローチを採用
- しかし根本的な解決には至らず、毎年新しい抜け道が発見される状況
2019年:scriptタグによるXSS
- SVG内の**<script>タグ**でJavaScriptが実行され、XSSが発生
- 攻撃者は他ユーザーの権限でコメント投稿・プロジェクト削除等が可能
- Scratch DesktopではNode.js統合により任意コード実行にも発展
- 正規表現でscriptタグ除去することで一時的に対策
2020年:正規表現の不備によるXSS(CVE-2020-7750)
- **大文字<SCRIPT>**やイベントハンドラ属性(onerror等)で回避可能
- DOMPurify導入でscript除去を強化
2022年:image要素のhrefによるHTTPリーク
- <image>要素のhref属性で外部リクエスト発生
- DOMPurifyは実行コードは除去するがHTTPリークは防げず
- IPアドレス漏洩や位置情報推測が可能
- DOMPurifyのフックで外部URLのhrefを除去することで対策
2023年:CSS @importによるHTTPリーク
- <style>内の**@import**で外部リクエスト誘発
- JavaScript製CSSパーサを導入し、@importを除去
2024年:Paper.js経由のXSS
- サニタイズ前のSVGがPaper.js(コスチュームエディタ用ライブラリ)に渡されXSS
- scratch-svg-rendererだけでなくPaper.js読み込み時にもサニタイズ適用
- サーバー側でも何らかの保護があるとされるが詳細不明
2025年:CSS url()によるHTTPリーク
- CSSの**url()**関数で外部リクエスト発生
- style属性や<style>内のurl()を検出し除去する処理を追加
2026年:サニタイズコードのバグによるHTTPリーク
- エスケープコードによるurl()の回避
- style属性内で複数のurl()がある場合の不備
- CSS変数(var(--name))経由のurl()参照
- さらなる複雑なサニタイズ処理追加で対応
2026年:長大なCSSトランジションによる全ページ再スタイリング
- SVG内の長いtransitionと全要素へのtransform適用で、ページ全体のスタイルを攻撃者が操作可能
- reportボタン非表示、likeボタン巨大化、偽の案内表示などフィッシング等の悪用例
- 現在も未修正
2026年:image-set()によるHTTPリーク
- CSSの**image-set()**関数で外部リクエスト発生
- url()以外の方法でHTTPリークが可能
- 現時点で未修正
20XX年:新しいCSS仕様による将来的なHTTPリーク
- CSS Units Level 4やCSS Images Level 4など新仕様の実装進展で、また新たな攻撃手法が登場する可能性
サニタイズの限界と今後の展望
- SVGサニタイズの複雑化は進むが、イタチごっこの様相
- SVG仕様・CSS仕様の拡張やブラウザ実装の変化により新たな抜け道が定期的に発生
- 根本的な安全性確保は困難であり、SVGのDOM挿入自体を極力避ける設計が望ましい
- Scratchに限らず、ユーザー生成SVGを扱う全てのサービスで同様のリスクが存在