Skip to content

CIFSwitch(cifs.spnego 身份混淆与 root NSS 加载)防御 ​

防御目标 ​

阻断非特权用户通过 request_key("cifs.spnego", ...) 伪造 pid=<attacker_pid>;upcall_target=app;user=root 描述串,诱导 root 权限的 cifs.upcall 切换至攻击者控制的用户/挂载命名空间(User/Mount Namespace)并加载伪造 /etc/nsswitch.conf 与 libnss_*.so.2 写入 /etc/sudoers.d/ 的提权链(QVD-2026-29453)。

分层防御矩阵 ​

攻击链环节阻断机制具体配置 / 补丁措施影响评估
非特权 User/Mount Namespace 构造限制非特权 usernsDebian/Ubuntu 设置 kernel.unprivileged_userns_clone=0 或 kernel.apparmor_restrict_unprivileged_userns=1;RHEL/CentOS 设置 user.max_user_namespaces=0直接切断伪造 /etc/nsswitch.conf 挂载面
request_key("cifs.spnego", ...) 触发收敛 /etc/request-key.d/cifs.spnego.conf未使用 Kerberos/CIFS 挂载的主机移除或注释 cifs.spnego 与 cifs.idmap 规则,或限制 request_key 系统调用非特权用户无法唤醒 /sbin/request-key 调用 cifs.upcall
内核缺少 vet_description 校验内核补丁 + cifs-utils 更新为 cifs_spnego_key_type 合入 .vet_description 来源/格式校验补丁;升级 cifs-utils 禁用不安全 upcall_target=app 切入不受信任 NS从根因拒绝伪造 description 与跨 NS 加载
root 权限下加载恶意 NSSLSM(SELinux / AppArmor)+ 完整性校验为 cifs.upcall 配置强制访问控制策略,禁止其执行 setns() 进入非全局命名空间或写入 /etc/sudoers.d/即使触发 upcall 也无法加载不可信共享库

防御实现与校验示例 ​

1. 命名空间收敛 sysctl 配置 ​

ini
# /etc/sysctl.d/99-userns-hardening.conf
# RHEL / CentOS / Rocky / AlmaLinux:
user.max_user_namespaces = 0
# Ubuntu 24.04+ (若需保留桌面/容器兼容性,启用 AppArmor 限制):
# kernel.apparmor_restrict_unprivileged_userns = 1

2. 主机 request-key 与命名空间暴露面检测脚本(Python) ​

检查 /etc/request-key.conf 与 /etc/request-key.d/*.conf 是否暴露活跃的 cifs.spnego 规则,并核对 userns 策略:

python
from pathlib import Path
import re

def check_cifs_spnego_exposure(request_key_files: list[str], max_user_ns: int, apparmor_restrict_ns: int) -> dict:
    active_rules = []
    for content in request_key_files:
        for line in content.splitlines():
            s = line.strip()
            if not s or s.startswith("#"):
                continue
            if re.search(r"\bcifs\.spnego\b", s) and "cifs.upcall" in s:
                active_rules.append(s)

    ns_restricted = (max_user_ns == 0) or (apparmor_restrict_ns == 1)
    vulnerable_surface = bool(active_rules) and not ns_restricted
    return {
        "active_cifs_spnego_rules": active_rules,
        "userns_restricted": ns_restricted,
        "exposed": vulnerable_surface,
    }

if __name__ == "__main__":
    sample_conf = "create  cifs.spnego    * * /usr/sbin/cifs.upcall %k\n"
    res_exposed = check_cifs_spnego_exposure([sample_conf], max_user_ns=1000, apparmor_restrict_ns=0)
    assert res_exposed["exposed"] is True
    res_hardened = check_cifs_spnego_exposure([sample_conf], max_user_ns=0, apparmor_restrict_ns=0)
    assert res_hardened["exposed"] is False
    print("cifswitch_defense_check: PASS")

防御工作流 ​

text
1. 规则排查:检查 /etc/request-key.conf 与 /etc/request-key.d/ 是否启用 cifs.spnego -> cifs.upcall
2. 业务裁减:对不需要 SMB/CIFS Kerberos 挂载的服务器,卸载 cifs-utils 或禁用 cifs.spnego.conf 规则
3. 命名空间收敛:配置 user.max_user_namespaces=0 或启用 kernel.apparmor_restrict_unprivileged_userns=1
4. 软件升级:同步更新内核(cifs_spnego vet_description 修复)与 cifs-utils 安全版本
5. 文件监控:使用 auditd 监控 /etc/sudoers.d/ 新增文件事件与异常 /usr/sbin/cifs.upcall 进程启动

验证与判定标准 ​

  • Request-Key 阻断:在禁用规则或补丁生效后,非特权进程执行 request_key("cifs.spnego", ...) 返回 ENOKEY 或 EACCES,不触发 cifs.upcall
  • Namespace 拦截:非特权用户执行 unshare -U -m 返回 EPERM 或受 AppArmor 策略约束无法绑定伪造 /etc/nsswitch.conf
  • 文件完整性:/etc/sudoers.d/ 与 /etc/nsswitch.conf 无非运维变更记录

MCP 工具映射 ​

防御环节MCP 工具用途
关联提权链路检索kb_router检索命名空间与 SUID/NSS 加固方案
加固配置文件落盘workspace_write_text输出 sysctl 与 auditd 监控规则模板
持久化落地检测规则make_sigma_stub生成监控 /etc/sudoers.d/ 异常写入与 cifs.upcall 异常父进程的检测规则

Apache-2.0 · 仅供授权环境下的学习与防御性研究使用 · 免责声明