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

PHP Object Injection Revival

Da063846b29d8d418fa1eda0d9b90706?s=47 alertot
September 28, 2018

PHP Object Injection Revival

Da063846b29d8d418fa1eda0d9b90706?s=128

alertot

September 28, 2018
Tweet

Transcript

  1. PHP Object Injection REVIVAL Claudio Salazar

  2. Whois • CEO and co-founder @alertot • Founder @spect.cl •

    Open-source contributor
  3. Agenda • Quick intro to serialization • Current problem •

    Gadgets' shape • poiwer, the tool
  4. Disclaimer I’m not expert in PHP! Quick intro

  5. 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
  6. Equation $variable <-> unserialize(serialize($variable)); (most cases) Quick intro

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

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

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

    = new Document; $m->filename = '/tmp/file'; $m->handler = $w; Quick intro
  13. 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
  14. Example 4/5 $serializedData = serialize($m); O:8:"Document":2:{ s:8:"filename";s:9:"/tmp/file"; s:7:"handler";O:6:"Writer":1:{ s:4:"data";s:5:"hello"; }

    } Quick intro
  15. Example 5/5 unserialize($serializedData); $ cat /tmp/file hello Quick intro

  16. 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
  17. Exploitation methods * (https://blog.secarma.co.uk/labs/near-phar-dangerous-unserialization-wherever-you-are) Quick intro unserialize function phar files

    *
  18. 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 *
  19. Current problem

  20. Motivation $request = unserialize($myData); $request = other_function($request['green']); Problem

  21. General solution Autoloading Problem

  22. Solution to motivation Find what Wordpress plugins must be present

    to turn the deserialization exploitable. Problem
  23. Gadget’s shape

  24. 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
  25. Magic methods 102 Magic methods are more than __destruct() and

    __wakeup(), let’s go to find other gems! Magic methods
  26. Definition __get() is utilized for reading data from inaccessible properties.

    Magic methods - __get()
  27. Use case $obj = unserialize($my_data); $attrib = $obj->carrot; Magic methods

    - __get()
  28. Expected class class ExpectedClass { public $carrot = 123; }

    Magic methods - __get()
  29. Unexpected class class UnexpectedClass { // no $carrot public attribute

    function __get($key = ‘carrot’) { [...] } } Magic methods - __get()
  30. 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()
  31. 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()
  32. __set method __set() is run when writing data to inaccessible

    properties. Magic methods
  33. Use case $obj = unserialize($my_data); $obj->carrot = 123; Magic methods

    - __set()
  34. Expected class class ExpectedClass { public $carrot; } Magic methods

    - __set()
  35. Unexpected class class UnexpectedClass { // no $carrot public attribute

    function __set( key = ‘carrot’, $value = ‘123’) { [...] } } Magic methods - __set()
  36. 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()
  37. Similar magic methods __isset($key) -> isset() or empty() __unset($key) ->

    unset() Magic methods
  38. __call method __call() is triggered when invoking inaccessible methods in

    an object context. Almost the same for __callStatic(). Magic methods
  39. Use case $obj = unserialize($my_data); $obj->carrot(); Magic methods - __call()

  40. Expected class class ExpectedClass { public function carrot() { return

    ‘hello’; } } Magic methods - __call()
  41. Unexpected class class UnexpectedClass { public function carrot() { return

    ‘bye’; } } Magic methods - __call()
  42. Unexpected class class UnexpectedClass { // no carrot method public

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

    will react when it is treated like a string. Magic methods - __toString()
  45. Use case $obj = unserialize($my_data); echo $obj; Magic methods -

    __toString()
  46. Expected value $carrot = ‘hello’; Magic methods - __toString()

  47. Unexpected class class UnexpectedClass { public function __toString() { return

    ‘bye’; } } Magic methods - __toString()
  48. Sets Sets are related gadgets given by the use of

    an interface or class.
  49. Sets The array set

  50. Scenario The program thinks it’s working on a normal array.

    The array set
  51. Foundations The ArrayAccess interface Interface to provide accessing objects as

    arrays. Also found in: ArrayObject class. The array set
  52. 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
  53. Caution It’s not a real array. The array set

  54. Sets The iterator set

  55. Scenario The program thinks it’s working on a normal array.

    The iterator set
  56. Case $theArray = unserialize($my_data); foreach($theArray as $element) {...} The iterator

    set
  57. 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
  58. Gadget #1 class Example implements Iterator { function current ()

    {...} function key () {...} function next () {...} function rewind () {...} function valid () {...} } The iterator set
  59. Gadget #2 class Example implements IteratorAggregate { function getIterator ()

    {...} } The iterator set
  60. 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
  61. Sets The json set

  62. Scenario The program encodes a variable as a JSON string.

    The json set
  63. Case $obj = unserialize($my_data); $jsonString = json_encode($obj); The json set

  64. Foundations The JsonSerializable interface Can customize their JSON representation when

    encoded with json_encode(). The json set
  65. Gadget class Example implements JsonSerializable { function jsonSerialize () {...}

    } The json set
  66. 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
  67. Additional sets • Serializable interface & unserialize() • new statement

    & __construct() • Countable interface & count()
  68. Additional ideas • Combine seen gadgets as you want •

    Gadgets chaining in an array
  69. The tool POIwer

  70. Architecture poiwer

  71. Gadget hints poiwer

  72. Exploitation poiwer

  73. Download software to analysis poiwer

  74. Editor • Focused on gadget chains building • Uses the

    same PHP parser as actual editors • Creates phpggc-ish gadgets poiwer
  75. Video time poiwer

  76. 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
  77. 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
  78. github.com/alertot/poiwer