ディレクトリトラバーサル攻撃とは (Directory Traversal)
ファイルのパスを操作して通常ルートではアクセスできないファイルへアクセスをする攻撃のこと。
例として入力情報をそのまま利用
文章じゃわからないと思うので極端な例だが、以下のコードだとどうだろうか?
<?php
echo file_get_contents($_GET['filename']);
?>
<input type="text" name="filename" />
このコードはクライアント側(ブラウザ)からファイル名を入力してサーバー上にあるファイルを読み込んで中身を表示するだけの処理をするものだ。
しかし、絶対パスや相対パスなども入力される可能性はないだろうか?
考えられる危険性
例えば、以下のようにサーバー上にそのままユーザー情報が入っているとする。
data/
は .htaccess
で守られているとして
- data/
- userlist.txt
- .htaccess
- txt/
- aaa.txt
- bbb.txt
- index.php
そしてコードは以下のようなものとする
<?php
echo file_get_contents($_GET['id'] . '.txt');
?>
<input type="text" name="id" />
aaa、bbbと入力してaaaやbbbのテキストファイルを取得するだけならいいが、
もし、../.htaccess
や ../data/userlist
と入力されるとfile_get_contents('../data/userlist.txt') として実行され、表示されてしまうかもしれない。
../.htaccess
に関しては.txtが末尾に付くので問題ないが、その末尾に拡張子を付けるのもなければそれも見られてしまう可能性がある。
そしてhtaccessが見られると権限設定からファイル構造などもバレてしまう可能性もある。
だからbasename() を使おう!
basename - PHP マニュアル によると
basename - パスの最後にある名前の部分を返す
つまり、ファイル名のみを取得できる。
例えば basename('aaa/bbb/hoge.txt')
ならば hoge.txt
となる。
先ほどのコードを以下のように修正するだけで対策できるのである。
<?php
echo file_get_contents(basename($_GET['id']) . '.txt');
?>
<input type="text" name="id" />
さいごに
こんなこと言っときながら、やらかしてるのは自分なんです。攻撃は受けていないんですが、よく考えたら、file_get_contentsってまずくないかって急に思ったんですよ。
ウィキのレンタルサービスを開発していて一時的にユーザー名とパスワードを保存しているテキストファイルがあったんですね。そしてそのファイルはユーザー名で保存していまして。
つまり、この記事で紹介した通りの攻撃される可能性もゼロではないかなと思い、試したところできちゃいました。
そしてパスワードは今ではハッシュで保存しているのですが、昔はそのままの状態で保存していたので大問題でしたね。開発者は私一人だけでしたのでまだよかったんでしょうけど。パスワードもハッシュで保存しておけば運営側も悪用できませんし、パスワード設定した本人しか知ることができないのでハッシュ化しましょう。