青龙面板最新版本鉴权绕过 RCE 分析
前言
免责声明:本文只用作技术分析和学习,任何利用本文内容进行非法攻击的行为均与作者无关!
漏洞简介
青龙面板最新版本存在一个 JWT 鉴权绕过漏洞,允许攻击者使用特定构造的 API 路径绕过鉴权,由于 /api/system/command-run 端点允许直接执行系统命令,这会导致 RCE(远程命令执行)。
影响版本:
分析
查看源码的 back/loaders/express.ts 文件第 34~41 行:
app.use(
expressjwt({
secret: config.jwt.secret,
algorithms: ['HS384'],
}).unless({
path: [...config.apiWhiteList, /^\/(?!api\/).*/],
}),
);这里的 path 使用严格匹配了纯小写的 /api,即攻击者使用 /API 或者 /aPi 均可绕过 JWT 鉴权验证。
查看同一文件的 51-56 行:
if (!['/open/', '/api/'].some((x) => req.path.startsWith(x))) {
return next();
}这里写的鉴权中间件使用的是 req.path.startsWith 严格判断纯小写,并直接返回 next() 放行。
另外文件里还有一个 URL 重写漏洞:
app.use(async (req: Request, res, next) => {
if (!['/open/', '/api/'].some((x) => req.path.startsWith(x))) {
return next();
}
// ...
}
app.use(rewrite('/open/*', '/api/$1'));
app.use(config.api.prefix, routes());这里将 /open/* 重写到 /api,意味着使用 PUT /open/user/init 就能成功修改密码,至于进入后台了想干什么随便干了。
参考
- Github Issues: 0day 青龙面板 最新版本 鉴权绕过导致 RCE #2934
back/loaders/express.ts: back/loaders/express.ts @ dc0b3f2eb29ee70311bba8e0c75bedf214acaccd