PHP serialize() for object injection - php

I'm currently analyzing the PHP exploitation method called PHP Object Injection, which allows for modification of already defined objects due to unsanitized input in unserialize() function.
Here is the code:
<?php
class foo {}
class SuperClass {}
$ss = 'O:3:"foo":2:{s:4:"test";b:1;s:2:"fg";O:10:"SuperClass":0:{}};';
print_r(unserialize($ss));
?>
Which produces the following output:
foo Object
(
[test] => 1
[fg] => SuperClass Object
(
)
)
My question is, how would I recreate the object structure that I could pass to serialize() function that would create the same input string? PHP doesn't allow nested classes, so I'm quite puzzled as to if it is even possible to generate such string with serialize()?
Here is how I would do it, but due to PHP not allowing nested classes, it won't work:
class foo {
public $test = 1;
public $fg = class SuperClass {
}
}
echo serialize(new foo);

If you want to see how PHP will serialize a class structure like that, and that is what I assume you are asking then create your classes like this
<?php
class SuperClass
{
public $name = 'SuperClass';
}
class foo
{
public $name = 'foo';
public $test = 1;
}
$s = new SuperClass();
$f = new foo();
$s->fg = $f;
$ss = serialize($s);
echo $ss . PHP_EOL;
$hydrated = unserialize($ss);
print_r($hydrated);
This produces the following output
O:10:"SuperClass":2:{s:4:"name";s:10:"SuperClass";s:2:"fg";O:3:"foo":2:{s:4:"name";s:3:"foo";s:4:"test";i:1;}}
SuperClass Object
(
[name] => SuperClass
[fg] => foo Object
(
[name] => foo
[test] => 1
)
)
You can play with this to see how to manipulate the serialized string to add whatever content to the string to make the objects contain whatever you want.

Probably the fields needs to be an instance of the class.
class foo {
public $test = 1;
public $fg = new SuperClass();
}
var_dump(serialize(new foo()));
Alternatively to your syntax, PHP7 provides anonymous classes functionality
public $fg = new class() extends SuperClass {
// some additional implementation here
}
So you can add fields which later will be presented in the serialized string. In the current example none are present.

Related

"Cannot use temporary expression in write context" when assigning to prop on class instance defined as constant

The following code snippet will produce an error on PHP 8.2:
<?php
const foo = new stdClass();
foo->bar = 'baz';
echo foo->bar;
?>
I would expect that an error would not occur, since I am assigning to the prop rather than trying to reassign the constant.
If I create a new class, extending stdClass, and add the following method:
class extendsStdClass extends stdClass {
public function set(string $name, mixed $value) {
$this->$name = $value;
}
}
then I can assign to props using the following syntax:
<?php
const foo = new extendsStdClass();
foo->set('bar', 'baz');
echo foo->bar;
?>
but, the linter will not recognize props being set in this way, nor provide any type hinting:
Undefined property: extendsStdClass::$bar
Is there some reason we are not able to write to props on a class instance that is defined as a constant?
I'd like to be able to define this const in a namespace, and access/modify it via
If you want to modify it, then it's not a const.
If you actually want a const, then you can just use an array to get key/value pairs:
namespace MyNamespace {
const FOO = [
'one' => 1,
'two' => 2,
];
}
Then reference it anywhere via:
print_r(\MyNamespace\FOO);
Yields:
Array
(
[one] => 1
[two] => 2
)
And you can pull out a single value with array notation:
echo \MyNamespace\FOO['one'];
If you want something that you can reference directly by namespace, and still modify, you could create a class with static storage. Sort of like a half-assed singleton:
namespace MyNamespace;
class Foo
{
private static array $data = [];
public static function get($name)
{
return self::$data[$name] ?? null;
}
public static function set($name, $value)
{
self::$data[$name] = $value;
}
}
Then you can set values from anywhere:
\MyNamespace\Foo::set('one', 1);
And get values from anywhere:
echo \MyNamespace\Foo::get('one');

PHP - how to get the "use (...)" section using reflection [duplicate]

