この記事は脆弱性"&'<<>\ Advent Calendar 2015 22日目の記事です。
ここでクイズです。下記の中身と拡張子が一致したファイルの中で画像なのはどれでしょう。ただし、判定がめんどいのでconvertコマンドでpngに変換できるファイルを画像とみなします。
- data.bmp
- data.svg
- data.txt
- data.html
答え : 全部画像。
convertコマンドの対応しているファイルフォーマットは公式サイトに書かれていますが無駄に多く、avi,txt,htmlなども変換可能です。ただし、aviはffmpegが必要、htmlだとhtml2psが必要です。
さて、本題に移ってPaperclipの脆弱性(CVE-2015-2963)について話をします。PaperclipとはRailsで画像アップローダーを簡単に作るためのライブラリで、今回の脆弱性を報告する前に実装されていたセキュリティ機構は主に下記の3つでした。
- リクエストのパラメータが指定されたContentType(または拡張子)である事をチェック
- fileコマンドで拡張子が偽装されてない事をチェック
- サムネ用の画像などconvertコマンドで生成し、元ファイルと一緒に保存しDBに画像情報を書き込む
一見問題なさそうに見えますが、HTTPリクエストを直接生成してtxtファイルのContentTypeをimage/jpegにしてアップロードするとどうなるでしょう。1はContentType偽装ですり抜け、2は拡張子と中身が一致するのですり抜けます。3の変換で失敗するとロールバックされるため画像以外アップロード出来ないように見えますが、最初に書いたようにtxtファイルはconvertコマンドにとっては画像なのですり抜けます。
つまりチェックを全てすり抜けアップロードが成功し、オリジナルのtxtファイルをサーバに置くことができます。あまり無さそうですが、サーバにhtml2psが入っているとhtmlもアップロード可能で、元ファイルの拡張子がそのまま残るのでXSSも可能です。
修正後は2の所でファイル自体のContentTypeの検証も行うようになってました。
という訳で外部のシステムに頼る場合は、ドキュメントなどを読んで挙動を確認するか、自前でバリデーションを掛けておいた方が無難という話でした。