*严正声明:本文仅限于技术讨论与分享,严禁用于非法途径
0×00 背景
10月9号国内几家安全媒体公布了Joomla RCE的漏洞预警,并且网上已公布漏洞利用EXP,影响版本包括Joomla 3.0.0 – 3.4.6。
0×01 环境搭建
Joomla是一套全球知名的内容管理系统。Joomla是使用PHP语言加上MySQL数据库所开发的软件系统,目前最新版本是3.9.11 。可以在Linux、Windows、MacOSX等各种不同的平台上执行。
Joomla环境搭建下载:https://github.com/joomla/joomla-cms/releases/tag/3.4.6
PS:搭建环境要求php 5.3.10以上
0×02 漏洞分析
Session会话机制
PHP本身对Session的存储默认放在文件中,当有会话产生使用到Session时候,将会在网站服务端设置好的路径写入相应的Session文件,文件的内容为默认序列化处理器序列化后的数据。然而在Joomla中则改变了PHP的默认处理规则,相反将序列化之后的数据存放在数据库的” hzlnp_session”表中存储:
将序列化之后的数据存放在数据库中所对应的处理函数为由session_set_save_handler()设置的librariesjoomlasessionstoragedatabase.php 中的write():
相应的取值函数read()也位于librariesjoomlasessionstoragedatabase.php中
接着从代码中可以看出,在存入数据库之前,会将传入数据中的chr(0) . ‘*’ .chr(0) 替换为 , 原因是mysql数据库无法处理NULL字节,而protected 修饰符修饰的字段在序列化之后是以x00x2ax00开头的。然后从数据库中取出来的时候,再将字符进行替换还原,防止无法正常反序列化。
Session会话逃逸
session 在 Joomla 中的处理存在一些问题,它会把没有通过验证的用户名和密码存储在hzlnp_session表中
当用户在登陆过程中,会有一个 303 的跳转,主要是用于write()数据库写入用户会话然后read()相应取出会话进行对比,显示结果
通过分析Session会话机制和Session逃逸我们还不明确Session形成的漏洞到底在哪!
首先需要了解一下PHP的序列化的机制,PHP在序列化数据的过程中,如果序列化的字段是一个字符串,那么将会保留该字符串的长度,然后将长度写入到序列化之后的数据,反序列化的时候按照长度进行读取。
知道PHP序列化过程之后,针对Joomla的内置序列化方法write和read函数,如果写入数据库的时候,是 , 取出来的时候将会变成chr(0) . ‘*’ . chr(0),这样的话,入库的时候生成的序列化数据长度为6( ), 取出来的时候将会成为3(N*N, N表示NULL),依据PHP反序列化原理,该数据在反序列化的时候,如果按照原先的长度进行读取,就会导致溢出。
那么由” ”溢出会造成什么问题呢?按照PHP反序列化的特点,PHP按照长度读取指定字段的值,读取完成以分号结束,接着开始下一个,如果我们能够控制两个字段的值,第一个用来溢出第一个字段和第二个字段的前一部分,第二个字段的另一部分用来构造序列化利用的payload,最终序列化结果将会把第一个字段开始部分到第二个字段的前一部分当成第一个字段的全部内容,第二个字段内容成功逃逸出来并且被反序列化。
为了触发我们的任意对象并实现RCE,我们需要将登录框处的两个字段username和password进行处理,第一个字段将导致“溢出”,第二个字段将包含漏洞利用的最后一部分。
漏洞利用大概思路
编写本地测试代码
此处伪代码对Joomla内置的write()、read()函数进行模拟,username字段通过9组”