| SQLインジェクション対策はおすみですか? 開発開始時点からのコンサルティングから、公開済みWebサイトの脆弱性検査、 脆弱性発見後の適切な対策まで |
2007-12-10 イメージファイトのまとめ
●画像ファイルによるクロスサイト・スクリプティング(XSS)傾向と対策
最近、画像ファイルを用いたクロスサイト・スクリプティングが注目されている。本稿では、画像を悪用したXSSについて説明した後、対策方法について解説する。
画像によるXSSとはどのようなものか
Internet Explorer(IE)の特性として、コンテンツの種類を判別する際に、レスポンスヘッダ内のContent-Typeだけでなく、コンテンツの内容も判断基準にしている。このため、Content-Typeが例えばimage/gif(GIF画像)となっていても、中身がHTMLであればHTMLと解釈して表示する。このため、JavaScriptが埋め込まれていたら、JavaScriptを実行することになる。
例を示そう。このファイル(html.gif)は、拡張子は.gifなので、ダウンロードするとContent-Typeはimage/gifとなるが、内容はHTMLでありJavaScriptが埋め込んである。これをIEとFirefoxで表示した例を以下に示そう。
| IE7での表示 | ![]() |
| Firefoxでの表示 | ![]() |
IEが、状況によってはContent-Typeを無視して、画像をHTMLと解釈し内部に埋め込まれたJavaScriptを実行してしまう。これによるXSSが成立する場合がある。典型的な状況とてしは、画像のアップロード機能を有するアルバム・サービスのような場合だ。たとえば、はてなの画像アップロードシステムには、この脆弱性があったとして、対応がなされたことがある。
下図は、画像によるXSSの模式図である。攻撃者(左側のサングラスの人物)は、攻撃用JavaScriptを仕込んだ画像を、maitter.com画像アップロードシステムを利用して登録・公開し、この画像のURLをダウンロードするよう、メールやブログなどで誘導する。被害者がこの誘導に引っかかって画像を閲覧すると、JavaScriptが実行され、maitter.comドメインのCookieが盗難されるなどの被害にあう。

先に示したhtml.gifは内容はhtmlテキストだけという素朴なものだが、イメージそのもの、パレット、コメントなどにhtmlやJavaScriptを仕込む手法が知られている(*1)。
対策の検討
IEがコンテンツの種類をどのように判別しているかは公開されていないようだが、たとえば2007年10月10日に公開されたマイクロソフト セキュリティ情報 MS07-057には以下のような記述がある。
PNGs が MIME スニッフィング アルゴリズム の jpg/gif と同じ状態に昇格されます。例: サーバーが png のコンテンツの種類を送信した場合、Internet Explorer は magic-byte (マジックバイト) のテストを実行し、成功した場合、権限のあるサーバーの MIME の種類として処理します。
意味のとりにくい日本語(機械翻訳?)だが、どうもコンテンツの種類判別にIEがマジックバイトを利用しているらしいことがわかる。
マジックバイトとは
マジックバイトとは、画像などのフォーマットを判別しやすいように、ファイルの先頭の数バイトに置かれた固定のデータである。GIF形式の場合であれば、"GIF87a"あるいは"GIF89a"で始まることになっており、先頭6文字を見ればGIF形式であることが容易に判別できる。下表に、主な画像形式のマジックバイトを示そう。
| 画像形式 | BMP | GIF | JPEG | PNG |
|---|---|---|---|---|
| マジックバイト | BM | GIF8[79]a | \xFF\xD8 | \x89PNG\x0D\x0A\x1A\x0A |
IEのコンテンツ種類判別はContent-Typeとマジックバイトの組み合わせ
以上の情報などから、どうもIEのコンテンツ種類判別は、Content-Typeとマジックバイトの組み合わせにより決まるように思える。これを検証するために、主要な画像フォーマット4種(BMP、GIF、JPEG、PNG)のContent-Typeとマジックバイトの全ての組み合わせを試してみた。検証用に用いたサンプルデータは、マジックバイトとJavaScriptを組み合わせただけの簡単なものである。一例を下図に示す(GIF形式の偽画像)。

