前言

免责声明:本文只用作技术分析和学习,任何利用本文内容进行非法攻击的行为均与作者无关!

漏洞简介

青龙面板最新版本存在一个 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 就能成功修改密码,至于进入后台了想干什么随便干了。

参考