4

たとえば、単純な MVC タイプ システム:

/api/class/methodを使用して PHP 変数に書き直して.htaccess/nginx.confから、次のようにします。

<?php

// Set up class + method variables
$className = some_class_filter($_GET['class']);
$method = some_method_filter($_GET['method']);

// Check if class exists and execute
if(file_exists(BASE . "/controllers/" . $className . ".class.php")) {
    require BASE . "/controllers/" . $className . ".class.php";
    $$className = new $className();

    // Execute the method
    $$className->$method();
} else {
    // Spit out some error based on the problem
}

?>

これはひどく悪い習慣ですか?それが悪い習慣である場合、誰かがその理由を正確に説明できますか? もしそうなら、私がしていることを行うためのより良い方法はありますか?

編集基本的に、私が可変変数を使用している理由は、コアシステムを簡単に拡張できるようにするためです。つまり、新しいコントローラーを追加するのは素晴らしく簡単です。私は、本質的にあらゆる関数やクラスを何らかのフィルターなしでインスタンス化できるようにすることのセキュリティ リスクを明確に理解しています。

「some_filter_here」は、許可されているコントローラーのリストである可能性があります-ここで言及したホワイトリスト。

4

3 に答える 3

6

はい、これはかなり悪い習慣です。そのインスタンスに可変変数が必要ですか? つまり、特定のリクエストで複数のクラスとメソッドをインスタンス化する必要がありますか? あなたのURI構造はそうではないことを示唆しています。そうでない場合は、次を使用できます。

$object = new $className();
$object->$method();

それ以外の場合は、次のことを行うことができます。

$objects = array();
$objects[$className] = new $className();
$objects[$className]->$method();

これにより、追跡が困難な可変変数でスコープが汚染されるのを回避できます。

指定されたディレクトリ内のクラスの存在をチェックする限り、これは十分なホワイトリストである必要があります (攻撃者がそのディレクトリに書き込むことができないと仮定します)。

EDITmethod_exists :さらなるチェックとして、メソッドを呼び出す前にオブジェクトのチェックを検討することをお勧めします。

于 2012-01-03T17:17:11.607 に答える
1

「some_class_filter」と「some_method_filter」のコードを書いているので、問題ないと思います。また、エラーまたはデフォルト ハンドラーが表示されるので、最終的には問題ないと思います。

とにかく、多くの MVC フレームワークが同様の方法で動作すると思います。

于 2012-01-03T17:14:26.200 に答える
1

それらは望ましくありませんが、あなたが持っている方法でそれらを使用しても問題ありません。

$_GETただし、いくつかのポイントがあります。あなたのコードには、攻撃者が?class=../base. そのファイルが存在する場合、file_exists()呼び出しは返さtrueれ、アプリケーションはそれを含めてクラスとしてインスタンス化しようとします。

安全なシナリオは、これらのパラメータを文字、数字、およびアンダースコアのみとしてホワイトリストに登録することです (単語をアンダースコアで区切る場合、つまり.php)。

call_user_funcまた、 andを使用する構文を好みますcall_user_func_array。コードでこれらの関数を使用すると、次のようになります。

<?php
$class_name = $_GET['class'];
$method_name = $_GET['method'];

$parameters = $_GET;
unset($parameters['class'], $parameters['method']); // grabs any other $_GET parameters

if (file_exists(BASE.'/controllers/'.$class_name.'.class.php')) {
    require BASE.'/controllers/'.$class_name.'.class.php';
    $controller = new $class_name();
    $response = call_user_func_array(array($controller, $action_name), $parameters);
}
else {
    header('HTTP/1.1 404 Not Found');
    // ...and display an error message
}
于 2012-01-03T17:28:51.000 に答える