2012-07-10 12 views
6

Próbuję utworzyć skrypt AJAX, który przyjmie dwie zmienne GET, klasę i metodę, i zamapuje je na zaprojektowane przez nas metody (podobne do tego, jak CodeIgniter działa dla ajax, I jestem prawie pewien). Ponieważ polegam na danych wprowadzanych przez użytkownika w celu określenia klasy i metody wykonania, obawiam się, że haker może w jakiś sposób wykorzystać tę technikę na swoją korzyść.Bezpieczne wywoływanie funkcji opartej na wprowadzaniu danych przez użytkownika

Kod:

//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(); 
} 

Czy są jakieś wady lub bezpieczeństwa watch-out powinien być świadomy podczas korzystania z tej techniki?

Odpowiedz

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); 
} 

Połącz z niektórych innych odpowiedzi dla najlepszych rezultatów. Wymaga PHP 5.3.0 lub nowszego. Można nawet zaimplementować interfejs

<?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); 
} 

Takie podejście wynika zasad OOP, jest bardzo rozwlekły (Łatwe w utrzymaniu) i nie wymaga, aby utrzymać tablicę z których zajęcia można nazwać, a które nie.

+1

Ten interfejs AjaxCallable był świetnym pomysłem, działa idealnie. Dzięki! – ACobbs

+0

Cieszę się, że to zadziałało dla Ciebie :) –

4

Biorąc pod uwagę, że nie przekazujesz żadnych argumentów, jest to na razie względnie bezpieczne. Ale chciałbym dodać listę ważnych zajęć w Twojej IF takich jak:

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

ten sposób haker może nie nazwać ewentualnych klasy w ramach tej drodze, ale tylko te, które pozwoli mu.

14

Sprawdź, czy metoda może być wywołana przez użytkownika:

// 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(); 
} 

Inaczej nie masz kontroli, co użytkownik będzie mógł zrobić.

+4

+1. Biała lista, nie czarna lista. – Polynomial

+2

dobra odpowiedź; używanie samych method_exists nadal może powodować nieoczekiwane rzeczy do zadowolenia. – Erik

+0

I okropne rzeczy też. –

2

W tym przypadku musisz obsłużyć numer Reflection.

Oto przykład tego, czego potrzebujesz.

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

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

Wykonywanie metoda może być tak użyciu ReflectionMethods:invoke:

<?php 
class HelloWorld { 

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

} 

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

Więc wreszcie mogliśmy:

$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

Jakie korzyści daje skorzystanie z oferty Reflection w przypadku bezpośredniego wywoływania metody? – ACobbs

+0

@ ACobbs nie jestem pewien, czy najpierw wywołasz metodę z łańcucha, a następnie, jeśli ktoś zaatakuje twoją witrynę, nie będzie to niezgodne. Wywołuje tę metodę, używając jej odniesienia do klasy, do której należy. – Burimi

+0

@Cody Czy możesz ** proszę ** dodać tablicę dla "dozwolonych funkcji" i zasadniczo uwzględnić odpowiedź Secatora na własną rękę? Wtedy twoja będzie niezaprzeczalnie jedyną odpowiedzią, na którą mogę głosować. –

1

Kod urlenia() nieco mnie martwi. Choć może to być bezpieczne, odkażę znacznie bardziej surowo. Dopuszczałem tylko litery, cyfry i podkreślenia. Nie powinieneś naprawdę potrzebować żadnych nazw klas ani metod z innymi postaciami. Nie sądzę, żebym kiedykolwiek widział.

Używam tego dla LOT rzeczy we wszystkich moich projektach:

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

I jak inne plakaty wspomnieli, to zdecydowanie powinien mieć jakiś rodzaj białej liście wyraźnie pozwalając (dla klas przynajmniej , ponieważ jestem pewien, że nie każda klasa musi być dostępna z ajax). Oprócz sprawdzania class_exists() i method_exists().

Polecam również system ostrzegania pocztą e-mail, jeśli któraś z tych kontroli nie powiedzie się.Jestem pewien, że chciałbyś wiedzieć, czy ktoś próbuje hax0r j00.

Powiązane problemy