具体的には、basename('c:autoexec.bat') の結果は、引数そのまま c:autoexec.bat となります。一方、basename('c:\autoexec.bat') の結果は、autoexec.bat と、期待通りの結果となります。
これにより、以下のようなスクリプトに対しては、c: などドライブレターが取り除かれないことになります。
上記に対して、file=c:autoexec.bat を指定すると、readfile('c:autoexec.bat') が実行されます。試してみると、ディレクトリセパレータがない場合、カレントディレクトリのautoexec.bat ではなく、c:\autoexec.bat がオープンされるようです。 ドライブレターは c: に限ったわけではなく、d:ドライブなど他のドライブのルートディレクトリ上のファイルもオープン可能となります。$file = $_GET['file']; readfile(basename($file));
すなわち、以下の条件が全てそろった場合、アプリケーションの想定ディレクトリではなく、任意ドライブのルートディレクトリの任意ファイルにアクセスできることになります。
- ファイル名として、basename関数を通しただけのパス名を指定している
- ディレクトリの指定をしていない。
- ルートディレクトリに重要情報があり、ファイル名を知る手段があれば、情報漏洩となる
- 指定したファイルに書き込みができる場合、ルートディレクトリの任意ファイル名で書き込みができる(*1)
- ディレクトリ修飾をしていないので、カレントディレクトリのPHPソースファイルにアクセスできる可能性が高い
- 書き込みできるスクリプトの場合、任意内容のPHPスクリプトを外部から書き込むことにより、スクリプトインジェクションができてしまう
安全なウェブサイトの作り方改訂第6版によると、ディレクトリトラバーサル脆弱性の根本的解決策は以下のいずれかとなっています。
- 外部からのパラメータでウェブサーバ内のファイル名を直接指定する実装を避ける。(3-(i)-a)
- ファイルを開く際は、固定のディレクトリを指定し、かつファイル名にディレクトリ名が含まれないようにする。(3-(i)-b)
下記は、安全なウェブサイトの作り方改訂第6版のP71から、ディレクトリトラバーサル脆弱性の修正例です。
上記はWindowsに限った話ではなく、Unix/Linuxでも同じですので、この機会にディレクトリトラバーサル対策の見直しをお勧めします。$dir = '/home/www/image/'; … $file_name = $_GET['file_name']; … if(!file_exists($dir . basename($file_name))) { $file_name = 'nofile.png'; } $fp = fopen($dir . basename($file_name),'rb'); fpassthru($fp);
なお、当該問題はphp.netにてBug #66395として報告済みで、既にリポジトリ上は修正されていますが、完全には対策されないと予想されます。安全なウェブサイトの作り方のようにアプリケーション側の正しい対応をお勧めします。
*1 Windowsのルートディレクトリに書き込むには高い権限が必要ですが、Windows版Apacheの場合、SYSTEM権限で動作するので、Apache上のPHPからルートディレクトリにファイルを書き込みできることを確認しています。
0 件のコメント:
コメントを投稿