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

PHP Object Injection Revival

alertot
September 28, 2018

PHP Object Injection Revival

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