作者: 閑舎
日時: 2007/9/22(01:13)
wtnabe@... (ねこ丸) さん wrote.

>   いやいや。ファイルを開くことそのものが危険なのではありません。普通に
> fopen して fread している途中でいきなり PHP のコードとして実行すること
> はできないです。だから前回のツッコミで GIF ファイルを include しないで
> しょ?と書いたのです。(ユーザーからのパラメータを利用して include する
> ファイルを決めるような場合は別ですが、これは今度はアップロードや画像内
> への埋め込みとは無関係に危険です。)

PHP がスクリプト内で <?php ... をパースするような文脈に画像のデータが生
におかれるようなことがあるか、ということですね。要するに、

<?php
header("content-type:image/gif\n");
include('./img/such.gif');
?>

と書くと同等な感じで画像ファイルが扱われるようなことがないか、ということ
になるわけで、カウンタなどは

<img src="count.php?sort=1">

みたいな形で用いられる関係で、そうした扱いがありうると思ったわけです。ま
た、GD の関数群も生のデータを httpd へ送ることがあるわけで、そうした部分
に PHP のパーサが使われるようなコードがあったりしてないかと思ったわけで
す(後者はどうもあまりなさげですが、ぐぐると別のセキュリティホールにはさ
らされているようですね)。

>   ちなみに、埋め込み方によっては GD で変換しようが攻撃コードを除去する
> ことはできません。テキストを保存する領域もありますし。ファイルが安全か
> どうかを特定するのは結構難しいですから、要するに得体の知れないファイル
> を include, require しちゃダメなんです。

おっしゃるように、パレット領域あるいはヘッダ領域は画像サイズや画像形式を
変えても残るようですね、困ったものです。取りあえず、バイナリファイルに向
けて

<?php
<script

が含まれないかチェックし、あったら「扱えないファイル形式です」とメッセー
ジを出すくらいが現実的のようですね。

で、本当に include, require だけ注意すればいいのか、と気になったので、少
し古いですが、手持ちの PHP 4.4.2 のソースをながめてみました。どうやら

zend_language_parser.y

|	T_INCLUDE expr 			{ zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
|	T_INCLUDE_ONCE expr 	{ zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
|	T_EVAL '(' expr ')' 	{ zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
|	T_REQUIRE expr			{ zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
|	T_REQUIRE_ONCE expr		{ zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }

zend_language_parser.c

case 340:
  { zend_do_include_or_eval(ZEND_INCLUDE, &yyval, &yyvsp[0] TSRMLS_CC); }
  break;
case 341:
  { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &yyval, &yyvsp[0] TSRMLS_CC); }
  break;
case 342:
  { zend_do_include_or_eval(ZEND_EVAL, &yyval, &yyvsp[-1] TSRMLS_CC); }
  break;
case 343:
  { zend_do_include_or_eval(ZEND_REQUIRE, &yyval, &yyvsp[0] TSRMLS_CC); }
  break;
case 344:
  { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &yyval, &yyvsp[0] TSRMLS_CC); }
  break;

ということで、include, eval, require が特別扱いであることがわかりました。
ざっと見ですが、これら 3種の関数を注意して使っていれば画像ファイルから攻
撃されることはないようですね(あくまでざっと見)。

>   いやぁ。負と言っていいと思います。PHP 以前はこれをはっきりと言えるよ
> うな軽量かつ強力で一般に普及した処理系がなかったのでよく分からなかった
> だけで、普及してみたらアレコレ問題あるね、って分かるようになったってこ
> とだと思います。PHP にはそういう便利機能が多いので叩かれるんだけど、先
> 駆者としての功績は大きいと思いますよ。ど真ん中で使ってる人にはつらいで
> すけど。

これには私としては異論がありますね。PukiWiki のソースなど否定されるわけ
だし、Xoops のモジュールなども HTML / PHP コード混在、で、当然モジュール
なんで include です。まあ、大垣氏も、テンプレートとしてのコード埋め込み
型のスクリプトは認めているようで、デフォルトの許可を負の遺産と言ってるよ
うですから、全面的に認めないわけではないですよね。注意して使えば Perl な
どよりウェブページ作成上便利なのは明かなわけですから。クヌース先生の言わ
れる、ソースとドキュメントが一度に書けるような感覚かな。

  http://www.atmarkit.co.jp/flinux/rensai/mysql5_02/mysql5_02a.html

などで始まる PHP の実戦的な活用紹介記事もいまだ HTML / PHP コード混在で
すしねー。

--
本田博通(閑舎)
テキストとスクリプトの http://www.rakunet.org/TSNET/