5

PHP でeval()関数を使用する Web ゲームのコードを引き継いでいます。これが重大なセキュリティ問題になる可能性があることはわかっているので、コードのその部分を削除するかどうかを決定する前に、引数をチェックするコードを精査する手助けが必要です。現在、安全であると確信できるまで、コードのこのセクションをゲームから削除しましたが、機能が失われることは理想的ではありません。そのようなことが可能であると仮定して、eval() の使用を避けるためにセグメント全体を再設計するよりも、これをセキュリティで証明したいと思います。悪意のあるコード インジェクションを防止すると思われる関連コード スニップを以下に示します。$value は、";" を含まないことがわかっているユーザー入力文字列です。

1 $value = eregi_replace("[ \t\r]","",$value);
2 $value = addslashes($value);
3 $value = ereg_replace("[A-z0-9_][\(]","-",$value);
4 $value = ereg_replace("[\$]","-",$value);
5 @eval("\$val = $value;");

これまでの私の理解は次のとおりです。

1) $value からすべての空白を削除します

2)データベース呼び出しに必要な文字をエスケープします(なぜこれが必要なのかは私にはわかりません)

3) 英数字の直後に \ または ( が続く文字を検索し、それらの組み合わせを - に置き換えます。おそらくこれは、文字列内の関数呼び出しに似たものをすべて削除することですが、なぜ前の文字も削除するのかは私には不明です. 2行目で明示的に追加した後、 \ も削除されます。

4) 文字列内の php 変数への参照に似たものを避けるために、$ のすべてのインスタンスを - に置き換えます。

だから:ここに穴が残っていますか?そして、上記の正規表現を誤解していますか? 最後に、 ( 文字を除外せずにこれをセキュリティで保護する方法はありますか? 入力される文字列は理想的には数式であり、 ( を許可すると操作の順序を操作できますが、これは現在不可能です。

4

3 に答える 3

4
  1. VM 内のコードを評価する - 参照Runkit_Sandbox

  2. または、数学用のパーサーを作成します。組み込みのtokenizerを使用することをお勧めします。T_DNUMBERトークンを反復し、括弧、、、T_LNUMBER演算子、および多分を追跡する必要がありますT_CONSTANT_ENCAPSED_STRING。他のすべてを無視します。その後、結果の式を安全に評価できます。

  3. 簡単なグーグル検索で、このライブラリが明らかになりました。それはまさにあなたが望むことをします...


トークナイザーを使用した簡単な例:

$tokens = token_get_all("<?php {$input}");
$expr = '';

foreach($tokens as $token){

  if(is_string($token)){

    if(in_array($token, array('(', ')', '+', '-', '/', '*'), true))
      $expr .= $token;

   continue;   
  }

  list($id, $text) = $token;

  if(in_array($id, array(T_DNUMBER, T_LNUMBER)))
    $expr .= $text;
}

$result = eval("<?php {$expr}");

(テスト)

これは、入力が有効な数式である場合にのみ機能します。そうしないと、空の括弧やそのようなものが原因で、eval`d コードで解析エラーが発生します。これも処理する必要がある場合は、別のループ内で出力式をサニタイズします。これにより、無効な部分のほとんどが処理されます。

while(strpos($expr, '()') !== false)
  $expr = str_replace('()', '', $expr);

$expr = trim($expr, '+-/*');
于 2013-07-15T00:42:22.797 に答える
2

ここでは、一部の文字を削除するのではなく、許可されているものを一致させることが最善の方法です。

システム コマンドの実行に使用できる ` (バッククォート) をフィルター処理していないようです。紐をサニタイズしようとしても防げないことは神のみぞ知る… どれだけ多くの穴が見つかったとしても、それ以上の穴がないという保証はありません。

あなたの言語がそれほど複雑ではないと仮定すると、eval を使用せずに自分で実装することはそれほど難しくないかもしれません。

于 2013-07-15T00:42:51.093 に答える