该漏洞利用链由两个漏洞组成:Strapi 远程代码执行漏洞(CVE-2023-22621)和Strapi 信息泄露漏洞(CVE-2023-22894)
Strapi 远程代码执行漏洞(CVE-2023-22621)为后台SSTI模板注入,在Strapi管理面板的Users & Permissions plugin可以设置确认邮件模板,在模板处存在模板注入,当开启邮件确认选项时将渲染该模板,触发漏洞,利用该漏洞需要后台管理员权限,以修改模板。
Strapi 信息泄露漏洞(CVE-2023-22894),Strapi 信息泄露漏洞(CVE-2023-22894)是由于Strapi在查询时,只是在查询结果中删除了敏感字段,在实际查询语句中仍然可以使用该敏感字段,所以攻击者可以通过观察Strapi服务端返回的数据,猜测所输入的敏感字段是否正确,即攻击者可以通过暴力破解,将敏感字段爆破出来
Strapi ≤ 4.5.5
参考
https://razinj.dev/how-to-run-strapi-4-in-a-docker-container-using-docker-compose/,使用npx create-strapi-app@4.5.5 app 命令启动strapi v4.5.5并且用docker起数据库。
docker-compose.yml:
version: '3'
services:
postgres:
image: postgres
restart: always
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: strapi
POSTGRES_PASSWORD: strapi
POSTGRES_DB: strapi
ports:
- '5432:5432'
mysql:
image: mysql:5
restart: always
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: strapi
MYSQL_USER: strapi
MYSQL_PASSWORD: strapi
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: strapi
volumes:
- mysqldata:/var/lib/mysql
ports:
- '3306:3306'
volumes:
pgdata:
mysqldata:
由于strapi监听在localhost,通过ssh把1337端口转发出来
ssh -CfNg -L 127.0.0.1:1337:127.0.0.1:1337 [root@192.168.59.197]
该漏洞利用链由两个漏洞组成,分别是Strapi 远程代码执行漏洞(CVE-2023-22621)和Strapi 信息泄露漏洞(CVE-2023-22894)。
Strapi 远程代码执行漏洞(CVE-2023-22621)是由服务端模板注入导致,在Strapi的管理面板的Users & Permissions plugin可以设置确认邮件模板,该模板由lodash 模板引擎渲染,代码如下
'use strict';
const _ = require('lodash');
const getProviderSettings = () => {
return strapi.config.get('plugin.email');
};
const send = async (options) => {
return strapi.plugin('email').provider.send(options);
};
/**
* fill subject, text and html using lodash template
* @param {object} emailOptions - to, from and replyto...
* @param {object} emailTemplate - object containing attributes to fill
* @param {object} data - data used to fill the template
* @returns {{ subject, text, subject }}
*/
const sendTemplatedEmail = (emailOptions = {}, emailTemplate = {}, data = {}) => {
const attributes = ['subject', 'text', 'html'];
const missingAttributes = _.difference(attributes, Object.keys(emailTemplate));
if (missingAttributes.length > 0) {
throw new Error(
`Following attributes are missing from your email template : ${missingAttributes.join(', ')}`
);
}
const templatedAttributes = attributes.reduce(
(compiled, attribute) =>
emailTemplate[attribute]
? Object.assign(compiled, { [attribute]: _.template(emailTemplate[attribute])(data) })
: compiled,
{}
);
return strapi.plugin('email').provider.send({ ...emailOptions, ...templatedAttributes });
};
module.exports = () => ({
getProviderSettings,
send,
sendTemplatedEmail,
});
该段代码获取模板及输入内容,调用_.template(emailTemplate[attribute])(data) })渲染内容, 在此之前,渲染内容由如下代码进行校验,以避免危险内容渲染:
'use strict';
const _ = require('lodash');
const invalidPatternsRegexes = [/<%[^=]([^<>%]*)%>/m, /\${([^{}]*)}/m];
const authorizedKeys = [
'URL',
'ADMIN_URL',
'SERVER_URL',
'CODE',
'USER',
'USER.email',
'USER.username',
'TOKEN',
];
const matchAll = (pattern, src) => {
const matches = [];
let match;
const regexPatternWithGlobal = RegExp(pattern, 'g');
// eslint-disable-next-line no-cond-assign
while ((match = regexPatternWithGlobal.exec(src))) {
const [, group] = match;
matches.push(_.trim(group));
}
return matches;
};
const isValidEmailTemplate = (template) => {
for (const reg of invalidPatternsRegexes) {
if (reg.test(template)) {
return false;
}
}
const matches = matchAll(/<%=([^<>%=]*)%>/, template);
for (const match of matches) {
if (!authorizedKeys.includes(match)) {
return false;
}
}
return true;
};
module.exports = {
isValidEmailTemplate,
};
该代码使用正则表达式检查邮件模板是否有非法内容,但由于正则表达式错误,导致攻击者可以使用排除列表的字符绕过检查,利用lodash的模板注入,向模板内注入恶意nodejs代码,当新注册用户时,Strapi将读取模板内容并渲染,从而导致代码执行。
Strapi 信息泄露漏洞(CVE-2023-22894)是由于Strapi在查询时,只是在查询结果中删除了敏感字段,在实际查询语句中仍然可以使用该敏感字段,所以攻击者可以通过观察Strapi服务端返回的数据,猜测所输入的敏感字段是否正确,即攻击者可以通过暴力破解,将敏感字段爆破出来,以上利用需要一定权限。当Strapi存在管理员创建的collection时,其关系字段会映射到管理员用户,如果该collection被配置为允许未授权用户访问,则未授权攻击者可以利用该collection访问Strapi管理员用户的密码哈希和重置密码token。

结合两个漏洞,攻击者可以利用Strapi 信息泄露漏洞(CVE-2023-22894)爆破得到管理员用户的邮箱,之后发送重置密码请求,在通过信息泄露获取到重置密码token,通过该token强制重置管理员密码并得到管理面板访问权限,之后利用Strapi 远程代码执行漏洞(CVE-2023-22621)向邮件模板里面注入恶意代码,在注册用户触发漏洞,执行恶意nodejs代码。

PoC
https://github.com/Chestnuts4/POC
参考链接
https://github.com/strapi/strapi/security/advisories/GHSA-2h87-4q2w-v4hf https://strapi.io/blog/security-disclosure-of-vulnerabilities-cve
Created at 2023-05-05T21:06:55+08:00