そうそう、C/C++セキュアコーディング ハーフデイキャンプPart2 File I/Oの話も途中までしか書いていなかった。
三部構成にわかれていて
1、UNIXの権限とパーミション
2、ファイルシステムの脆弱性
3、ファイル入出力と競合状態
1については、前に書いた。今回は、「2、ファイルシステムの脆弱性」について。
ディレクトリトラバーサルの脆弱性(プログラムで../を認めてしまうと、やばいことになる脆弱性等)についてです。
■ディレクトリトラバーサル(パストラバーサル)とは
つまり、../をファイル名として認めてしまうと、
ファイルのアップロードとかで、アップロードファイルを
../../../../../../../etc/password
とかすると、パス名が、
/usr/local/tomcat/webapps/myapp/../../../../../../../etc/password
(/以上で../をやっても、/なので、../を十分長くしてしまうと・・)
つまりこれは、
/etc/password
を上書きしろ!っていう意味になり(>_<!)!
これを、ディレクトリトラバーサルまたは、パストラバーサルという。
■ファイル名によるアタック
大文字小文字の評価が違うこと、
/を入れるか入れないか
./
などでの脆弱性もある
(文字列でチェックすると、./等を入れても同じファイルなのに、違うファイルと思ってしまう)
■シンボリックリンクによるアタック
機密のファイルにシンボリックリンクを張られてしまうと、アクセスできてしまう
(権限チェックはシンボリックリンクに対するチェック)
■ハードリンクによるアタック
消す前にハードリンクを張られてしまうと、
そのファイルをプログラムは消したつもりが、
ファイルは(悪い人がハードリンクした名前で)残ってしまう
(TOCTOU攻撃とあわせて使う)
■名前つきパイプも
悪用できるらしい(signal-based attack??)
■Linuxで、デバイスファイルを・・・
誰かに開かれてしまうと、ファイルがロックされてしまう
■対策:ファイル名関係→正規化(canonicalization)
realpath()を使う
■対策:シンボリックリンク・ハードリンク
シンボリックリンクの場合、S_ISREG()
リンクカウントのチェック(lstat()で、第二引数のst_nlink)
ハードリンクの場合、別のパーティションに機密ファイルは置く。
■対策:名前つきパイプ、デバイスファイル
ファイルタイプのチェック
■対策:権限を落とす
setuidプログラムで入出力のとき、実ユーザーIDにレベルを落とす
■サンドボックス(jail化)
chroot()で独自のルートの範囲内以外、アクセスさせない
注意:chdir()して、chroot()の範囲内にしといてね
UIDを変更し忘れると、プロセスが抜ける危険があるそうな・・・
jail()はさらに協力
注意:chroot()もそうだけど、アクセス範囲を狭める
=他のところにユーティリティがあると使えないからね!
こんなかんじ