Share
Embed
PHP Object Injection Revival
alertot
September 28, 2018
Transcript
78 slides
-
Whois • CEO and co-founder @alertot • Founder @spect.cl •
Open-source contributor -
Agenda • Quick intro to serialization • Current problem •
Gadgets' shape • poiwer, the tool -
What is serialization? • Serialization was thought to transport objects.
• It creates a string representation of any data type. • Deserialization is the inverse process. Quick intro -
Problem The problem happens when a program unserializes untrusted data.
In a normal flow, the program expects to create X but eventually creates Z. Quick intro -
Exploitation It’s called PHP Object Injection (POI). The exploitation is
carried out through Property-oriented Programming (PoP). Quick intro -
Property-oriented Programming • It reuses classes available in the project.
• Classes with interesting methods are the gadgets. • Interesting methods are driven by controlled data. • The goal is to chain objects to achieve something. Quick intro -
Magic methods Methods with magic powers, according to PHP documentation.
The two more famous in POI are: 1. __destruct() 2. __wakeup() -
Example 1/5 class Writer { public $data; function save($filename) {
file_put_contents($filename, $this->data); } } class Document { public $filename; public $handler; function __destruct() { $this->handler->save($this->filename); } } Quick intro Both classes are part of the app -
Example 2/5 $w = new Writer; $w->data = 'hello'; $m
= new Document; $m->filename = '/tmp/file'; $m->handler = $w; Quick intro -
Example 3/5 class Writer { public $data = ‘hello’; function
save($filename) { file_put_contents($filename, $this->data); } } class Document { public $filename = ‘/tmp/file’; public $handler = new Writer; function __destruct() { $this->handler->save($this->filename); } } Quick intro -
Clarifications • We work only with available classes (no code
creation). • We can set any kind of property in class. • Distinction between data and functions. Quick intro -
Exploitation methods * (https://blog.secarma.co.uk/labs/near-phar-dangerous-unserialization-wherever-you-are) **(https://www.evonide.com/how-we-broke-php-hacked-pornhub-and-earned-20000-dollar/) Quick intro - Serialized string
- Exploit unserialize() function ** unserialize function phar files * -
Solution to motivation Find what Wordpress plugins must be present
to turn the deserialization exploitable. Problem -
Example explanation 1. class ExpectedClass { carrot } 2. $instance
= new ExpectedClass; 3. $my_data = serialize($instance); 4. $obj = unserialize($my_data); 5. some operation on carrot! Gadget’s shape -
Magic methods 102 Magic methods are more than __destruct() and
__wakeup(), let’s go to find other gems! Magic methods -
Definition __get() is utilized for reading data from inaccessible properties.
Magic methods - __get() -
Expected class class ExpectedClass { public $carrot = 123; }
Magic methods - __get() -
Unexpected class class UnexpectedClass { // no $carrot public attribute
function __get($key = ‘carrot’) { [...] } } Magic methods - __get() -
Real-world example (1/2) class ValidGenerator { public function __get($attribute) {
return $this->__call($attribute, array()); } } * fzaninotto/faker/src/Faker/ValidGenerator.php Magic methods - __get() -
Real-world example (2/2) public function __call($name, $arguments){ do { $res
= call_user_func_array( array($this->generator, $name), $arguments ); [...] } while (!call_user_func($this->validator, $res)); } * fzaninotto/faker/src/Faker/ValidGenerator.php Magic methods - __get() -
__set method __set() is run when writing data to inaccessible
properties. Magic methods -
Unexpected class class UnexpectedClass { // no $carrot public attribute
function __set( key = ‘carrot’, $value = ‘123’) { [...] } } Magic methods - __set() -
Real-world example class CI_Session { public function __set($key, $value) {
$_SESSION[$key] = $value; } } * CodeIgniter-3.1.9/system/libraries/Session/Session.php Magic methods - __set() -
Similar magic methods __isset($key) -> isset() or empty() __unset($key) ->
unset() Magic methods -
__call method __call() is triggered when invoking inaccessible methods in
an object context. Almost the same for __callStatic(). Magic methods -
Expected class class ExpectedClass { public function carrot() { return
‘hello’; } } Magic methods - __call() -
Unexpected class class UnexpectedClass { public function carrot() { return
‘bye’; } } Magic methods - __call() -
Unexpected class class UnexpectedClass { // no carrot method public
function __call($key = ‘carrot’, $args) { [...] } } Magic methods - __call() -
Real-world example class TraceableEventDispatcher { public function __call($method, $arguments) {
return \call_user_func_array( array($this->dispatcher, $method), $arguments ); } } * symfony/event-dispatcher/Debug/TraceableEventDispatcher.php Magic methods - __call() -
Definition __toString() method allows a class to decide how it
will react when it is treated like a string. Magic methods - __toString() -
Unexpected class class UnexpectedClass { public function __toString() { return
‘bye’; } } Magic methods - __toString() -
Sets Sets are related gadgets given by the use of
an interface or class. -
Foundations The ArrayAccess interface Interface to provide accessing objects as
arrays. Also found in: ArrayObject class. The array set -
Cases $theArray = unserialize($my_data); $v = $theArray[$key]; offsetGet($key) $theArray[$key] =
1; offsetSet($key, value) empty($theArray[$key]); offsetExists($key) unset($theArray[$key]); offsetUnset($key) The array set -
Scenario The program thinks it’s working on a normal array.
The iterator set -
Foundations The Traversable interface Interface to detect if a class
is traversable using foreach. Also found in: Iterator, IteratorAggregate interfaces and ArrayObject class. The iterator set -
Gadget #1 class Example implements Iterator { function current ()
{...} function key () {...} function next () {...} function rewind () {...} function valid () {...} } The iterator set -
Gadget #2 class Example implements IteratorAggregate { function getIterator ()
{...} } The iterator set -
Real-world example: Symfony Console class TableRows implements \IteratorAggregate { public
function getIterator() { $g = $this->generator; return $g(); } } * symfony/console/Helper/TableRows.php The iterator set -
Foundations The JsonSerializable interface Can customize their JSON representation when
encoded with json_encode(). The json set -
Real-world example: CakePHP Mailer class Email implements JsonSerializable, Serializable {
public function jsonSerialize() { array_walk($array['_attachments'], function (&$item, $key) { if (!empty($item['file'])) { $item['data'] = $this->_readFile($item['file']); unset($item['file']); } }); } } * cakephp/cakephp/src/Mailer/Email.php The json set -
Additional sets • Serializable interface & unserialize() • new statement
& __construct() • Countable interface & count() -
Additional ideas • Combine seen gadgets as you want •
Gadgets chaining in an array -
Editor • Focused on gadget chains building • Uses the
same PHP parser as actual editors • Creates phpggc-ish gadgets poiwer -
Generated code 1/2 namespace GuzzleHttp\Cookie; class SetCookie { private $data
= ['Expires' => 1, 'Discard' => 0, 'Data' => "injection"]; public function __construct($data) { $this->data = $data; } } poiwer -
Generated code 2/2 class CookieJar { private $cookies = [new
SetCookie]; public function __construct() { } } class FileCookieJar extends CookieJar { private $filename = "injection"; public function __construct($filename) { $this->filename = $filename; } } poiwer