[PHP-users 16412]Re: headerってなによ?(was 他のディレクトリの変更)

Osamu Shigematsu m5issige @ mr.hitachi-medical.co.jp
2003年 7月 3日 (木) 10:01:52 JST


重松です。こんにちは。
十分理解が深まったようで、よかったですね。

> 簡単に書けば・・・
> 
>   header("Content-type: image/jpeg");
>   readfile("ディレクトリ + ファイル名");
> 
> だけでOKなのですね・・・。

確かに動くでしょう。そういう意味では、OK です。

しかし、こういう処理で気をつけなければならないことがあります。
それは、「Directory Traverse (Traversal) 脆弱性」です。

# 手前味噌ですが、ちょっとまとめてます。 :)
	http://www.ravi.ne.jp/~shige/?DirectoryTraversal

まあ、横文字で書くとなにやら小難しい感じですが、
平たく言うと、不正なファイル名を渡して、php スクリプトを誤動作させて、
大事なデータを盗む攻撃に対処できないセキュリティ欠陥です。

で、ysano さんのコードは、サンプルでしかなくて、動きますが、
使い物にはなりません。

もっとも、中村さんは勉強熱心な方だから大丈夫だと思いますが、
なかには、動くものが手に入った時点で、背景にある基本的な原理や、
自分が行おうとしていることの問題点、危険性などを検証しない人が
たくさんいると思います。

なので、質問にたいして、答えそのものを書くときには、
実際に運用されても、害がないものをきちんと書くか、
それができないなら、問題点があり、そのまま運用するのは危険だ、
位のフォローは入れたほうがよいのではと思います。

質問した当の本人以外にも、これらの一連のやり取りは、
データとして蓄積されて、のちのち、同じ問題の解決策を求めた、
多くのビギナーに読まれる可能性がありますから。

なので、

	(1) 渡されたデータは正当性を検証する
	(2) そもそもデータの捏造を難しくする
	(3) ファイルを扱う場合には、../ などの相対パス、%00 (NUL) 挿入による
		正当性チェックの回避などに厳密に対処する (or safemode)

などの各種対策を講じるべきです。

画像を呼び出す HTML を生成するスクリプト
<?php
$id = '2003-07-03-012345': // 日付, 6 桁の連番(?)

// これだと、簡単に id 捏造可能
// 例)
// curl -O "http://example.com/nasty.php?2003-07-03-[000000-000099]"

// ハッシュを生成
// これだと環境変数 MAGIC の内容を知らないと id が作れない
$magic = md5(md5($id) . getenv('MAGIC'));
$id = "$id-$magic";
print "<img src=\"image_server.php?id=$id\" />";
?>

画像を出力するスクリプト
<?php
$id = $_GET['id'];
// パターンを解析
if (!preg_match('/^(\d{4})-(\d\d)-(\d\d)-(\d{6})-([\da-f]{32})$/i', $id,
$matches)) {
        die("No match\n");
}
// マッチした各要素を取り出す
list(,$Y, $m, $d, $id, $magic) = $matches;
// 捏造でないか確認する
if (md5(md5("$Y-$m-$d-$id") . getenv('MAGIC')) != $magic) {
        die("Invalid request\n");
}
// ファイルのパスを組み立てる
$path = "/path-to/img/$Y-$m-$d/$id.jpg";
header('image/jpeg');
readfile($path);
?>

-- 
Osamu Shigematsu <m5issige @ mr.hitachi-medical.co.jp>



PHP-users メーリングリストの案内