靶场配置
通过vulhub搭建靶场vulhub-master/metabase/CVE-2023-38646
docker-compose up -d启动靶场
漏洞原理
本次漏洞主要是由于 metabase 中数据库连接中出现的安全风险漏洞,在整个产品可通过metabase 安装时配置数据源数据库以及在安装之后在系统管理中配置数据库信息。所以整体的漏洞点即可通过安装以及配置数据源开始。
在产品安装时会调用 /api/setup/validate 来对参数校验,其中最为核心的部分对数据库的连接信息校验。

metabase\api\setup.clj#L184
从函数调用的逻辑来看,/api/setup/validate 会通过 api.database/test-database-connection 来处理输入的参数完成对数据库的校验。但本身 api.database/test-database-connection 其实就是 POST /api/database 路由的核心处理参数。

metabase\api\database.clj#L668
从整体的逻辑来看,该漏洞可通过 setup、database 两种方式来完成对漏洞验证,不同的是 setup 方式在安装时是不需要权限的,database 需要管理员权限。
setup 在安装时会校验 setup-token 参数是否正确,来判断是否要进行下步的数据库连接。

metabase\api\setup.clj#L45-L48
而 setup-token 在进行生成的时候被默认设置为了 public 权限,所以可以通过 /api/session/properties 来读取。

metabase\api\session.clj#L279-L281

metabase\setup.clj#L13-L17
我们可以通过 setup + setup-token 来完整的漏洞利用。在利用时主要依靠于数据库的类型,目前 metabase 支持多种数据库,本次我们重点说明 H2 数据库的深入利用,目前最为常用利用方式是 RUNscript 、TRIGGER 来完成对漏洞的利用。
以下使用TRIGGER方式
H2 在解析 init 参数时对 CREATE TRIGGER 会由 loadFromSource 做特殊处理,根据执行内容的开头来判断是否为需要通过 javascript 引擎执行。如果以 //javascript 开头就会通过 javascript 引擎进行编译然后进行执行。

我们就可以通过 javascript 引擎来实现代码执行,不过该方式在 JDK 15 之后移除了默认的解析,但是有意思的是 metabase 在项目中使用到了 js 引擎技术。

最后我们即可构建 javascript 引擎来构建代码执行,如:
1 | java.lang.Runtime.getRuntime().exec('touch /tmp/success') |

整体利用流程为:
**获取
setup-token**:首先攻击者需要通过访问/api/session/properties接口来获取Metabase的setup-token,这是利用漏洞的先决条件。数据库连接信息校验:在校验数据库连接信息时,
/api/setup/validate接口会通过api.database/test-database-connection进行处理,但实际上这是POST /api/database路由的核心处理参数。利用
setup接口:攻击者可以利用setup接口在安装时不需要权限的特点,通过setup-token来进行下一步的数据库连接。创建TRIGGER:利用H2数据库的特性,攻击者可以通过
CREATE TRIGGER触发器,在init参数中插入恶意的JavaScript代码。H2数据库在解析init参数时,会根据内容开头判断是否需要通过JavaScript引擎执行,如果以//javascript开头,则会通过JavaScript引擎编译并执行。代码执行:通过JavaScript引擎,攻击者可以执行任意代码,例如在POC中执行的
touch /tmp/success命令,从而在Metabase容器中执行系统命令。权限获取:如果攻击者通过
setup方式进行攻击,可以在安装时不需要管理员权限。但如果通过database方式,则需要管理员权限来配置数据库信息。漏洞利用:整体利用流程依赖于数据库类型,但关键在于利用H2数据库的
TRIGGER特性来执行恶意代码。
综上所述,CVE-2023-38646的漏洞利用链主要涉及未授权的数据库连接校验和H2数据库的特定执行特性,攻击者可以利用这一链条执行任意代码。
漏洞复现
首先,我们需要先访问/api/session/properties来获取Metabase的setup-token:
1 | GET /api/session/properties HTTP/1.1 |
要利用漏洞,必须要获取这个Token。
接着,将刚才获取的[setup-token]替换进下面这个请求后发送:
1 | POST /api/setup/validate HTTP/1.1 |
touch /tmp/success已成功在Metabase容器中执行
poc
python cve-2023-38646.py --protocol http --host 192.168.159.131 --port 3000 --cmd "touch /tmp/success"

在/tmp下成功创建success

参考
漏洞分析|Metabase 远程代码执行(CVE-2023-38646): H2 JDBC 深入利用 - FreeBuf网络安全行业门户
vulhub/metabase/CVE-2023-38646/README.zh-cn.md at master · vulhub/vulhub (github.com)