tonextone.com/note/

Last-modified: 2006-09-01 (金)

Copyright ©master_at_tonextone.com All rights reserved.

ちょっと安全かもしれない eval() の使い方。

Posted : 2006-02-27 00:00 / Category : [開発日誌]
長らくエントリのない状態が続いた後ですが、
地味な思いつきのメモです。

eval() 使ったらスゲェ簡単なのに…とか思いながら、
その強力さゆえに、恐ろしくて使えない場合が、間々ある。
いつも奥の手として持ってるだけみたいな。

良くあるのは、
'こんにちは、{$foo}さん。ようこそ{$bar}のホメパゲへ。'
みたいな文字列の中の変数に値を代入したいというやつ。

正規表現とかでやってたら回りくどいので、
何とか eval() を活用するためにセキュリティ対策を考えてみた。

ヒアドキュメント使うのがキモ。
あと、ちゃんと意識して引用符「'」「"」を使い分けて、
1 回しか評価しないように気を付ける。
ついでに、境界識別子 '$_boundary' を予測し難くすれば、悪い事もやりにくかろう。

PHP だと、こんな感じ。
<?
function eval_vars_in_string($_string,$_vars)
{
  extract($_vars);

  $_boundary = uniqid('__');

  $_code = '$_return = <<<'.$_boundary.'
'.$_string.'
'.$_boundary.';
';

  eval($_code);

  return $_return;
}

$_string = 'こんにちは、{$foo}さん。ようこそ{$bar}のホメパゲへ。';

$_out = eval_vars_in_string($_string,$_POST);

?>

という思い付きでした。[サンプル]

コメント歓迎。

ツッコミ

1: itoh (04/05 15:20)
これ、どうやってsystemコード書きます?
2: master (04/06 13:39)
この関数の使命は変数展開で、
system 関数の評価/実行までは行わないというのがキモです。

system 関数を動的に生成して実行したい場合は、
まず、system 関数のコードを動的に生成して、
もう一回 eval(); すれば、実行されるかと。

ただし、リクエスト変数の無害化は、別途必要です。

<?
$_vars = array('path' => '.');
$_string = ' system(\'ls {$path}\'); ';

$_out = eval_vars_in_string($_string, $_vars);
?>
<pre>
<?
var_dump($_out);
eval($_out);
?>
</pre>
[ このエントリへはツッコミ出来ません ]