深入解析理解session原理并由此反观SOAP的安全问题

深入解析理解session原理并由此反观SOAP的安全问题

前言:

今早无事,翻看了个学校web学长的博客,看到里面讲到了php的基础知识,就当复习看了看;其中简略提到了session;但是还多多少少有些残缺的点,在这里我深入解析理解一下,并由此反观SOAP的安全问题;发个博文;session了解的透彻的师傅可以直接去看SOAP的安全问题;

分析:

问题一:什么是session

session,简单的来说就是我们用浏览器和服务器的交互对话,额。至于什么是对话,师傅们可以自行脑补,这个不过多赘述;另外,我们也了解可以将一个变量存入全局的$_SESSION['name']中,这样php就可以在各各页面或者逻辑都可以访问的到;这也可以判断是否登陆;当我们用浏览器去访问一个页面的时候,了解计网的师傅都知道,采用的是http协议;这个协议有个明显的特性,它是无状态的;所谓的无状态就是指代我们这一次请求和下一次请求之间是没有任何的联系的;是两个独立的请求;这种的优点就是快速;

但是我们深入想想,这样的话,也就会有很多问题,比如,我在www.s1mple.com/login.php这个页面下登陆了,然后我去到这个域名下的其他的页面,如果是无相关的请求,那么其他页面又如何识别我确实登陆了呢;是去到数据库查询么?如果是这样,那么数据库一定很快就崩溃,所以这里我们也就是想让几个请求的页面相互的关联;

也是因为这个原因,一个新的客户端存储数据的方式就出现了;cookie诞生了;cookie就是将少量的信息存储在我们本地的电脑上,它在一个域名之下是全局的;只要设置了存储路径在www.s1mple.com之下,那么当浏览器去访问这个域名之下的任意页面时;浏览器都会带上我们本地的cookie;php也就可以读取到我们的cookie;以此来判定我们是否登陆或者是否已经进行了其他的预备工作;这样也就方便多了,我们就可以避免了上述的很多问题;但是这里有个新的问题出现;

打过ctf的同志们都知道;有很多ctf的入门题;都是涉及了cookie的伪造;有'0'到‘1’的,还有经过jwt加密的;也有存储钱数或者其他的信息的;甚至有的考点很简单直接flag的base64放到cookie里;知道了这些;我们应该深刻的意识到一个问题;我们本地的cookie是不安全的;我们可以随意的修改伪造;那么我们如何才能保证我们可以畅通并且安全的浏览网页呢;这时候一个全新的存储数据session就出现了;它位于服务器端,这样的话我们就可以保证了安全性和流畅性了;

问题二:session的工作机制和存储的方式是如何的

就这个问题,我们需要打开服务器来试验一下;打开我的vps;在fuck.php中写入如下的代码;

YRzmp4.png

这里我们访问该页面,得到如下的回显;

YRz96s.png

YRzZhF.png

通过对比我们发现,这里系统输出了这次生成的session_id,但是没有输出cookie的值;当我们再次刷新的时候,cookie的值才会出现,但是我们发现第一次虽然没有输出cookie的值,但是我们本地是存在的;我们看到的数据是基于服务器上面的,这里也是说明了第一次访问的时候我们服务器生成session_id然后给我们本地返回一个cookie;第二次我们访问的时候,服务器会去读取这个本地的cookie看看是否过期,如果没有过期,那么就接着使用;这个session_id只是在我们访问的时候有效;

YRzuc9.png

当我们关闭浏览器再次打开这个网页的时候;发现了新的值;(这里缺图了。后来才发现。hhhh)

搞清楚了工作机制,我们就来看看session的存储方式是如何的;我们打开php.ini中定义session的模块,然后发现临时存储的路径,我们去到相关的目录之下,发现了临时文件的存储方式;如下:

YRzt9e.png

YRzQn1.png

看到这些个文件,存储的方式是 sess_+session_id的方式;所以每次访问服务器,服务器都会生成这么个文件;现在我们就来看看里面存储内容的格式是怎么样的;这里我们看到存储的方式;

YRzF00.png

不难发现这里是序列化数据,玩过php构造pop链进行攻击的师傅,不难发现这里的 i 的含义指的就是int型;也就是说我们向$_SESSION这个全局变量中写入数据的时候;服务器也会向相应的临时文件里存储数据;

问题三:session的相关配置

我们看看php.ini中对session的配置;

YRzn1J.png

我把这些个配置项选取几个列出来;

session.save_handler = files

session.save_path = "/var/lib/php/sessions"

session.use_cookies = 1

session.name = PHPSESSID

session.auto_start = 0

