PHP nasıl yansıma enjeksiyon saldırıları önlemek mi?

3 Cevap php

Ben HTTP size köprü konum sınıfındaki herhangi bir uygulama olmadan, veri JSON kullanarak sınıf örnekleri ile talep köprü sağlayan bir sınıf yazıyorum. Temelde bu nasıl işliyor:

// This is just an ordinary class.
$service = new WeatherService();

$jhi = new JsonHttpInterface($service);
$jhi->exec();

JsonHttpInterface class isteği PATH_INFO kontrol ve argüman olarak herhangi bir sorgu dizesi parametrelerini uygulayarak, bu yöntemi arayacak.

http://example.com/the_above.php/getWeather?state="CA" would translate to
$service->getWeather("CA") (assuming that the name of the first argument is $state).

Bu yöntem buldu ve denir nasıl:

$method = new ReflectionMethod(get_class($this->instance), $action);
/*
... code that matches query string values to arguments of above method...
*/
$response = $method->invokeArgs($this->instance, $args);

Şimdi ne olduğunu merak ediyorum: Böyle bir sistemin güvenlik açıkları nelerdir. Ben varolmayan veya özel / korumalı yöntemleri çağırmak için çalışırken hataları atmak için PHP güvenerek, hata denetimi oldukça hoşgörülü oldum.

  • Bu sistem hile mümkün mü?
  • Bir hata atmak dışında bir şeyler yapan bir geçersiz yöntem adı geçmek mümkün mü?
  • Bir temel sınıf veya başka bir sınıfta bir yönteme başvurmak mümkün mi?

JsonHttpInterface tam kaynağı burada mevcuttur: http://blixt.org/js/two-cents.php

3 Cevap

Sen ReflectionXYZ sınıfları kullanmadan aynı elde edebilirsiniz

call_user_func( array($this->instance, $action) , $args);

And both are save in the same way, as long as you control what $this->instance is.
$action is a string that is used to search an entry in the object's/class' method hashtable and there's no magic symbol that can escape the object context (switching to another object). And there's no parsing involved like e.g. in sql and sql injections.
Both ReflectionMethod and call_user_func_array() honour the protection level of methods. e.g.

class Foo {
  public function publicfn() {
    echo 'abc';
  }

  protected function protectedfn() {
    echo 'xyz';
  }
}

$obj = new Foo;
call_user_func_array(array($obj, 'publicfn'), array());
call_user_func_array(array($obj, 'protectedfn'), array());
$ro = new ReflectionMethod($obj, 'protectedfn');
$ro->invokeArgs($obj, array());

baskılar

abc
Warning: call_user_func_array() expects parameter 1 to be a valid callback, cannot access protected method Foo::protectedfn() in blabla on line 14

Fatal error: Uncaught exception 'ReflectionException' with message 'Trying to invoke protected method Foo::protectedfn() from scope ReflectionMethod' in blabla:16
Stack trace:
#0 blabla(16): ReflectionMethod->invokeArgs(Object(Foo), Array)
#1 {main}
  thrown in blabla on line 16

You might want to look up if this was always the case. There's e.g. an entry - MFH Fixed bug #37816 (ReflectionProperty does not throw exception when accessing protected attribute). At least it's true for php 5.3 branch.
You can always access public methods of any base class of $this->instance.
You can access protected methods from within the class context, i.e. if $this and $this->instance are of the same/a derived type protected methods of $this->instance are accessible. e.g.

class Foo {
  protected $instance;
  public function __construct(Foo $instance=null) {
    $this->instance = $instance;
  }
  public function publicfn() {
    if ( !is_null($this->instance)) {
      call_user_func_array( array($this->instance, 'protectedfn'), array());
    }
  }

  protected function protectedfn() {
    echo 'Foo::protectedfn() invoked';
  }
}

class Bar extends Foo {
  protected function protectedfn() {
    echo 'Bar::protectedfn() invoked';
  }
}

$foo = new Foo(new Bar);
$foo->publicfn();

baskılar Bar::protectedfn() invoked. But that shouldn't be too hard to avoid.

Her şeyden önce,

Bir white_list oluşturmanız gerekir.

Sen nesnenin tanımlı fonksiyonlar olsun, ve size gönderilen işlev adı dizide olup olmadığını, eğer iyi, başka, unut gitsin, görmek için kontrol edin.

Otomatik bir beyaz liste, ya da yapılandırılmış bir manuel birini tercih yapabilirsiniz ya.

Tüm geçmiş değerleri için bir munging / yıkama fonksiyonu oluşturmak gerekir.

Bir devletin örnekte, devlet CA, ya da California olabilir, bu yüzden aslında, preg_match ('/ \ + / w') böylece verileri doğrulamak için kontrol bazı kolay yapabilirsiniz. Gerekir

Eğer fantezi olsun istedim, insanlar FunctionName bir karma harita allowedValues ​​denilen bir yöntem oluşturmak için izin verebilir => / Regex / ve kullanmak geçerli bir veri arama tablosu gibi, işlev sınıfında tanımlı değilse , sen yalnızca belirli bir uzunlukta dize / numaraları ve perhops sağlayan bir genel birini kullanın.

    class MyClass{

    public function allowedArguments() {
        //This acts as a white list, and a cleaner/restricter
        return array(
            'myfunc' => array(
                'pattern' => '/\w+/'
                'length' => 255
            )
        );
    }

    public function myFunc($arg) {
        ... do something
    }
}

Kullanıcı tarafından girilen PHP kod verir Anthing bazı sömürüye açık olması muhtemeldir, bu yüzden kesinlikle yüksek risk. Onunla devam yaparsanız sonra bir onay ben bu şekilde erişilen istediğiniz sınıfları belirli bir arabirim uygulamak ve yürütmeden önce arayüzü kontrol yapıyor gibi düşünün. Yani bu şekilde yürütülen herhangi bir keyfi sınıfını önlemek ve sadece özel izin ettik olanlar için kısıtlamak olur.

Daha iyi bir çözüm ihtiyacınız tüm çağrılar, sen explictly yerine tüm delikleri nerede olabilir ikinci tahmin etmeye çalışırken daha belirli eylemleri izin ettik yol statik dosyaları otomatik oluşturmak için olabilir.