Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP Object Injection Revival

Avatar for alertot alertot
September 28, 2018

PHP Object Injection Revival

Avatar for alertot

alertot

September 28, 2018
Tweet

More Decks by alertot

Other Decks in Technology

Transcript

  1. 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
  2. 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
  3. Exploitation It’s called PHP Object Injection (POI). The exploitation is

    carried out through Property-oriented Programming (PoP). Quick intro
  4. 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
  5. Magic methods Methods with magic powers, according to PHP documentation.

    The two more famous in POI are: 1. __destruct() 2. __wakeup()
  6. 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
  7. Example 2/5 $w = new Writer; $w->data = 'hello'; $m

    = new Document; $m->filename = '/tmp/file'; $m->handler = $w; Quick intro
  8. 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
  9. 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
  10. Solution to motivation Find what Wordpress plugins must be present

    to turn the deserialization exploitable. Problem
  11. 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
  12. Magic methods 102 Magic methods are more than __destruct() and

    __wakeup(), let’s go to find other gems! Magic methods
  13. Unexpected class class UnexpectedClass { // no $carrot public attribute

    function __get($key = ‘carrot’) { [...] } } Magic methods - __get()
  14. 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()
  15. 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()
  16. Unexpected class class UnexpectedClass { // no $carrot public attribute

    function __set( key = ‘carrot’, $value = ‘123’) { [...] } } Magic methods - __set()
  17. 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()
  18. __call method __call() is triggered when invoking inaccessible methods in

    an object context. Almost the same for __callStatic(). Magic methods
  19. Unexpected class class UnexpectedClass { // no carrot method public

    function __call($key = ‘carrot’, $args) { [...] } } Magic methods - __call()
  20. 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()
  21. Definition __toString() method allows a class to decide how it

    will react when it is treated like a string. Magic methods - __toString()
  22. Foundations The ArrayAccess interface Interface to provide accessing objects as

    arrays. Also found in: ArrayObject class. The array set
  23. 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
  24. 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
  25. Gadget #1 class Example implements Iterator { function current ()

    {...} function key () {...} function next () {...} function rewind () {...} function valid () {...} } The iterator set
  26. 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
  27. 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
  28. Additional sets • Serializable interface & unserialize() • new statement

    & __construct() • Countable interface & count()
  29. Editor • Focused on gadget chains building • Uses the

    same PHP parser as actual editors • Creates phpggc-ish gadgets poiwer
  30. 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
  31. 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