理解pam_pkcs11 认证绕过漏洞 (CVE-2025-24531)

286 阅读4分钟

漏洞名称: pam_pkcs11 认证绕过漏洞 (CVE-2025-24531)

影响版本: pam_pkcs11 0.6.12

修复版本: pam_pkcs11 0.6.13

漏洞描述: 在特定错误情况下,pam_pkcs11 0.6.12 版本中的 pam_sm_authenticate() 函数会返回 PAM_IGNORE,导致认证流程被跳过,从而可能绕过系统登录验证。简单来说,就是当 pam_pkcs11 验证智能卡(例如 YubiKey)出现问题时,没有正确地阻止用户登录,反而让用户直接进入系统。

技术细节

PAM (Pluggable Authentication Modules) 是一种 Linux 系统上用于身份验证的框架。pam_pkcs11 是一个 PAM 模块,用于通过智能卡进行身份验证.

  • PAM_IGNORE 的问题:

    • PAM_IGNORE 的含义:告诉 PAM 框架,这个模块不参与最终的认证结果判断,继续执行下一个模块。
    • 错误使用 PAM_IGNORE:在 0.6.12 版本中,当 pam_pkcs11 验证失败时,错误地返回了 PAM_IGNORE。这意味着即使智能卡验证失败,PAM 框架仍然认为验证过程可以继续,导致认证绕过。
  • 漏洞触发条件:

    • GDM (GNOME Display Manager) 将 YubiKey 识别为智能卡。
    • 系统配置了 gdm-smartcard PAM 堆栈,并且该堆栈中 pam_pkcs11 是唯一的身份验证模块。
    • pam_pkcs11 模块在初始化加密环境时失败(例如,无法读取智能卡)。
  • 根本原因: pam_sm_authenticate() 函数中的代码逻辑错误地使用了 PAM_IGNORE。在特定条件下,即使智能卡验证失败,该函数仍然返回 PAM_IGNORE,导致 PAM 框架跳过智能卡验证,允许用户无需凭据即可登录。

    if (!configuration->card_only || !login_token_name) {
        /* Allow to pass to the next module if the auth isn't
           restricted to card only. */
        pkcs11_pam_fail = PAM_IGNORE;
    } else {
      pkcs11_pam_fail = PAM_CRED_INSUFFICIENT;
    }
    

实际应用场景和代码示例

场景: 某公司使用 YubiKey 作为员工登录 Linux 系统的身份验证方式。攻击者通过以下步骤绕过身份验证:

  1. 在装有 pam_pcks11 0.6.12 的 Linux 系统上,插入一个无效的智能卡或 YubiKey。
  2. 输入用户名。
  3. 由于 pam_pkcs11 无法正确初始化加密环境,返回 PAM_IGNORE
  4. PAM 框架跳过智能卡验证,允许攻击者无需密码或智能卡即可登录系统。

模拟代码(仅用于演示目的,不可直接运行):

以下代码片段演示了 pam_sm_authenticate() 函数中导致漏洞的关键逻辑。

// 假设的 pam_sm_authenticate 函数
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
  // ...
  // 模拟智能卡初始化失败
  bool crypto_init_failed = true;

  if (crypto_init_failed) {
    // 错误地返回 PAM_IGNORE
    return PAM_IGNORE;
  }

  // ...
  // 智能卡验证逻辑
  // ...

  return PAM_AUTH_ERR; // 验证失败
}

漏洞利用的简化演示 (Python):

以下 Python 代码演示了如何通过模拟智能卡错误来触发漏洞。请注意,这只是一个概念验证,并不能直接用于攻击真实系统。

def simulate_smartcard_error():
    """模拟智能卡错误"""
    print("模拟智能卡初始化失败")
    return "PAM_IGNORE"  # 模拟 pam_pkcs11 返回 PAM_IGNORE

def pam_authentication():
    """模拟 PAM 认证流程"""
    result = simulate_smartcard_error()
    if result == "PAM_IGNORE":
        print("pam_pkcs11 返回 PAM_IGNORE,跳过智能卡认证")
        print("允许用户登录(存在漏洞)")
    else:
        print("智能卡认证失败,拒绝用户登录")

pam_authentication()

代码解释:

  1. simulate_smartcard_error() 函数模拟智能卡初始化失败,并返回字符串 "PAM_IGNORE"。
  2. pam_authentication() 函数模拟 PAM 认证流程。如果 simulate_smartcard_error() 返回 "PAM_IGNORE",则 PAM 框架会跳过智能卡认证,允许用户登录,这代表存在漏洞。

实际案例 在某公司内部红队演练中,红队成员利用该漏洞,在目标机器上插入一个格式错误的智能卡,成功绕过了双因素认证,获取了系统访问权限。

修复方案

  1. 升级 pam_pkcs11:升级到 0.6.13 或更高版本。该版本已将错误的 PAM_IGNORE 返回值改回 PAM_CRED_INSUFFICIENT

  2. 修改 PAM 堆栈配置:如果无法立即升级,可以使用以下 PAM 堆栈配置作为临时解决方案:

    auth [success=ok default=bad] pam_pkcs11.so wait_for_card card_only
    

    default=ignore 修改为 default=bad,确保任何非成功的智能卡验证都会导致认证失败。

经验教训

  1. 谨慎使用 PAM_IGNORE:在 PAM 模块开发中,应避免在不明确的错误情况下使用 PAM_IGNORE,因为这可能导致意外的认证绕过。
  2. 充分测试:对 PAM 模块进行充分的测试,特别是在涉及身份验证的关键路径上。
  3. 安全配置:系统管理员应仔细审查 PAM 堆栈配置,确保身份验证流程的安全性。