Practical PHP Object Injection
Total Page:16
File Type:pdf, Size:1020Kb
Practical PHP Object Injection Practical PHP Object Injection $(whoami) Brendan Jamieson (@hyprwired) . Wellington based consultant for Insomnia Security . Infosec . Linux . Python . CTF (@hamiltr0n_ctf) . Apparently 16/12/2015 Practical PHP Object Injection Talk Overview 1. Theory 4. TODO.txt Objects 101 Future ideas PHP Serialization 101 Magic Methods + Autoloading PHP Object Injection 101 2. Bug Hunting Finding PHP Object Injection Finding useful POP chains 3. Exploitation Building POP chains Demos 16/12/2015 Practical PHP Object Injection PHASE 1 - THEORY 16/12/2015 Practical PHP Object Injection Objects in PHP . Objects in code can represent anything . An object is defined by a class . e.g. a Hacker object is defined by the Hacker class 16/12/2015 Practical PHP Object Injection Hacker class class Hacker { private $beard_length; public function __construct(){ $this->beard_length = 0; } public function grow_beard($grow_length){ $this->beard_length += $grow_length; } } 16/12/2015 Practical PHP Object Injection Hacker objects <?php require("./Hacker.php"); $hyprwired = new Hacker(); . 16/12/2015 Practical PHP Object Injection Hacker objects <?php require("./Hacker.php"); $hyprwired = new Hacker(); $hyprwired->grow_beard(0); // Maybe one day . 16/12/2015 Practical PHP Object Injection Hacker objects <?php require("./Hacker.php"); $hyprwired = new Hacker(); $hyprwired->grow_beard(0); // Maybe one day $metlstorm = new Hacker(); . 16/12/2015 Practical PHP Object Injection Hacker objects 16/12/2015 Practical PHP Object Injection Hacker objects <?php require("./Hacker.php"); $hyprwired = new Hacker(); $hyprwired->grow_beard(0); $metlstorm = new Hacker(); $metlstorm->grow_beard(9001); 16/12/2015 Practical PHP Object Injection What is (de)serialization used for? . (De)serialization allows for easy transfer of objects. e.g. serialize() an object to a string . write string to a file . unserialize() file’s contents back into an object . Deserialization of data is not necessarily dangerous . Deserialization of user controllable data is 16/12/2015 Practical PHP Object Injection PHP Serialized Format . boolean . NULL b:<value>; N; // NULL b:1; // True b:0; // False . string s:<length>:"<value>"; . integer s:8:"INSOMNIA"; // "INSOMNIA" i:<value>; i:1; // 1 . array i:-3; // -3 a:<length>:{key, value pairs}; a:2:{s:4:"key1";s:6:"value1"; . double s:4:"key2";s:6:"value2";} d:<value>; // array("key1" => "value1", "key2" => "value2"); d:1.2345600000000001; // 1.23456 16/12/2015 Practical PHP Object Injection Serialization Example – Class Definition <?php . Foobar.php class Foobar{ private $state = 'Inactive'; public function set_state($state){ $this->state = $state; } public function get_state(){ return $this->state; } } 16/12/2015 Practical PHP Object Injection Serialization Example – Class Definition <?php . Foobar.php class Foobar{ private $state = 'Inactive'; . Example class “Foobar” public function set_state($state){ $this->state = $state; } public function get_state(){ return $this->state; } } 16/12/2015 Practical PHP Object Injection Serialization Example – Class Definition <?php . Foobar.php class Foobar{ private $state = 'Inactive'; . Example class “Foobar” public function set_state($state){ $this->state = $state; . Simple class that has a “state” } property public function get_state(){ return $this->state; } } 16/12/2015 Practical PHP Object Injection Serialization Example - serialize() <?php . serialize.php require('./Foobar.php'); $object = new Foobar(); . New Foobar object is created $object->set_state('Active'); . Property is set, object serialized $data = serialize($object); file_put_contents('./serialized.txt', . Serialized value is saved to file $data); ?> 16/12/2015 Practical PHP Object Injection Serialization Example - Serialized Object Format $ cat serialized.txt O:6:"Foobar":1:{s:13:"Foobarstate";s:6:"Active";} O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>}; 16/12/2015 Practical PHP Object Injection Serialization Example - Serialized Object Format $ cat serialized.txt O:6:"Foobar":1:{s:13:"Foobarstate";s:6:"Active";} O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>}; . O:6:"Foobar" . Object, 6 character long name (“Foobar”) 16/12/2015 Practical PHP Object Injection Serialization Example - Serialized Object Format $ cat serialized.txt O:6:"Foobar":1:{s:13:"Foobarstate";s:6:"Active";} O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>}; . O:6:"Foobar" . Object, 6 character long name (“Foobar”) . 1 . Object has 1 property 16/12/2015 Practical PHP Object Injection Serialization Example - Serialized Object Format $ cat serialized.txt O:6:"Foobar":1:{s:13:"Foobarstate";s:6:"Active";} O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>}; . O:6:"Foobar" . Object, 6 character long name (“Foobar”) . 1 . Object has 1 property . s:13:"Foobarstate";s:6:"Active"; . Object’s properties; “state” with value “Active” 16/12/2015 Practical PHP Object Injection Serialization Example - Serialized Object Format $ cat serialized.txt O:6:"Foobar":1:{s:13:"Foobarstate";s:6:"Active";} O:<class_name_length>:"<class_name>":<number_of_properties>:{<properties>}; . O:6:"Foobar" . Object, 6 character long name (“Foobar”) Wait a minute… “Foobarstate” is only . 1 11 characters long? . Object has 1 property . s:13:"Foobarstate";s:6:"Active"; . Object’s properties; “state” with value “Active” 16/12/2015 Practical PHP Object Injection Serialization Example - Serialized Object Format 16/12/2015 Practical PHP Object Injection Serialization Example - unserialize() <?php . unserialize.php require('./Foobar.php'); . File containing serialized object read $filename = './serialized.txt'; $file_contents = file_get_contents($filename); . Object created from stored value $object = unserialize($file_contents); var_dump($object->get_state()); var_dump($object); ?> 16/12/2015 Practical PHP Object Injection Magic Methods - Part I PHP classes have a specific subset of “magic methods”: . __construct(), __destruct() . __call(), __callStatic() . __get(), __set() . __isset(), __unset() . __sleep(), __wakeup() . __toString() . __invoke() . __set_state() . __clone() . __debugInfo() 16/12/2015 Practical PHP Object Injection Magic Methods - Part I PHP classes have a specific subset of “magic methods”: . __construct(), __destruct() . __call(), __callStatic() . __get(), __set() . __isset(), __unset() . __sleep(), __wakeup() . __toString() For this talk, we’ll . __invoke() focus on these two. __set_state() . __clone() . __debugInfo() 16/12/2015 Practical PHP Object Injection Magic Methods - Part II . __wakeup() "unserialize() checks for the presence of a function with the magic name __wakeup(). If present, this function can reconstruct any resources that the object may have.“ . __destruct() "The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.“ 16/12/2015 Practical PHP Object Injection PHP Object Injection 101 . Stefan Esser first presented in 2009 and 2010 . “Shocking News in PHP Exploitation” . “Utilizing Code Reuse/ROP in PHP Application Exploits” . Makes use of POP (Property-oriented Programming) chains . Similar to ROP; reuse existing code (POP gadgets) . Vulnerability introduced using unsafe deserialization methods on untrusted input: . unserialize(<user_input>) 16/12/2015 Practical PHP Object Injection PHP Object Injection - Examples . CVE-2012-0911: Tiki Wiki unserialize() PHP Code Execution . CVE-2012-5692: Invision IP.Board unserialize() PHP Code Execution . CVE-2014-1691: Horde Framework Unserialize PHP Code Execution . CVE-2014-8791: Tuleap PHP Unserialize Code Execution . CVE-2015-2171: Slim Framework PHP Object Injection . CVE-2015-7808: vBulletin 5 Unserialize Code Execution . MWR Labs: Laravel -> Cookie Forgery -> Decryption -> RCE 16/12/2015 Practical PHP Object Injection Magic Methods and POP Chains . POP = Property Oriented Programming . Name is from the fact that adversary controls all properties of an object that can be used during deserialization . Just like ROP, start with initial gadgets, which can then call other gadgets . In PHP Object Injection, the initial gadgets are magic methods such as __wakeup() or __destruct() . Useful POP chain methods: . Command Execution . File Access . exec() . file_put_contents() . passthru() . file_get_contents() . popen() . unlink() . system() 16/12/2015 Practical PHP Object Injection Simple Class POP Chain <?php class DemoPopChain{ private $data = “bar\n”; private $filename = ‘/tmp/foo’; public function __wakeup(){ $this->save($this->filename); } public function save($filename){ file_put_contents($filename, $this->data); } ?> 16/12/2015 Practical PHP Object Injection Simple Class POP Chain <?php __wakeup() magic method in the class DemoPopChain{ DemoPopChain class private $data = “bar\n”; private $filename = ‘/tmp/foo’; public function __wakeup(){ $this->save($this->filename); } public function save($filename){ file_put_contents($filename, $this->data); } ?> 16/12/2015 Practical PHP Object Injection Simple Class POP Chain <?php Calls DemoPopChain- class DemoPopChain{ >save() method, with the filename private $data = “bar\n”; property private $filename = ‘/tmp/foo’; public function __wakeup(){ $this->save($this->filename); } public function save($filename){ file_put_contents($filename, $this->data); } ?> 16/12/2015 Practical PHP Object Injection Simple Class POP Chain <?php DemoPopChain- >save() method class DemoPopChain{ writes contents