wasbook reading #6
「体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践」読書会の第6回。
だんだん月一になってきたけど、それでも頑張って続ける。
今回読んだのは以下の範囲。
- 4章 Webアプリケーションの機能別に見るセキュリティバグ
- 4.10 ファイルアクセスにまつわる問題
- 4.11 OSコマンド呼び出しの際に発生する脆弱性
- 4.12 ファイルアップロードにまつわる問題
これまでののメモはこちら。
- wasbook reading #1 - techlog
- wasbook reading #2 - techlog
- wasbook reading #3 - techlog
- wasbook reading #4 - techlog
- wasbook reading #5 - techlog
4章 Webアプリケーションの機能別に見るセキュリティバグ
4.10 ファイルアクセスにまつわる問題
ディレクトリトラバーサルについて。
基本的にはファイル名をそのまま使わないようにすればよいと思う。あとは各言語にはファイル名だけを返す関数がありそうな気がするので、そういったものを活用するとか。(javaだとjava.io.File#getName()とか)
公開ディレクトリに置くと、公開されてしまうというのはその通りで、公開してはいけないものは公開されていないディレクトリに置く。
4.11 OSコマンド呼び出しの際に発生する脆弱性
最近だとsendmailコマンドを直接呼び出してメール送信とか、あまりないと思うのけどそうでもないのかな。JavaならJavaMailを使いそうだし。
SQLServer で sa で xp_cmdshell でコマンド実行されるとかのほうがありそうな気がした。最近は減っていると思うけど。
Javaだと java.Runtime#exec で直接コマンドを呼び出せるけど、あんまり使ったことがない。OSコマンドを使わなきゃ絶対できないことって、どんなことだろう…。
シェル呼び出し機能のある関数というものは知らなかった。perlでもRubyでもあるみたいなので、気を付けなくては。
4.12 ファイルアップロードにまつわる問題
この章だけで、25ページある。基本的な内容と、IE対策を入れるとこれくらいになってしまうのだと思う。それにしても複雑怪奇すぎて、ファイルアップロードからのダウンロード処理は実装したくないと思った。できれば適切なライブラリを探して、それを使うようにしたい。でもそんな都合のよいライブラリはあるのかな。
普段PHPはほとんど使わないので、こんなにPHPを読んだのははじめてだと思う。PHPの知識が少なすぎて、正直この章はちょっと辛かった。コードを詳しく読んでいくと、Javaと違って型が明示されていないのでなかなかすっと読めなかったりした。
読んでみて、関数名などでちょっとだけ気になることがあった。
get_upload_file_name という関数があって、これはアップロードしたファイル名を取得するのかなと思って読んでいけど、実際にはユニークなファイル名を生成した上でファイルを作成していた。細かく関数を分けたりすると紙面上わかりにくくなることを懸念して、ある程度まとめているのかもしれない。関数名と役割が多少異なっているように感じた。あとは他の関数と合わせて get_uploaded_file_name がいいかもしれない。
check_image_type という関数については、is_image_type のほうが関数から返却される boolean の値が推定できてよさそう。違うところ(P.263)では is_uploaded_file という関数があった。is_uploaded_file と同じページに move_uploaded_file という関数があって、これはちょっと微妙だけど movable_uploaded_file のほうがいいのかな。やっぱりちょっと微妙だけど。命名は難しいよね…。
さて、本題のファイルアップロードにまつわる問題。
サーバにファイルをアップロードして、それがそのままPHPやJavaとして動いてしまうと困るよね、と。そこで、Javaでファイルアップロード処理を作って、JSPの動くディレクトリにJSPをアップロードしたらどうなるのかなと思って作ってみた。ちゃんと、しっかりJSPが動いた。
Javaでもできるのかな、実はできないかな、でもできそうだな、ということで確認してみた。Servlet3.0からマルチーパートデータを直接扱えるようになったので、けっこう簡単だった。実装にあたってはこちらのエントリを参考にさせていただいた。
こういった問題に対処するには、地味だけどファイル名を適切に変更して、拡張子による制限を加えることが必要になる。
またアップロードしたファイルが、ダウンロードできる場合はもっと注意が必要になる。
Content-Typeを正しく設定して、拡張子とファイルの中身の対応を確認して、レスポンスヘッダに Content-Disposition:attachment を指定する。
Content-Dispositionヘッダーははじめて知ったので、もう少し調べてみようと思いいろいろ見てみたけど、RFCをちょこっと読んで挫折した。ま、ファイルをブラウザで開くのではなく、ダウンロードさせたいときに指定するみたいですね、と。
今回のまとめ
読みなれないPHPを読み解くのがちょっと大変で、さらにファイルアップロードとファイルダウンロードについて理解するのが大変だった。
Webアプリケーションでもファイルを扱うことはしょっちゅうあるので、十分に気をつけて実装しなくては。
ひとりで読んでいるとけっこう読み飛ばしてしまうけど、余計なことも含めて喋りながら読んでいるといろいろ気付く。なんでこうなってるんだっけとか。それ以外はカレログ入れた?とか、証明書の話とか、職場環境の愚痴とか。
永遠に続くかと思われた第4章も、あと20ページを残すのみ。全体としては、まだ200ページくらいあるけど…。年内には読書会を終えたいところ。
このエントリとは関係ないけど、一緒にwasbookを読んでいる id:Kango くんの PHPカンファレンス2011で安全なPHPアプリ開発の10の鉄則を聞いてきた。 - piyolog もあわせて読みたい。
wasbookに関するものは、こちらのタグで。
電子書籍版はこちら。