結果は下表の通りである。表で、「HTML」となっている欄はHTMLと判別され、JavaScriptが起動するもの、「画像」となっているのは、画像と解釈しようとしたが表示できないため「×」表示となることを示している。これらはリンクとなっていて、実際のサンプルデータで試すことが出来るようにした。
| 画像種類 | マジックバイト | Content-Type | |||
|---|---|---|---|---|---|
| image/bmp | image/gif | image/jpeg | image/png | ||
| BMP | BM | HTML | HTML | HTML | HTML |
| GIF | GIF87a | HTML | 画像 | HTML | HTML |
| JPEG | xFFxD8 | HTML | HTML | 画像 | HTML |
| PNG | \x89PNG\x0d\x0a\x1a\0a | HTML | HTML | HTML | 画像(*2) |
この表から分かることは以下の二点である
- Content-Typeとマジックバイトは同一の画像フォーマットに対応したものでなければならず、不一致だとHTMLとみなされる(可能性がある)
- BMP形式に関しては、Content-Typeとマジックバイトの両方を揃えても、なおHTMLとみなされる場合がある
なお、マジックバイトのContent-TypeからPNG形式を判定するようになったのは、前述のようにMS07-057(2007年10月10日)適用後のことであるので、ちょうど2ヶ月前からのことである。
対策:ではどうすればよいか
従来、画像XSSの対策には、イメージを他の形式に変換してから元の形式に戻す、あるいは竹迫氏のmod_imagefightのように画像中にXSS防御文字列を挿入するなど、さまざまな手法が提案されている。しかしながら、対策として不十分であったり、画質や処理速度の低下を招くなどさまざまな副作用があった。
マイクロソフトがMS07-057にてPNG画像のコンテンツ種別判定を改善してくれたことから、Content-Typeとマジックバイトの判定のみで、画像XSSを予防できる可能性が高くなった。
これでもまだ、BMP形式については改善がされておらず、画像XSSの危険性が残っている。コレに対しては、BMP形式画像のアップロードを許容する場合はPNGに変換して公開するというガイドラインを提案したい。BMP形式は通常画像が圧縮されていないので圧縮して公開した方が好ましいこと、BMPの特性(色数、可逆性など)はPNGで全てカバーしていることがその根拠である。
結論としては以下のようになる。
- 画像のマジックバイトとContent-Typeが同一の画像フォーマットに対するものであることを確認する
- MS07-057を適用する(ようにユーザに促す)
- 例えば、BMPを避ける。あるいはPNGに変換して公開する。
謝辞:
画像埋め込みのHTML/JavaScriptについては、 はせがわようすけ氏からさまざまな情報を教授いただいた。記して、感謝の意を表する。
脚注
*1:JavaScriptを埋め込んだ画像を作ってみました参照
*2:MS07-057を適用していないとHTMLと解釈される
参考文献:
マイクロソフト セキュリティ情報 MS07-057
2007-07-15 - T.Teradaの日記 - 画像へのPHPコマンド挿入
TAKESAKO @ Yet another Cybozu Labs: LL魂お疲れ様でした[LLSpirit]
yohgaki's blog - 画像ファイルにPHPコードを埋め込む攻撃は既知の問題
- http://www.tokumaru.org/ ×871
- http://www.tokumaru.org/JavaScript/ ×268
- http://d.hatena.ne.jp/ockeghem/20071210/p1 ×183
- http://press.eek.jp/result/gif/gif 変換 ×174
- http://d.hatena.ne.jp/ockeghem/ ×92
- http://d.hatena.ne.jp/hasegawayosuke/20071226/p1 ×89
- http://d.hatena.ne.jp/teracc/20070715 ×61
- http://labs.cybozu.co.jp/blog/takesako/2007/08/lls... ×55
- http://press.eek.jp/result/拡張子/拡張子 種類 ×39
- http://d.hatena.ne.jp/hasegawayosuke/ ×35
- http://press.eek.jp/result/gif/gif 画像 ×31
- http://www.tokumaru.org/index.htm ×31
- http://press.eek.jp/result/gif/gif jpg ×30
- http://www.tokumaru.org/techterm/ ×29
- http://www.tokumaru.org ×26
- http://d.hatena.ne.jp/hasegawayosuke/20070625/p1 ×25
- http://d.hatena.ne.jp/ockeghem/20070528 ×22
- http://d.hatena.ne.jp/ockeghem/about ×21
- http://tokumaru.org/ ×19
- http://d.hatena.ne.jp/ockeghem/20071021/1192986523... ×19
- http://d.hatena.ne.jp/ockeghem/?of=5 ×16
- http://www.hash-c.co.jp/ ×15
- http://b.hatena.ne.jp/entry/http://www.tokumaru.or... ×14
- http://www.saiyasuweb.com/2/c/クッキー ×14
- http://d.hatena.ne.jp/ockeghem/20071126/p1 ×14
- http://press.eek.jp/result/拡張子/画像 拡張子 ×13
- http://www.tokumaru.org/JavaScript/index.htm ×12
- http://www.choix.jp/etc/徳丸浩の日記_-_イメージファイトのまとめ_-_画像... ×11
- http://d.hatena.ne.jp/hasegawayosuke/20080802/p1 ×11
- http://labs.cybozu.co.jp/blog/kazuho/archives/2007... ×11
- http://d.hatena.ne.jp/ockeghem/?of=10 ×10
- http://b.hatena.ne.jp/HiromitsuTakagi/20070901 ×10
- http://d.hatena.ne.jp/teracc/20070908 ×9
- http://press.eek.jp/result/gif/gif 検査 ×8
- http://www.tokumaru.org/was/ ×8
- http://d.hatena.ne.jp/m383m/20070918/1190100985 ×7
- http://b.hatena.ne.jp/entry/5892458 ×7
- http://press.eek.jp/result/gif/gif jpeg ×7
- http://www.saiyasuweb.com/3/c/テーブル ×6
- http://press.eek.jp/result/gif/gif メール ×6
- http://bakera.jp/ebi/2007/9 ×6
- http://nogue.cocolog-nifty.com/diary/2007/05/refiz... ×6
- http://www.about-reference.com/php/manual/function... ×6
- http://b.hatena.ne.jp/entrylist?sort=hot&of=50&thr... ×6
- http://b.hatena.ne.jp/keyword/サニタイズ ×6
- http://b.hatena.ne.jp/entrylist?sort=hot&of=50&thr... ×5
- http://a.hatena.ne.jp/harupu/ ×5
- http://bakera.jp/ebi/topic/2986 ×5
- http://search.live.com/results.aspx?q=imagefight&m... ×5
- http://b.hatena.ne.jp/keyword/クロス ×5
- http://clip.nifty.com/entry/a59bf3224009c0bff718ff... ×5
- http://b.hatena.ne.jp/t/SQLインジェクション ×5
- http://a.hatena.ne.jp/yamagata21/ ×4
- http://d.hatena.ne.jp/ockeghem/20071010/1192009917... ×4
- http://labs.cybozu.co.jp/blog/kazuho/archives/2007... ×4
- http://bloger.x0.com/result/gif/gif jpeg ×4
- http://b.hatena.ne.jp/entry/5303987 ×4
- http://mgw.hatena.ne.jp/?url=http://www.tokumaru.o... ×4
- http://b.hatena.ne.jp/t/イメージファイト ×4
- http://b.hatena.ne.jp/keyword/画像 ×4
- http://d.hatena.ne.jp/cybert/20071206 ×4
- http://b.hatena.ne.jp/hasegawayosuke/ ×4
- http://www.about-reference.com/db/mysql-manual/myi... ×4
- http://b.hatena.ne.jp/nitoyon/ ×3
- http://209.85.175.104/search?q=cache:0UQ2hKdT_gEJ:... ×3
- http://www.math.sansu.org/u/diary/?date=20070604 ×3
- http://d.hatena.ne.jp/teracc/ ×3
- http://d.hatena.ne.jp/monjudoh/20070807/1186505259... ×3
- http://b.hatena.ne.jp/ockeghem/bmp/xss/ ×3
- http://b.hatena.ne.jp/ockeghem/ ×3
- http://www.about-reference.com/php/manual/ref.oci8... ×3
- http://d.hatena.ne.jp/ockeghem/20080226/p1 ×3
- http://r.hatena.ne.jp/keyword/BMP ×3
- http://labs.ceek.jp/hbnews/list.cgi ×3
- http://b.hatena.ne.jp/keyword/サニタイジング ×3
- http://d.hatena.ne.jp/ockeghem/?of=25 ×3
- http://d.hatena.ne.jp/ockeghem/searchdiary?word=XS... ×3
- http://209.85.175.104/search?q=cache:FINZ23JWaeMJ:... ×3
- http://d.hatena.ne.jp/ockeghem/20071205/p1 ×3
- http://b.hatena.ne.jp/entrylist?sort=hot&of=100&th... ×3
- http://d.hatena.ne.jp/ockeghem/20071126/p3 ×3
- http://b.hatena.ne.jp/HiromitsuTakagi/?of=180 ×3
- http://d.hatena.ne.jp/ockeghem/searchdiary?word=SQ... ×3
- http://b.hatena.ne.jp/entry/http://blog.ohgaki.net... ×3
- http://www.math.sansu.org/u/diary/?date=20070529 ×3
- http://b.hatena.ne.jp/nilfigo/ ×3
- http://b.hatena.ne.jp/keyword/JavaScript ×3
- http://b.hatena.ne.jp/entry/6750847 ×3
- http://stressfulangel.cocolog-nifty.com/stressful_... ×3
- http://b.hatena.ne.jp/entrylist?sort=hot&of=100&th... ×3
- http://press.eek.jp/result/ipアドレス/ipアドレス 確認方法 ×3
- http://www.tokumaru.org/d/20080502.html ×2
- http://search.live.com/results.aspx?q=javascript ... ×2
- http://tokumaru.org/d/20070717.html ×2
- http://press.eek.jp/result/log/log c言語 ×2
- http://press.eek.jp/result/gif/gif 拡張子 ×2
- http://www.pluto.dti.ne.jp/rinou/saji/200708.html ×2
- http://www.tokumaru.org/techterm/index.html ×2
- http://www.tokumaru.org/d ×2
- http://www.about-reference.com/db/mysql-manual/num... ×2
- javascript break ×92 / キーワード不明 ×31 / 画像 XSS ×30 / 徳丸浩 ×28 / DNS Rebinding ×24 / mod_imagefight ×22 / 徳丸 イメージファイト XSS ×20 / dns rebinding ×12 / イメージファイト ×10 / GIF ファイル検証 ×9 / イメージファイト XSS ×8 / gif xss ×8 / XSS 挿入 ×8 / XSS テスト ×7 / 画像 bmp ×6 / クロスサイトスクリプティング サンプル ×6 / 画像XSS ×6 / イメージファイト 徳丸 ×6 / ウェブアプリケーションセキュリティ ×6 / BMP XSS ×6 / 画像xss ×6 / 画像ファイル php 埋め込み ×5 / XSS 画像 ×5 / イメージファイト bmp ×5 / javascript for break ×5 / 画像 クロスサイト ×5 / XSS イメージファイト ×4 / php mysql sqlインジェクション 対策 推奨 方法 ×4 / XSS 画像 script ×4 / javascript xss ×4 / http://www.tokumaru.org/d/20071126.html ×4 / SQL 暗黙 型変換 ×4 / jpegファイル xss ×4 / 徳丸 画像 xss ×4 / 徳丸 XSS gif ×4 / "DNS Rebinding" ×4 / 画像 XSS 実行 ×3 / oracle エスケープ シングルクォート ×3 / 徳丸 浩 ×3 / jpg ファイト ×3 / サニタイズ言うな ×3 / XSS攻撃 16進数 ×3 / java-script 画像 ×3 / image ファイト ×3 / 画像ファイル XSS ×3 / RFI攻撃 やってみた ×3 / XSS WAF ×3 / javascript XSS ×3 / クロスサイトスクリプティング 画像 埋め込み ×3 / Base64 javascript IE 画像 ×3 / "GIF87a" ×3 / javascript break if ×3 / 拡張子、マジック、フォーマット ×3 / XSS 対策 ×3 / ラベル付 break文 ×3 / javascript switch ×3 / IEEE754 ×3 / 画像 XSS IE ×3 / png javascript xss ×3 / 徳丸浩の日記 ×3 / webアプリケーション 徳丸 ×3 / 日記 JavaScript ×3 / JavaScript break ×3 / jpeg 埋め込み XSS ×3 / SQL 暗黙の型変換 パフォーマンス ×3 / 画像 スクリプト 埋め込まれた 実行 ×3 / IE HTML 画像 埋め込み ×3 / javascript if break ×3 / xss 種類 ×2 / gif89a 脆弱性 phpスクリプト ×2 / content type イメージ ×2 / プログラム 書法 ×2 / javascript 画像を 表示 ×2 / 画像 クロスサイトスクリプティング サンプル ×2 / XSS ×2 / IE Content-Type XSS ×2 / java script ラベル ×2 / SQL 暗黙の型変換 ×2 / ファイル イメージ GIF ×2 / mod_ImageFight ×2 / ie 画像 xss ×2 / JAVAscript break ×2 / Postgresql バインド機構 ×2 / javascript ラベル ×2 / sqlインジェクション 対処法 ×2 / rebinding ×2 / html IE 画像 base64 -ダメ -だめ -非対応 ×2 / 画像ファイルによるクロスサイト・スクリプティング ×2 / php 文字種チェック ×2 / javascript gif 実行 表示 アップロード ×2 / 徳丸 浩 ブログ ×2 / IE7 MIME 判別 ×2 / 画像 xss ×2 / break if break javascript ×2 / postgres 暗黙の型変換 ×2 / javascript ループ 例 ×2 / DNS rebinding ×2 / xss ×2 / break javascript ×2 / WEBアプリケーションのセキュリティ完全対策 ×2
| SQLインジェクション対策はおすみですか? 開発開始時点からのコンサルティングから、公開済みWebサイトの脆弱性検査、 脆弱性発見後の適切な対策まで |


はてなでの2004年の対策は、MS07-034のmhtml:に対する対策だったはずです。mhtml:をURLに付与することで、あらゆるリソースがRFC557のMHTML形式のドキュメントであると強制可能だったため、画像でも何でもbase64なスクリプトが埋め込み可能でした(なのでスタイルシート内でboundaryを削除している)。IEがContent-Typeを無視するというのとは、表面的・結果的には似ていますが、原理的には異なるものでした。
まさしくアレはmhtml対策でした。はてなに報告した人より。
IE8でサンプルデータを試してみたらBMPはすべてtext/plainで(JavaScriptは起動せず)、GIF/JPG/PNGはすべて壊れた画像アイコンで表示されました。
ようやく画像XSSも過去のものになりそうです。