画像だと思って油断してない?SVGに隠された「忍び込むプログラム」の恐怖
こんにちは。現場で泥臭いインシデント対応を繰り返していると、時折「えっ、そんなところが入り口になるの?」という相談を受けます。
その代表格が、今回のテーマであるSVG画像です。
「画像ファイルなんだから、ただの絵でしょ?」と高を括っていると、気づかないうちにサイトが乗っ取られ、ユーザーの個人情報が盗まれる事態に発展します。今日は、なぜSVGが危険なのか、そしてどうやってそれを防ぐのか、家の防犯に例えて紐解いていきましょう。
—
1. SVGは「画像」ではなく「プログラム」だと思え
まず、一般的な画像(JPEGやPNG)を想像してみてください。これらは「画素の集まり」です。一方で、SVGは「図形を描くための命令書(XMLコード)」です。
家の防犯に例えるなら、JPEGが「ただの風景画のポスター」なら、SVGは「扉の開け方が書かれた設計図」のようなものです。
なぜ攻撃者はSVGを狙うのか?
SVGはXML形式なので、中にタグを埋め込むことができます。
もし、ユーザーがプロフィール画像としてこのSVGをアップロードし、ブラウザで直接開いてしまったらどうなるでしょう? ブラウザは「画像だ」と思って表示しようとしますが、同時に中のまで律儀に実行してしまいます。これがXSS(クロスサイトスクリプティング)の入り口です。
---
2. 攻撃の仕組み:泥棒は「信頼」を悪用する
XSSの怖さは、「そのサイトを信頼しているユーザーのブラウザ」で、攻撃者の命令が実行されることです。
1. 侵入: 攻撃者が掲示板やプロフィール設定に、細工したSVGをアップロードする。
2. 待機: ほかのユーザーがそのページを開く(あるいはSVGのURLを直接叩く)。
3. 実行: ブラウザがSVGを読み込み、中に隠されたスクリプトが「サイトの一部」として動き出す。
4. 被害: ログイン中のセッションIDが盗まれたり、偽の入力フォームを表示されたりする。
家で言えば、「近所の住人だと思って鍵を開けたら、実は変装した泥棒だった」という状況です。サイト側が「画像ファイルだから安心だろう」と無防備に受け入れていると、こうして悪意あるプログラムが中庭に入り込んでしまうのです。
---
3. どうやって防ぐ?「泥棒を家に入れない」ための鉄則
SVGの利便性は捨てたくないですよね。では、どうやって安全を確保すべきか。現場で必ず押さえるべきポイントは3つです。
① コンテンツタイプ(Content-Type)を固定する
ブラウザは、「ファイルの中身」を勝手に推測して実行しようとする癖があります。これを防ぐために、サーバーから「これは絶対に画像としてしか扱わせないぞ」という強い命令を送ります。
HTTPレスポンスヘッダーに以下を設定してください。
ブラウザの勝手な推測(MIMEスニッフィング)を禁止する
X-Content-Type-Options: nosniff
SVGをHTMLとして実行させないよう、適切なMIMEタイプを明示する
Content-Type: image/svg+xml
② 「防御の壁」を作る:Content Security Policy (CSP)
万が一、攻撃者にスクリプトを埋め込まれたとしても、「外と通信させない」「スクリプトを実行させない」というルールを課すのがCSPです。
スクリプトの実行を禁止し、外部との通信も制限する最強の防御
Content-Security-Policy: default-src 'self'; script-src 'none';
これをしておけば、SVG内のは「ルール違反!」としてブラウザが実行を拒否してくれます。
③ アップロード時に「消毒(サニタイズ)」する
一番確実なのは、画像としてアップロードされた瞬間に、中の「不穏なコード」を削除してしまうことです。
簡易的なイメージ:SVGからスクリプトタグを削除する処理(概念コード)
from bs4 import BeautifulSoup
def sanitize_svg(file_content):
soup = BeautifulSoup(file_content, 'xml')
# scriptタグやonload属性を徹底的に削除!
for script in soup.find_all('script'):
script.decompose()
# 他にもonmouseoverなどの属性も削除が必要
return str(soup)
---
最後に:セキュリティは「疑うこと」から始まる
セキュリティの世界に「完璧」はありません。しかし、SVGのように「便利そうに見えて実は危険」なものに対して、一歩立ち止まって「これはプログラムが含まれていないか?」と疑う姿勢が、あなたとユーザーを守る最強の武器になります。
まずは「アップロードされたファイルは信用しない」「ブラウザには厳格なルールを守らせる」という基本を徹底しましょう。
もし、「うちのサイトはどうかな?」と不安になったら、まずは開発者ツールを開いて、サイトのレスポンスヘッダーに X-Content-Type-Options: nosniff が付いているか確認するところから始めてみてください。一歩ずつ、強固な城を築いていきましょう!
コメント