php - 如何避免 PHP 中的反射注入(inject)攻击?

标签 php reflection code-injection

我正在编写一个类,它允许您将 HTTP 请求与使用 JSON 数据的类实例桥接起来,而无需在您正在桥接的类中进行任何实现。基本上这是它的工作原理:

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

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

JsonHttpInterface 类将检查请求的 PATH_INFO 并调用该方法,应用任何查询字符串参数作为参数。

http://example.com/the_above.php/getWeather?state="CA" 将转换为
$service->getWeather("CA")(假设第一个参数的名称是$state)。

这是找到和调用方法的方式:

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

现在我想知道的是:这样一个系统的弱点是什么。我对错误检查非常宽松,在尝试调用不存在或私有(private)/ protected 方法时依赖 PHP 抛出错误。

  • 是否可以欺骗系统?
  • 是否可以传入一个无效的方法名来执行除抛出错误之外的其他操作?
  • 是否可以引用基类或任何其他类中的方法?

JsonHttpInterface 的完整源代码可在此处获得:http://blixt.org/js/two-cents.php

最佳答案

您可以在不使用 ReflectionXYZ 类的情况下实现同样的效果

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

只要您控制 $this->instance 是什么,两者都以相同的方式保存。
$action 是一个字符串,用于搜索对象/类的方法哈希表中的条目,并且没有可以转义对象上下文(切换到另一个对象)的魔术符号。并且不涉及解析,例如在 sql 和 sql 注入(inject)中。
ReflectionMethod 和 call_user_func_array() 都遵循方法的保护级别。例如

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

打印

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

如果情况总是如此,您可能想查找一下。有例如条目 - MFH 修复了错误 #37816(ReflectionProperty 在访问 protected 属性时不会抛出异常)。至少对于 php 5.3 分支是这样。
您始终可以访问 $this->instance.
的任何基类的公共(public)方法 您可以从类上下文中访问 protected 方法,即如果 $this 和 $this->instance 是相同的/派生类型 $this->instance 的 protected 方法是可访问的。例如

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

打印 Bar::protectedfn() 被调用。但这应该不难避免。

关于php - 如何避免 PHP 中的反射注入(inject)攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2066305/

相关文章:

php - 如何将图像放在图像上并调整大小并拖动它

php - 设置 cookie 以保存登录详细信息 PHP

.net - 应该在多大程度上使用反射?

JAVA : How to get the name of variable with annotation in Java?

windows - 错误 0xc000007b 尝试绕行注入(inject) DLL 时

php - Mysql公式根据列中的值计算出他们有多少分

php - 从 azure 虚拟机使用 laravel 连接到 azure 数据库会引发 SQLSTATE[HY000] [2002] 错误

java - 如何使用反射调用外部 jar 内的方法

symfony - 我应该将学说注册表或特定存储库、实体管理器传递到 symfony2 中的 DI 容器吗?

linux - 如果不使用 eval,是否可以在 shell 脚本中执行命令注入(inject)?