如何避免 PHP 中的反射注入攻击?
我正在编写一个类,它允许您使用 JSON 数据来桥接 HTTP 请求与类实例,而无需在您要桥接的类中进行任何实现。基本上它的工作原理是这样的:
// 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);
现在我想知道的是:这样的系统有哪些漏洞。我对错误检查相当宽松,依靠 PHP 在尝试调用不存在或私有/受保护的方法时抛出错误。
- 是否可以欺骗系统?
- 是否可以传入一个无效的方法名称来执行除抛出错误之外的其他操作?
- 是否可以引用基类或任何其他类中的方法?
JsonHttpInterface 的完整源代码可以在这里找到: http://blixt.org/js/two-cents .php
I'm writing a class that allows you to bridge HTTP requests with class instances using JSON for data, without any implementation in the class you're bridging to. Basically this is how it works:
// This is just an ordinary class.
$service = new WeatherService();
$jhi = new JsonHttpInterface($service);
$jhi->exec();
The JsonHttpInterface
class will check the PATH_INFO
of the request and call that method, applying any query string parameters as arguments.
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
).
This is how the method is found and called:
$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);
Now what I'm wondering is: what are the vulnerabilities of such a system. I've been pretty lenient on error checking, relying on PHP to throw errors when attempting to call non-existent or private/protected methods.
- Is it possible to cheat the system?
- Is it possible to pass in an invalid method name that does something other than throw an error?
- Is it possible to refer to a method in a base class, or any other class?
The full source of JsonHttpInterface is available here: http://blixt.org/js/two-cents.php
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以在不使用 ReflectionXYZ 类的情况下实现相同的效果,
并且两者都以相同的方式保存,只要您控制 $this->instance 是什么。
$action 是一个字符串,用于搜索对象/类的方法哈希表中的条目,并且没有可以逃脱对象上下文(切换到另一个对象)的魔法符号。并且不涉及像 sql 和 sql 注入那样的解析。
ReflectionMethod 和 call_user_func_array() 都遵循方法的保护级别。例如
打印
您可能需要查找是否总是如此。例如,有一个条目
- MFH 修复了错误#37816(ReflectionProperty 在访问受保护的属性时不会抛出异常)
。至少对于 php 5.3 分支来说是这样。您始终可以访问 $this->instance 的任何基类的公共方法。
您可以从类上下文中访问受保护的方法,即如果 $this 和 $this->instance 具有相同/派生类型,则可以访问 $this->instance 的受保护方法。例如
打印
Bar::protectedfn() invoked
。但这应该不难避免。You can achieve the same without using the ReflectionXYZ classes
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.
prints
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.
prints
Bar::protectedfn() invoked
. But that shouldn't be too hard to avoid.首先,
您需要创建一个白名单。
您获取对象的定义函数,然后检查发送给您的函数名称是否在数组中,如果是,则很好,否则,忘记它。
您可以选择自动创建白名单,也可以配置手动白名单。
您需要为所有传递的值创建一个修改/清洗函数。
在州的示例中,州可以是加利福尼亚州或加利福尼亚州,因此本质上,它必须 preg_match('/\w+/') 以便您可以进行一些简单的检查来验证数据。
如果你想变得更奇特,你可以允许人们创建一个名为 allowedValues 的方法,它是 functionName => 的哈希映射。 /Regex/,并将其用作有效的数据查找表,如果该函数未在类中定义,则使用仅允许字符串/数字和特定长度的通用函数。
First of all,
You need to create a white_list.
You get the defined functions of the object, and you check to see if the function name sent to you is in the array, if it is, good, else, forget about it.
You can either do an automatic whitelist, or a manual one that is configured, your choice.
You need to create a munging/washing function for all passed values.
In the example of a state, state can be CA, or California, so essentially, it must preg_match('/\w+/') so you can do some easy checking to verify data.
If you wanted to get fancy, you could allow people to create a method called allowedValues which is a hash map of functionName => /Regex/, and use that as a valid data lookup table, if the function isn't defined in the class, you use a generic one that only allows string/numbers and perhops only of a certain length.
允许用户输入 PHP 代码的东西很可能会受到某些利用,因此它的风险肯定很高。如果您确实继续这样做,那么我会考虑包括的一项检查是让您想要以这种方式访问的任何类实现特定的接口,并在执行之前检查该接口。这将防止以这种方式执行任何任意类,并将其限制为您特别允许的类。
更好的解决方案可能是自动生成包含您需要的所有调用的静态文件,这样您就明确允许特定操作,而不是试图事后猜测所有漏洞可能在哪里。
Anthing that allows user-entered PHP code is likely to be open to some exploitation, so it's certainly high risk. If you do keep going with it then one check I would consider including is making any classes that you want accessed in this way implement a particular interface and check for the interface before executing. That would prevent any arbitrary class from being executed in that way and just restrict it to those that you've specifically allowed.
A better solution might be to to auto-generate static files with all the calls in that you need, that way you've explictly allowed particular actions rather than trying to second-guess where all the holes might be.