2012-07-10 20 views
6

私は、GET変数、クラス、メソッドを2つ取り、設計したメソッドにマップするAJAXスクリプトを作成しようとしています(CodeIgniterがAjax、私はかなり確信しています)。私はどのクラスとメソッドを実行するかを決定するためにユーザーの入力に依存しているので、ハッカーがその技法を利用するための方法があるかもしれないと心配しています。安全にユーザー入力に基づいて関数を呼び出す

コード:

//Grab and clean (just in case, why not) the class and method variables from GET 
$class = urlencode(trim($_GET['c'])); 
$method = urlencode(trim($_GET['m'])); 

//Ensure the passed function is callable 
if(method_exists($class, $method)){ 
    $class::$method(); 
} 

が、私はこのテクニックを使用している間に注意すべき不利益ま​​たはセキュリティウォッチアウトがありますか?

答えて

6
<?php 
class AjaxCallableFunction 
{ 
    public static $callable_from_ajax = TRUE; 
} 

$class = $_POST['class']; 
$method = $_POST['method']; 

if (class_exists($class) && isset($class::$callable_from_ajax) && $class::$callable_from_ajax) { 
    call_user_func($class, $method); 
} 

最良の結果を得るための他の回答の一部と組み合わせます。 PHP 5.3.0以上が必要です。

<?php 
interface AjaxCallable {} 

class MyClass implements AjaxCallable 
{ 
    // Your code here 
} 

$class = $_POST['class']; 
$method = $_POST['method']; 

if (class_exists($class) && in_array('AjaxCallable', class_implements($class))) { 
    call_user_func($class, $method); 
} 

あなたも、このアプローチは、OOPの原則を次の(簡単に維持するために)非常に冗長であるとクラスと呼ばれ、できないことができたの配列を維持するためにあなたを必要としないインタフェースを実装することができます。

+1

AjaxCallableインターフェイスは素晴らしいアイデアでしたが、完璧に動作します。ありがとう! – ACobbs

+0

それはあなたのために働いてうれしい:) –

4

引数を渡さないことを考慮すると、これは比較的安全です。しかし、のような場合、私はあなたの中の有効なクラスのリストを追加します。

//Ensure the passed function is callable 
if(method_exists($class, $method)){ 
    if(in_array($class, array('controller1', 'controller2'))){ 
     $class::$method(); 
    } 
} 

この方法では、ハッカーは本当に枠組みの中ですべての可能なクラスをこのように呼んでいますが、彼ができるようにするだけではできません。

14

チェック方法は、ユーザが呼び出すことが許可されている場合:

// methods that user can call: 
$user_methods = array("method1", "method2", "method3",); 

//Ensure the passed function is callable 
if(method_exists($class, $method) and in_array($method, $user_methods){ 
    $class::$method(); 
} 

そうでなければあなたが行うことができるようになりますどのようなユーザーを制御することはできませんよ。

+4

+1。ホワイトリスト、ブラックリストに載せないでください。 – Polynomial

+2

良い答え。 method_existsだけを使用しても、予期しないことが起こる可能性があります。 – Erik

+0

ひどいことも。 –

2

この場合、Reflectionで処理する必要があります。

あなたが必要としているものをここに示します。だから、最終的に我々はできる

<?php 
class HelloWorld { 

    public function sayHelloTo($name) { 
     return 'Hello ' . $name; 
    } 

} 

$reflectionMethod = new ReflectionMethod('HelloWorld', 'sayHelloTo'); 
echo $reflectionMethod->invoke(new HelloWorld(), 'Mike'); 
?> 

:メソッドを実行

<?php 
class Apple { 
    public function firstMethod() { } 
    final protected function secondMethod() { } 
    private static function thirdMethod() { } 
} 

$class = new ReflectionClass('Apple'); 
$methods = $class->getMethods(); 
var_dump($methods); 
?> 

ReflectionMethods:invokeを使用して、このようなことができ

$class = urlencode(trim($_GET['c'])); 
    $method = urlencode(trim($_GET['m'])); 

    $allowed_methods = array("insert", "update", "delete"); 

    if(method_exists($class, $method) and in_array($method, $allowed_methods){ 
    $reflectionMethod = new ReflectionMethod($class, $method); 
    $reflectionMethod->invoke(new $class, 'First Argument'); 
    } 
+1

メソッドを直接呼び出すだけでReflectionのメリットを利用するとどのようなメリットがありますか? – ACobbs

+0

@ACobbsあなたが文字列からメソッドを最初に呼び出すかどうかわからない、次は、あなたがサイトを攻撃している場合、参照が一致しないということです。それはそれが属するクラスへの参照を使ってそのメソッドを呼び出します。 – Burimi

+0

@Cody **「許可された機能」の配列を追加してください。基本的にSecatorの答えはあなた自身で追加できますか?そうすれば、私は投票できる唯一の答えがあなたのものになるでしょう。 –

1

urlencode()は少し気になります。おそらく安全かもしれないが、私ははるかに厳密に浄化するだろう。私は文字、数字、アンダースコアのみを許可します。他の文字と実際にクラス名やメソッド名は必要ありません。私は今まで見たことがないと思う。

私は ためLOTすべての私のプロジェクトにおけるもののこれを使用

:少なくとも、クラスのために(

function very_safe_string($string) 
{ 
    return preg_replace("/[^A-Za-z0-9_]/" , '' , $string); 
} 

をそして他のポスターが言及しているとして、あなたは間違いなくホワイトリストのいくつかのタイプを明示的に許可する必要があります私はすべてのクラスがajaxからアクセスされる必要はないと確信しています)。 class_exists()とmethod_exists()をチェックするだけでなく、

これらのチェックのいずれかが失敗した場合は、電子メール警告システムを使用することをお勧めします。誰かがjxをhax0rにしようとしているかどうかを知りたいと思います。

関連する問題