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
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.