现在来分别解释上面的配置;session.save_handler = files;这个配置项默认了是以file形式进行存储;然后session.save_path = "/var/lib/php/sessions"很自然之前在前面也是利用了这个配置项才找到了我们的临时文件,这个配置项就是配置临时文件存储的位置;这两个都是可以自定义的;session.use_cookies = 1session是否使用cookie的功能(预设为1,启动),session基于cookie使用;session.name = PHPSESSID这个配置是配置session的名字;你可以改为任意的;比如PHPS1MPLE,那么下一次生成的就是名字为PHPS1MPLE的session_id;session.auto_start = 0这个配置是是否开启session,可以看到默认是0为不开启,所以我们刚刚的代码要一个session_start方法的原因;

php中session的相关的知识在此就先讲到这里;有兴趣的师傅可以去再次了解了解;下面来讲SAOP的安全问题;

saopclient是php中的一个内置类;这个类比较特殊,它具有SSRF的功能;自然和我们的session分不开;下面就先解释一下SOAP:

SOAP(简单对象访问协议)是连接或Web服务或客户端和Web服务之间的接口。其采用HTTP作为底层通讯协议,XML作为数据传送的格式,SOAP消息基本上是从发送端到接收端的单向传输,但它们常常结合起来执行类似于请求 / 应答的模式。

下面来看看题目的源码:

YRzJhD.png

看到源码之后,进行简单的审计,发现这里的implode其实并没有什么用处,它只是将字符串做一个拼接;对于我们这里的题目来说是没用用处的;所以自然就想到了利用回调函数传入f为extract将b的值进行覆盖;想法是好的,现在就是来看看后面的session的利用了;

补充知识点

这里先来解释一下这个回调函数;如果回调函数传入的参数是数组的话,那么回调函数就会将这个数组里面的成员作为类和方法;懂得了这一点特性,后面就好来了;还有一点需要注意的是:我们如果使用session_start方法开启了session之后我们可以自定义其配置文件;具体的如下图文档所示;

YRzEkT.png

还有一点需要注意;我们在之前的session中也讲过也发现过我们传入的数据的存储方式是序列化,这里要说明一下;服务器中对于session的序列化是有序列化引擎的,不同引擎的存储方式也不同;有三种:

php_binary:存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值

php:存储方式是,键名+竖线+经过serialize()函数序列处理的值

php_serialize(php>5.5.4):存储方式是,经过serialize()函数序列化处理的值

这里特别解释一下php和php_serialize引擎,这里php_serialize引擎和我们平常的php序列化效果一样,这里着重说明一下php引擎,也就是之前让大家看的一张图,里面的存储形式为 name|i:3:xxxxxx这种方式,那么这里如果将两种引擎交错使用会不会有问题呢,答案肯定是有的;这里php引擎在反序列化的时候会将|当作分隔符;也就是简单来说|前面的都会被看作键名,|后面的会被看做键值;就拿name|s:6:"s1mple"这个例子来讲是我们php引擎序列化得到的;如果我们传入|s1mple呢,经过php_serialize引擎序列化之后a:1:{s:4:"name";s:7:"|s1mple";}这个序列化如果经过php引擎来进行反序列化的时候,就会出现问题;就会把a:1:{s:4:"name";s:7:"这个当作键名,s1mple当作键值;然后将结果存储在$_SESSION的全局变量中;这就出现了问题;这里文档说明是会默认反序列化的:我们的根本想法还是利用引擎的差异来造成session注入;

YRz8AK.png

另外想要解题还需要有csrl漏洞的知识,这里就是利用\r\n进行控制http的包;深层次的内容师傅们可以自行查阅相关文档;

思路

有了上面的知识点,我们可以想到,先来session_start开启session服务,然后传入|xxxx数据使其存储在sess_sessionid中;然后用extract函数将b覆盖为call_user_func方法;然后看到下面代码为session设置;这里可以将name设为soapclient方法,然后最后的那个式子就变成了call_user_func(array('soapclient','welcomexxxxxxxxx'))就会成数组样式,这里服务器就会去sopaclient这个类里面去找welcomxxxxxx这个方法,发现没有这个方法,所以就会调用soapclient类中的__call方法;从而发出请求;(简单来说这个类的call方法被触发以后就会发送http和https请求;)

YRzVtU.png

这里我们看到已经成功写入了;现在服务器默认调用php引擎反序列化写入全局变量;

YRzCXn.png

可以看到已经调用了写入了;然后我们以session身份访问就可以攻击成功过;可以看到利用成功;

YRzplj.png

猜你喜欢

转载自www.cnblogs.com/Wanghaoran-s1mple/p/12907912.html