When you create a method that returns a closure in PHP:
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
The result of print_r contains this (the class whose method created the closure) and static, which appears to be the values bound within the use () statement of the closure:
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
Producing:
Closure Object (
[static] => Array (
[example] => 10
)
[this] => ExampleClass Object()
)
However I cannot for the life of me work out how to capture these values. It is not possible to use any form of property accessor (e.g. $closure->static or $closure->{'static'}) without receiving the following:
PHP Fatal error: Uncaught Error: Closure object cannot have properties in XYZ.
Array access notation obviously does not work either:
PHP Fatal error: Uncaught Error: Cannot use object of type Closure as array in XYZ.
JSON encoding the object, besides this making the values useless were they objects, provides an empty JSON object {} and using the ReflectionFunction class does not provide access to these items.
The closure documentation does not provide any means of accessing these values at all either.
Outside of doing something shameful like output buffering and parsing print_r or similar, I cannot actually see a way to get these values.
Am I missing something obvious?
Note: The use-case is for implementing memoization and these values would be extremely beneficial in identifying whether or not the call matched a previous cached call.
It seems you may have overlooked some of the ReflectionFunction methods.
Take a look at the ReflectionFunction::getClosureThis() method. I tracked it down by looking through the PHP 7 source code by doing a search for the zend_get_closure_this_ptr() which is defined in zend_closures.c.
The manual currently doesn't have a lot of documentation for this function. I'm using 7.0.9; try running this code based on your example:
class ExampleClass {
private $testProperty = 33;
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
$func = new ReflectionFunction($closure);
print_r($func->getClosureThis());
You should get output similar to
Closure Object
(
[static] => Array
(
[example] => 10
)
[this] => ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
)
ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
Regarding the closure static variables, these are returned with ReflectionFunction::getStaticVariables():
php > var_dump($func->getStaticVariables());
array(1) {
["example"]=>
int(10)
}
In order to get value of $example youn can try this
<?php
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$number = call_user_func($instance->test(),null);
I found this solution into a Laravel framework and works for me.
call_user_func helps you.

Reading "this" and "use" arguments from a PHP closure

When you create a method that returns a closure in PHP:
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
The result of print_r contains this (the class whose method created the closure) and static, which appears to be the values bound within the use () statement of the closure:
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
Producing:
Closure Object (
[static] => Array (
[example] => 10
)
[this] => ExampleClass Object()
)
However I cannot for the life of me work out how to capture these values. It is not possible to use any form of property accessor (e.g. $closure->static or $closure->{'static'}) without receiving the following:
PHP Fatal error: Uncaught Error: Closure object cannot have properties in XYZ.
Array access notation obviously does not work either:
PHP Fatal error: Uncaught Error: Cannot use object of type Closure as array in XYZ.
JSON encoding the object, besides this making the values useless were they objects, provides an empty JSON object {} and using the ReflectionFunction class does not provide access to these items.
The closure documentation does not provide any means of accessing these values at all either.
Outside of doing something shameful like output buffering and parsing print_r or similar, I cannot actually see a way to get these values.
Am I missing something obvious?
Note: The use-case is for implementing memoization and these values would be extremely beneficial in identifying whether or not the call matched a previous cached call.
It seems you may have overlooked some of the ReflectionFunction methods.
Take a look at the ReflectionFunction::getClosureThis() method. I tracked it down by looking through the PHP 7 source code by doing a search for the zend_get_closure_this_ptr() which is defined in zend_closures.c.
The manual currently doesn't have a lot of documentation for this function. I'm using 7.0.9; try running this code based on your example:
class ExampleClass {
private $testProperty = 33;
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$closure = $instance->test();
print_r($closure);
$func = new ReflectionFunction($closure);
print_r($func->getClosureThis());
You should get output similar to
Closure Object
(
[static] => Array
(
[example] => 10
)
[this] => ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
)
ExampleClass Object
(
[testProperty:ExampleClass:private] => 33
)
Regarding the closure static variables, these are returned with ReflectionFunction::getStaticVariables():
php > var_dump($func->getStaticVariables());
array(1) {
["example"]=>
int(10)
}
In order to get value of $example youn can try this
<?php
class ExampleClass {
public function test() {
$example = 10;
return function() use ($example) {
return $example;
};
}
}
$instance = new ExampleClass();
$number = call_user_func($instance->test(),null);
I found this solution into a Laravel framework and works for me.
call_user_func helps you.

How to programmatically find public properties of a class from inside one of it's methods

I've got a class Foo with public and protected properties. Foo needs to have a non-static method, getPublicVars() that returns a list of all the public properties of Foo (this is just an example, I know from outside the Foo object calling get_object_vars() will accomplish this and there is no need for my getPublicVars() method).
Note: This must also return dynamically declared properties assigned at runtime to the class instance (object) that aren't defined in the class's definition.
Here's the example:
class Foo{
private $bar = '123';
protect $boo = '456';
public $beer = 'yum';
//will return an array or comma seperated list
public function getPublicVars(){
// thar' be magic here...
}
}
$foo = new Foo();
$foo->tricky = 'dynamically added var';
$result = $foo->getPublicVars();
var_dump($result); // array or comma list with 'tricky' and 'beer'
What is the most concise way to get the only the public properties of an object from inside a class's own methods where both public and protected are visible?
I've looked at:
What is the best way to look inside a PHP class instance (object) to see all of its available public properties and methods?
But this doesn't seem to address my question as it points to using get_object_vars() from outside the object.
As you already realized, PHP's build in get_object_vars is scope-sensitive. You want the public object properties only.
So from that function to the public variant is not a large step:
function get_object_public_vars($object) {
return get_object_vars($object);
}
Calling this get_object_public_vars will give you only the public properties then because it is place out of scope of the current object.
If you need more fine-grained control, you can also make use of the ReflectionObject:
(new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);
Which has the benefit that you don't need to introduce another function in the global namespace.
Does not work with php version >=7
As such, I can't really recommend solution any longer.
Use reflection instead
To get the public properties from within the class
$publicProperties = call_user_func('get_object_vars', $this);
the "trick" is that get_object_vars is being called from the scope of call_user_func and not the scope of the object
no need for reflection, stand-alone functions, closures, etc
Another (PHP 7.* compatible) way is to cast $this to an array and filter out any binary keys. This is a little less verbose than using Reflection.
return array_filter(
(array) $this,
static fn(string $key): bool => strpos($key, "\0") !== 0, ARRAY_FILTER_USE_KEY,
);
Using the ReflectionClass, you can do this easily. For example, below, I make an associative array of all the public properties.
$rc = new \ReflectionClass($this);
//get all the public properties.
$props = $rc->getProperties(\ReflectionProperty::IS_PUBLIC);
$ret = [];
foreach($props as $p) {
//get the name and value of each of the public properties.
$ret[$p->getName()] = $p->getValue($this);
}
You can wrap it into a closure and bind it to nowhere, then you'll have an outer scope view to the local public properties.
public function getPublicVars(){
return \Closure::bind(fn($obj) => get_object_vars($obj),null,null)($this);
}
According to this article (written by Vance Lucas), you can create a new call scope inside your "Foo" class definition using an "anonymous" function, and then you can call get_object_vars() from within. This allow you to get only the public properties from inside your class, even if these have been created dynamically later from the outside.
So adapted to your example it would be:
<?php
class Foo {
private $bar = '123';
protected $boo = '456';
public $beer = 'yum';
// return an array of public properties
public function getPublicVars(){
$publicVars = create_function('$obj', 'return get_object_vars($obj);');
return $publicVars($this);
}
}
$foo = new Foo();
$foo->tricky = 'dynamically added var';
$result = $foo->getPublicVars();
print_r($result);
and the output will be:
Array
(
[beer] => yum
[tricky] => dynamically added var
)
There is a second example in the article mentioned above that shows another way to do the same using the so-called "closures" (from php 5.3) but for some reason it doesn't work for me with php v5.4 so the private and protected properties remains included in the resulting array.

Can you define class variables from within a class method in PHP?

I want to pull all info about a file from a files table, but that table's structure might change.
So, I'd like to pull all the field names from the table and use them to generate the class variables that contain the information, then store the selected data to them.
Is this possible?
Yes you can, see php overloading.
http://php.net/manual/en/language.oop5.overloading.php
Quick Example: ( Not this isn't great usage )
<?php
class MyClass{
var $my_vars;
function __set($key,$value){
$this->my_vars[$key] = $value;
}
function __get($key){
return $this->my_vars[$key];
}
}
$x = new MyClass();
$x->test = 10;
echo $x->test;
?>
Sample
<?php
class TestClass
{
public $Property1;
public function Method1()
{
$this->Property1 = '1';
$this->Property2 = '2';
}
}
$t = new TestClass();
$t->Method1();
print( '<pre>' );
print_r( $t );
print( '</pre>' );
?>
Output
TestClass Object
(
[Property1] => 1
[Property2] => 2
)
As you can see, a property that wasn't defined was created just by assigning to it using a reference to $this. So yes, you can define class variable from within a class method.

Categories