作者 akihi(白帽攻防录讲师),某甲方网络安全工程师,合集 SRC 年度第一、腾讯 SRC 连续三年前十,单漏洞赏金 4w+,擅长 Web/App/PC 客户端漏洞挖掘。专注 SQL 注入、Web 安全、邮件系统安全审计。本文基于公开 CVE 信息与技术原理深度复盘,供安全研究与防护参考。
一、漏洞时间线
2026 年 5 月,Roundcube 发布安全补丁修复了一个预认证 SQL 注入漏洞 CVE-2026-48842。但直到 9 月,安全厂商才确认这个漏洞正在被活跃利用。补丁发布了 4 个月,大量企业仍未修复。
| 时间 | 事件 | 影响版本 |
|---|---|---|
| 2026-05-24 | Roundcube 发布补丁(1.6.16 / 1.7.1) | 1.6.x / 1.7.x |
| 2026-05-25 | 漏洞公开披露 | ------ |
| 2026-09-21 | 安全厂商确认在野利用 | ------ |
| 2026-09-24 | 多家媒体报道预警 | ------ |
| 2026-09-25 | 安全研究人员发布技术分析 | ------ |
这个漏洞的 CVSS 评分为 8.1(High),攻击复杂度为 HIGH,但因为是预认证且无需用户交互,实际被利用的门槛并不高。
二、攻击链全景
让我们先用一张流程图还原完整的攻击路径:
攻击者发现暴露在公网的 Roundcube Webmail
│
▼
第一步:分析登录流程
│ Roundcube 使用 virtuser_query 插件
│ 插件通过数据库查询验证用户邮箱
│ 输入参数:用户输入的邮箱地址
▼
第二步:构造恶意输入
│ 在邮箱地址中插入 SQL 注入 payload
│ 利用 preg_replace 反斜杠转义绕过
│ 让转义后的输入仍然包含恶意 SQL
▼
第三步:发送登录请求
│ POST /roundcube/?_task=login
│ 邮箱字段填入恶意 payload
│ 不需要密码正确,SQL 注入在验证前执行
▼
第四步:virtuser_query 插件处理输入
│ 插件使用 preg_replace 处理输入
│ 反斜杠转义被绕过
│ 恶意 SQL 进入查询语句
▼
第五步:数据库执行恶意 SQL
│ 攻击者可以查询任意数据
│ 读取用户邮箱地址和密码哈希
│ 甚至写入数据或执行命令
▼
攻击者获得 Roundcube 数据库访问权
│
├─ 读取所有用户的邮箱地址
├─ 窃取密码哈希并破解
├─ 登录用户邮箱读取邮件
└─ 利用邮件中的敏感信息进一步渗透
**关键结论:**这个漏洞的可怕之处在于"预认证"------SQL 注入发生在用户认证之前,攻击者不需要任何账号密码。只需要发送一个精心构造的登录请求,就能在数据库中执行任意 SQL。邮件系统通常存储了企业最敏感的信息,一旦被攻破,后果不堪设想。
三、SQL 注入原理
3.1 什么是 SQL 注入
SQL 注入是一种代码注入技术,攻击者可以将恶意 SQL 语句插入到应用程序的数据库查询中:
// 有缺陷的代码
$email = $_POST['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";
$result = mysqli_query($conn, $sql);
// 如果用户输入:admin@example.com' OR '1'='1
// 最终查询变成:
// SELECT * FROM users WHERE email = 'admin@example.com' OR '1'='1'
// 这会返回所有用户!
3.2 防御 SQL 注入的方法
| 方法 | 描述 | 安全性 |
|---|---|---|
| 预处理语句(Prepared Statement) | 参数化查询,SQL 和数据分离 | 最安全 |
| 转义特殊字符 | 用反斜杠转义引号等特殊字符 | 较安全,但容易绕过 |
| 输入验证 | 白名单验证输入格式 | 辅助手段 |
| ORM 框架 | 对象关系映射,自动转义 | 较安全 |
3.3 virtuser_query 插件
virtuser_query 是 Roundcube 的一个插件,用于:
- 通过数据库查询验证用户邮箱
- 将邮箱地址映射到本地用户名
- 支持虚拟域(多个域名共用一个数据库)
- 很多邮件服务商使用这个插件
四、漏洞深度分析
4.1 漏洞根因
根据 NVD 和安全分析,漏洞的根本原因是 preg_replace() 函数的反斜杠转义绕过:
// 有缺陷的代码(伪代码)
function virtuser_query($email) {
// 先转义特殊字符
$email = mysqli_real_escape_string($conn, $email);
// 然后使用 preg_replace 处理
// 问题:preg_replace 的 e 替换模式会处理反斜杠
$email = preg_replace(
'/\/', // 匹配反斜杠
'\\', // 替换为两个反斜杠
$email
);
// 构造 SQL 查询
$sql = "SELECT * FROM users WHERE email = '$email'";
// 问题:经过 preg_replace 后,
// 原本转义好的引号又被"还原"了
// 导致 SQL 注入
}
// 攻击过程:
// 1. 用户输入:admin@example.com'
// 2. mysqli_real_escape_string 转义:
// admin@example.com'
// 3. preg_replace 处理反斜杠:
// admin@example.com\'
// 4. 但在 SQL 字符串中:
// 表示一个字面的反斜杠
// 而 ' 变成了未转义的引号!
// 5. SQL 注入成功
4.2 preg_replace 为什么会出问题
preg_replace() 是 PHP 的正则表达式替换函数。问题出在替换字符串中的反斜杠处理:
// preg_replace 的替换模式
// 在替换字符串中,反斜杠有特殊含义
// 表示一个字面的反斜杠
// 表示第一个捕获组
// 漏洞场景:
// 原始输入:admin@example.com'
// (' 表示转义后的单引号)
// preg_replace('/\/', '\\', $input)
// 这个函数想把每个反斜杠变成两个
// 但实际上:
// 输入中的 ' 会被处理成什么?
// 关键:preg_replace 的替换字符串中
// 反斜杠的解析是两层的
// 一层是 PHP 字符串解析
// 一层是 preg_replace 自身的解析
// 这就导致了:
// 原本转义好的反斜杠+引号
// 经过 preg_replace 后
// 反斜杠被"消耗"了
// 引号变成了未转义的
**安全原则:**在处理 SQL 注入防护时,不要在转义之后再做任何字符串处理。转义应该是最后一步,直接拼接到 SQL 查询中。任何在转义之后对字符串的修改,都可能意外地"撤销"转义效果。这就像锁门之后又去转动门把手------可能会把锁打开。
4.3 攻击利用
攻击者利用这个漏洞的步骤:
// 攻击前提:
// 1. Roundcube 使用了 virtuser_query 插件
// 2. 插件已启用并配置为验证用户
// 3. Roundcube 暴露在可访问的网络上
// 攻击 payload 示例:
// 在登录页邮箱输入框中输入:
// admin@example.com' UNION SELECT 1,version(),3,4--
// 处理过程:
// 1. mysqli_real_escape_string 转义
// admin@example.com\' UNION SELECT...
// 2. preg_replace 处理反斜杠
// admin@example.com\' UNION SELECT...
// 3. 进入 SQL 查询后
// 反斜杠被"消耗"
// UNION 注入成功
// 攻击效果:
// - 读取数据库中的所有用户邮箱
// - 读取密码哈希
// - 可能写入管理员账户
// - 可能通过 SQL 注入执行系统命令
4.4 影响范围
| 产品 | 影响版本 | 影响程度 |
|---|---|---|
| Roundcube Webmail | 1.6.x 早于 1.6.16 | 预认证 SQL 注入 |
| Roundcube Webmail | 1.7.x 早于 1.7.1 | 预认证 SQL 注入 |
| virtuser_query 插件 | 内置插件 | ------ |
| 修复版本 | 1.6.16 / 1.7.1 | ------ |

五、修复方案分析
Roundcube 在 2026 年 5 月 24 日发布了补丁:
| 修复项 | 修复方式 |
|---|---|
| 转义顺序 | 将转义操作移到最后一步 |
| preg_replace | 不再在转义后使用 preg_replace 处理 |
| 参数化查询 | 改用预处理语句(Prepared Statement) |
| 输入验证 | 增加邮箱格式白名单验证 |
5.1 SQL 注入安全最佳实践
// SQL 注入安全检查清单
// 1. 使用预处理语句
// 永远优先使用参数化查询
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
// 2. 不要自己实现转义
// 使用数据库提供的转义函数
// 不要在转义后再做字符串处理
// 3. 白名单验证
// 邮箱格式验证
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new Exception('Invalid email');
}
// 4. 最小权限
// 数据库用户只授予必要的权限
// 不要使用 root/sa 用户
// 5. 错误处理
// 生产环境不显示详细错误信息
// 防止攻击者通过错误信息探测数据库结构
5.2 邮件系统安全
// 邮件系统安全加固
// 1. 及时更新
// 安装最新的 Roundcube 版本
// 2. 网络隔离
// 管理界面放在内网
// 只暴露必要的服务端口
// 3. 强密码策略
// 强制用户使用强密码
// 启用多因素认证
// 4. 日志监控
// 监控异常的登录尝试
// 监控异常的 SQL 错误
// 5. 数据备份
// 定期备份邮件数据
// 备份文件加密存储
六、SRC 审计启示录
6.1 SQL 注入审计清单
在 SRC 挖洞过程中,针对 SQL 注入的审计清单:
| # | 检查项 | 检测方法 |
|---|---|---|
| 1 | 是否使用参数化查询 | 测试各种注入 payload |
| 2 | 转义后是否还有字符串处理 | 测试转义绕过技巧 |
| 3 | 错误信息是否泄露数据库信息 | 触发错误观察返回 |
| 4 | 是否有预认证的注入点 | 测试登录前的所有接口 |
| 5 | 数据库用户权限是否过大 | 测试能否写文件或执行命令 |
6.2 常见转义绕过技巧
// 常见 SQL 转义绕过
// 1. 宽字节注入
// 使用 %bf%27 等宽字节字符
// 让转义的反斜杠被"吃掉"
// 2. 二次注入
// 第一次注入的数据被存储
// 第二次使用时转义被绕过
// 3. 字符集转换
// 利用不同字符集之间的转换
// 导致转义失效
// 4. 函数处理绕过
// 在转义后还有字符串函数处理
// 如 preg_replace、str_replace 等
// 5. 注释绕过
// 使用注释符"吃掉"转义的反斜杠
6.3 邮件系统安全
| 风险点 | 常见问题 | 防护建议 |
|---|---|---|
| Webmail 暴露 | 管理界面暴露在公网 | 网络隔离,VPN 访问 |
| 插件安全 | 第三方插件有漏洞 | 只安装必要的插件 |
| 密码策略 | 用户使用弱密码 | 强制强密码和 MFA |
| 数据泄露 | 邮件包含敏感信息 | 加密存储,访问审计 |
七、防护建议
- 及时升级:升级到 Roundcube 1.6.16 或 1.7.1
- 网络隔离:不要将 Webmail 管理界面暴露在公网
- 插件审计:禁用不需要的插件
- 强密码策略:启用多因素认证
- 监控告警:监控异常的登录尝试和 SQL 错误
- 定期备份:备份邮件数据并加密存储
八、总结
CVE-2026-48842 是一个典型的"安全措施被意外抵消"漏洞。它提醒我们:在实现安全防护时,不仅要考虑防护措施本身,还要考虑防护措施之后的所有代码路径。转义之后的任何字符串处理,都可能意外地破坏转义效果。在 SRC 挖洞实践中,"转义后还有处理"是一个高价值的审计点------不要只看有没有转义,还要看转义之后发生了什么。
