end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

secure coding - マジックバイトによるブラウザの画像種類判定

webアプリで画像データを直接出力する際、ファイル名の拡張子がなかったり、Content-Typeが誤っていても、ブラウザは、JPEGPNG、GINF等の画像フォーマットに応じ、レンダリングし、表示してくれます。

「なぜ?」と思いつつも、これまで調べていませんでしたが、実体は、画像データの先頭数数バイトにあるマジックバイトで判定しているらしい。

画像フォーマット MAGIC BYTE
BMP BM
GIF GIF8[79]a
JPEG xFFxD8
PNG \x89PNG\x0A\x0A\x1A\0A

http://www.tokumaru.org/d/20071210.html
マジックバイトの一覧は↑こちらで、perlでマジックバイトによる判定例は↓こちら。
http://howtobeahacker.seesaa.net/article/141255226.html
(上記サンプルコードのマジックバイトと徳丸さんが記載するマジックバイトが少々、ことなる点が気になりますが...)

更に 古いIE?では、 Content-Type とマジックバイトが異なる場合、ファイルの内容から、そのファイルの種類を自動判定してくれるらしく、FOO.PNGというファイルの内容が

<script>alert('FOO!!!')</script>

のようにjavascriptを含む場合、XSSになってしまうと。
怖い話です。
http://www.mozilla.gr.jp/standards/webtips/webtips0033.html


<img src="foo.png">

のように、インラインで表示する場合は、validationを強化するとして
ユーザにファイルをダウンロードさせる場合は、HTTPのヘッダで
perl cgiでダウンロードさせるファイル名を指定 (RFC6266準拠版) - end0tknrのkipple - web写経開発
のように Content-Type: application/octet-stream ;
Content_Disposition: attachment を指定すればよいのかな?

マジックバイトに関連する脆弱性は、十分に理解できていないので、
次のurlをきちんと理解しなくては
http://www.tokumaru.org/d/20071210.html
http://www.mozilla.gr.jp/standards/webtips/webtips0033.html