1. 权限提升到底在测什么先把权限模型吃透Linux权限提升Privilege Escalation这四个字很多人第一反应就是搞到 root但真在授权靶场或自有服务器自查里走一遍你会发现它考验的其实是你对 Linux 权限模型的理解深度。系统里能提权的口子本质上都是某个高权限主体做了一件它本不该做的事——要么是一个配置写错了的 SUID 程序要么是一条带通配符的计划任务要么是密码在配置文件里复用了。你要做的不是背命令而是顺着权限的流向找出这条越权通道。这份笔记我前后改过七八版从最早一张命令清单慢慢长成了现在按「信息收集、路径识别、验证利用、善后清理」四段走的完整流程。它适合三类人刚接触 Linux 安全、需要在授权环境下做提权练习的新手平时做运维、想给自己服务器做一轮权限自查的老手还有准备 CTF 或安全认证、需要一套可复用清单的选手。全文所有操作都默认你在授权环境自己搭的靶机、公司授权的测试网段、CTF 赛场里进行这一点我会在 1.3 节反复强调因为脱离授权谈提权性质就完全变了。1.1 用户、组与权限位提权的物理基础Linux 的权限体系是三层结构所有者owner、所属组group、其他人others每层对应读r数值 4、写w数值 2、执行x数值 1三个位。你看到的-rwxr-xr-x就是把这九个位按三层排开。这套模型的设计逻辑很朴素——谁的东西谁做主同组的人给点面子外人只能看看。真正让提权成为可能的是三个特殊权限位SUID4、SGID2、Sticky1。SUID 的含义是执行时临时借用文件所有者的身份比如/usr/bin/passwd这个文件本身是 root 所有普通用户执行它时会短暂获得 root 权限去改/etc/shadow。这个机制本来是为了让普通用户能改自己密码可一旦某个 SUID 程序存在逻辑缺陷或者能被转去执行别的命令它就成了提权的高速公路。SGID 对文件的作用类似只不过借的是所属组的身份对目录而言SGID 意味着目录里新建的文件会继承目录的组这在团队协作场景里很有用但配置不当也会让低权限用户读到不该读的东西。Sticky 位常见于/tmp则是只有文件所有者或 root 才能删除该文件它挡的是删除操作跟提权关系不大但排查时经常会被一起列出来。我建议你在理解这套模型时脑子里始终问一个问题这个文件是以谁的身份运行的只要答案不是当前用户就值得深挖一层。1.2 提权的三条主线内核层、配置层、凭据层我习惯把所有提权路径归成三类这样排查时思路不会乱。第一类是内核层也就是 Linux 内核或核心组件的漏洞。典型的是历史上那些有公开编号的本地提权漏洞思路都是通过某个系统调用或文件操作的边界处理错误让普通用户拿到高权限。这条路的特点是一击致命但门槛高——补丁一旦打上就失效而且不同内核版本的可利用性差别很大盲目尝试容易把系统搞崩。第二类是配置层这是实战里命中率最高的地方。SUID 程序配错了、sudo 规则给宽了、计划任务里用了通配符、服务脚本的路径可写、环境变量被继承——这些都属于系统本身没漏洞但管理员把权限开大了。配置层的问题往往能稳定复现也不依赖特定内核版本是自查的重点。第三类是凭据层说白了就是密码或密钥泄露了。数据库配置里明文写着 root 密码、.bash_history里留着mysql -uroot -pXXX、备份目录里躺着一份 shadow、某台机器的 SSH 私钥忘了删——这类问题不需要任何技术含量但危害往往最大因为它可能直接通往横向移动。三条主线里我通常的排查顺序是先扫凭据成本最低再查配置覆盖最广最后才考虑内核风险最高。1.3 授权边界这一步不能省必须把话说在前面。提权技术的使用有且只有一个前提你拥有对该系统的明确测试授权。自有服务器、公司书面授权的测试资产、CTF 靶场、本地虚拟机这些都没问题。凡是扫描别人家的站、朋友让我帮忙看看这类场景一律不要碰——未经授权的访问和权限提升在绝大多数地区都是明确的违法行为代价远大于那点技术收益。我自己在做任何测试前会确认三件事授权书或工单里写清楚了资产范围测试窗口和回滚方案已经和业务方对齐手边有快照或备份一旦系统被搞挂能立刻恢复。这三件事听起来啰嗦但真出过事的人都懂——提权操作里把机器跑挂的概率一点不比成功提权低。工程师的职业道德不是束缚而是让你能长期做这件事的护身符。2. 信息收集把目标系统翻个底朝天提权失败十有八九不是技术不行而是信息没收集全。我见过太多人上来就找漏洞脚本跑一遍没结果就换下一个最后抱怨这机器没洞。实际上一台配置规范的机器确实很难提权但配置规范本身就是个很稀缺的品质——绝大多数被拿到低权限 shell 的机器信息收集阶段就能发现一堆线索。信息收集的核心不是命令越多越好而是带着问题去查。我会按照我是什么身份、这台机器是什么底子、有什么以高权限运行的东西、有什么能被低权限写入的东西这四个问题来组织排查。下面分几节展开每节我会说明为什么查、查到之后怎么解读。2.1 系统底子内核版本、发行版与补丁状态先摸清这台机器是什么。内核版本决定了你能不能走内核漏洞那条路发行版决定了包管理器和配置文件的位置补丁状态决定了历史漏洞还灵不灵。uname -a # 内核版本、架构、编译时间 cat /etc/os-release # 发行版和版本号 cat /proc/version # 内核编译信息和 GCC 版本 cat /etc/issue # 发行版标识可能被改过仅作参考 uname -r # 只看内核版本方便对着漏洞库查解读的时候有几个细节值得注意。uname -a里的编译时间如果很旧说明这台机器长期没更新存在历史漏洞的概率会明显上升。发行版号如果你不确定对应的内核范围可以去查该发行版的更新日志。另外一些容器环境会暴露宿主机内核版本但实际权限被限制得很死这时候即使内核有洞也未必打得通需要结合后面的容器检测来判断。注意内核漏洞的利用代码往往对版本、架构、编译选项非常敏感跑之前一定确认目标是不是快照可恢复的环境。我踩过的坑是某次在一个生产测试机上跑了一个不符合版本的内核利用脚本直接把内核 panic 了整台机器要重装。2.2 用户、组与身份线索搞清楚我和他们这一步要回答的是我现在是谁、能做什么、系统里还有哪些身份值得关注。id # 当前用户、所属组 whoami # 当前用户名 sudo -l # 当前用户能用 sudo 做什么重点 cat /etc/passwd # 所有用户及 shell cat /etc/group # 所有组sudo -l是整个提权流程里最重要的一条命令没有之一。它会列出当前用户被允许以什么身份、运行什么命令。你要重点看几种模式(ALL) NOPASSWD: ALL是直接通关(root) NOPASSWD: /usr/bin/vim这种只允许某个程序的规则则要去看这个程序能不能跳出自身去执行 shell带通配符的规则如/usr/bin/tar *往往也藏着绕过空间。/etc/passwd里要留意两类用户一类是有登录 shell 的普通用户/bin/bash、/bin/sh另一类是 UID 为 0 但不是 root 的账号——这种是隐藏的 root可能是管理员留的后门也可能是配置事故。2.3 文件系统排查SUID、SGID 与 capabilities前面说过 SUID 是提权的重灾区这里就是把它全部找出来。find / -perm -4000 -type f 2/dev/null # 所有 SUID 文件 find / -perm -2000 -type f 2/dev/null # 所有 SGID 文件 find / -perm -us -type f 2/dev/null # 同上另一种写法 getcap -r / 2/dev/null # 带 capabilities 的文件2/dev/null是为了把权限报错吞掉不然输出会被大量 Permission denied 淹没。找出来之后逐个对照公开的 SUID 滥用知识库比如 GTFOBins 这类整理好的清单判断这个程序以 root 身份运行时能不能通过它的某个参数去读写任意文件、执行任意命令、或者逃逸出一个 shell。常见的危险分子包括各种编辑器、分页器、归档工具、脚本解释器。getcap查的是另一套机制——capabilities。它把 root 的一部分特权拆成细粒度能力比如cap_setuid允许程序把进程 UID 改成任意值cap_dac_read_search允许绕过文件读权限。一个带cap_setuidep的普通程序可能就是一个直接的提权点。很多人只查 SUID 不查 capabilities会漏掉一批目标。2.4 计划任务、服务与进程找出定时以高权限运行的东西这是配置层里我最喜欢的一类。系统里有大量以 root 身份定时运行或常驻运行的任务如果这些任务调用的脚本、二进制、或者脚本里引用的文件路径是低权限用户可写的那就等于你可以在 root 执行到它的时候塞点私货。cat /etc/crontab # 系统级计划任务 ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly 2/dev/null crontab -l # 当前用户的计划任务 systemctl list-timers --all # systemd 定时器 ps aux # 所有进程及其运行身份 ps -ef --forest # 进程树看谁是谁的子进程看ps aux的时候重点找以 root 运行、但命令路径指向可写目录的进程比如某个自定义服务从/opt/app/run.sh启动而/opt/app恰好其他人可写。这类发现往往比 SUID 更好利用因为它不依赖特殊权限位只要路径可写就行。排查的时候还要注意监控类进程——有些运维工具会定期执行某个目录下的脚本这类脚本如果可写同样是一把钥匙。2.5 网络、挂载与共享容易被忽略的横向入口这一节查的是这台机器还连着别的什么。ss -antp 2/dev/null # 监听端口和对应进程比 netstat 更现代 netstat -antp 2/dev/null # 老系统的替代方案 cat /etc/fstab # 挂载配置找 no_root_squash 之类 mount # 当前挂载情况注意是否有可写共享 cat /etc/exports # NFS 导出配置NFS 的no_root_squash是个经典配置层问题如果某台共享目录导出时带了no_root_squash那么你在客户端以 root 身份创建的文件在服务端也会是 root 所有。这意味着如果你能从那台客户端去写共享目录可以放一个 SUID 程序进去然后回服务端执行它——听起来绕但实操里成功率高得惊人。监听端口那部分要结合当前身份判断有些服务只在本地监听127.0.0.1但因为你现在就在本机反而可以直接访问这类本地服务经常缺乏认证或者使用了默认凭据。3. 常见提权路径与实操拆解信息收集做完手上应该有一张候选清单了。这一节我按命中率从高到低的顺序把最常见的几条路径拆开讲。每条路径我都会说明原理、验证方法、以及实操中容易翻车的地方。重申一次以下内容仅适用于授权环境下的安全学习与自查。3.1 SUID / SGID 程序的滥用面拿到 SUID 文件清单后第一件事是筛掉系统自带的、设计上就安全的那些比如passwd、su、mount重点看两类一是第三方安装的、路径奇特的 SUID 文件二是那些本身就有强大功能的通用工具。通用工具的典型代表是编辑器和分页器。一个以 root 身份运行的编辑器如果允许你编辑任意文件、并在编辑器中执行 shell 命令那它就是一个提权点。归档工具同理——很多归档工具支持在执行时调用外部程序或者支持从归档里恢复出任意权限位的文件。验证时的思路是先确认这个程序确实带 SUID 且属主是 rootls -la看权限位然后尝试用它去读一个只有 root 能读的文件比如/etc/shadow作为无害验证成功读到再考虑进一步的利用。这个顺序很重要——先用只读操作验证能力比一上来就执行命令要稳妥得多。实操心得不要看到 SUID 就兴奋。系统里可能有几十上百个 SUID 文件逐个查会累死人。我的做法是先把清单和 GTFOBins 这类公开清单做交叉比对只留下清单上有但系统里不该出现的通常能筛到三五个候选。3.2 sudo 配置里的经典口子sudo -l的输出值得逐字读。常见的几种看起来安全其实不安全的规则sudo 规则形式表面含义实际风险(root) NOPASSWD: /usr/bin/vim只允许用 vimvim 内可执行 shell等于 root shell(root) NOPASSWD: /bin/tar *只允许用 tar通配符允许--checkpoint-action等参数执行命令(root) NOPASSWD: /usr/bin/find只允许用 findfind 的-exec参数可执行任意命令(root) NOPASSWD: ALL全开直接通关面对这类规则处理方式不是去破解sudo而是看被允许的那个程序有没有顺带能做别的事的能力。绝大多数功能完整的命令行工具都提供了某种执行外部命令或读写文件的途径。还有一种更隐蔽的情况sudo -l里显示某个命令你可以免密运行但那个命令的路径本身可写。比如规则写的是/opt/tools/check.sh而/opt/tools目录其他人可写——那你直接改掉这个脚本内容再sudo /opt/tools/check.sh就以 root 身份执行了你自己写的代码。这类问题在自定义运维脚本里极其常见。3.3 计划任务与通配符配置层的经典组合计划任务本身不是问题计划任务 可写文件 通配符三者凑齐才是。先看一个最常见的组合一个 root 的 cron 任务内容类似cd /home/user tar -czf /tmp/backup.tar.gz *。这里的*会被 shell 展开成目录下的所有文件名。如果你能在这个目录里创建文件就可以创建一个名字看起来像参数的文件——因为 tar 会把以-开头的文件名当成选项来解析。通过构造特定的参数名可以让 tar 在打包过程中执行你指定的命令而执行者是 root。# 假设发现这么一个可写的备份脚本由 root 每分钟执行 # cd /home/app tar -czf /tmp/backup.tar.gz * # 在授权靶机上的验证思路示意 cd /home/app echo cp /bin/bash /tmp/rootbash; chmod s /tmp/rootbash shell.sh chmod x shell.sh touch -- --checkpoint1 touch -- --checkpoint-actionexecsh shell.sh # 等 cron 执行后检查 ls -la /tmp/rootbash这段只是说明通配符 参数注入的原理实际验证一定要在你自己搭的靶机上跑。真实环境里参数名会因工具而异需要先确认 cron 到底调用的是哪个命令、哪个版本。除了通配符计划任务还有两个常见问题一是调用的脚本可写直接改内容就行二是脚本里引用的二进制通过相对路径调用、且 PATH 变量可控可以 PATH 劫持。这两类在 3.4 节会展开。3.4 环境变量与动态链接器路径劫持的思路PATH 劫持的原理很简单当脚本里用相对路径调用命令比如直接写backup而不是/usr/bin/backupshell 会按PATH里的目录顺序去查找。如果脚本是以 root 运行、且PATH里包含了一个你能写入的目录你就可以在那个目录里放一个同名的恶意程序等脚本执行时优先命中你的版本。echo $PATH # 看当前 PATH env # 看所有环境变量 cat /etc/ld.so.conf # 动态链接器搜索路径 cat /etc/ld.so.conf.d/*.conf和 PATH 类似的还有动态链接器相关变量。当某个带 SUID 的程序在启动时会加载外部共享库而它加载库的路径或者影响路径的环境变量可被控制时就能让它在启动时加载你的库代码从而以 SUID 所有者的身份执行。这类利用对环境的依赖比较强需要先确认目标程序的具体行为但一旦成立就很稳定。验证 PATH 劫持的标准流程是先找到以 root 运行、通过相对路径调用命令的脚本或服务再确认调用命令的那一段PATH里有没有可写目录最后放着同名程序等它被调用。整个过程的关键在第二步——很多人的 PATH 劫持失败都是因为脚本里其实用的是绝对路径。3.5 内核与第三方组件的版本问题内核漏洞这条路我给它的定位是最后手段。原因有三可利用性对版本极其敏感利用过程常常导致系统不稳定很多利用代码在真实环境下需要反复调试。处理方式应该是有条理的先拿到精确内核版本uname -r和发行版补丁级别再去公开的漏洞库或安全公告里比对确认这个版本是否受某个已知提权漏洞影响。确认受影响之后优先找与目标架构、发行版匹配的验证方法而不是随便抓一个就往上跑。除了内核本身第三方组件也经常是提权入口。装在系统里的老旧服务、Web 应用运行时、数据库、备份工具只要它们以高权限运行且版本存在公开问题就值得关注。这类问题的排查思路和内核类似确认版本、比对公告、在隔离环境验证。注意任何时候都不要在你不拥有、或者没有快照保护的系统上尝试内核利用。内核 panic 是不可逆的一次误操作可能让整个服务停摆这个责任担不起。3.6 凭据复用最没技术含量也最有效的一条把这条放在最后是因为它在实战里命中率最高但很多人反而容易忽略——他们一门心思找复杂漏洞却没去翻最简单的配置文件。grep -ri password /var/www /opt /home 2/dev/null grep -ri passwd\|pwd\|secret\|token /etc/*.conf 2/dev/null cat ~/.bash_history ls -la /var/backups /tmp /var/tmp 2/dev/null find / -name *.bak -o -name *.old -o -name *.sql 2/dev/null要查的地方包括Web 应用的配置文件数据库连接串里经常明文写着凭据、版本控制目录比如应用目录下遗留的.git里面可能有历史提交记录、命令历史管理员手敲过的带密码命令、备份目录可能直接躺着一份/etc/shadow的副本或者数据库导出、以及家目录里的 SSH 私钥。一旦拿到一个可用的高权限凭据接下来的事就水到渠成——su或者sudo上去就行。这条路径的价值还在于它能直接服务于横向移动同一个密码往往在多台机器上复用。4. 拿到高权限之后会话加固、凭据整理与善后很多人一提权成功就松口气收工其实后面这一段才是体现专业度的地方。授权测试的产出不只是证明能提权还包括一份清晰的证据链、一份可复现的操作记录、以及不留下烂摊子的收尾。这一节讲三个动作。4.1 会话加固别让你的 shell 说断就断通过反弹连接拿到的 shell 往往是哑终端——没法用 Tab 补全、没法用方向键、CtrlC一按就连带整个会话一起挂掉。这种状态下做复杂操作非常痛苦稍微一个误触就得重来。# 如果你有 python3先升级成完整 TTY python3 -c import pty;pty.spawn(/bin/bash) # 或者用 script 命令 script -qc /bin/bash /dev/null升级之后再做两件事把终端设成 raw 模式、设置正确的窗口大小这样 Tab 补全和全屏程序比如编辑器才能正常工作。具体按键组合与环境相关操作时按提示来即可。另外建议在拿到权限的第一时间就建立一个备用通道——比如再起一个稳定的反向连接、或者添加一个自己可控的普通账号作为后备。目的不是持久化留后门而是防止主通道意外断开后你失去访问能力导致无法完成测试和清理。备用通道在测试结束后必须一并清除。4.2 凭据与信息整理为报告和横向做准备拿到高权限后你会获得读取全系统的能力。这时候要系统性地把所有有价值的凭据和信息整理出来一是为了判断影响范围二是为了在报告里量化危害。# 系统凭据 cat /etc/shadow cat /etc/passwd # 应用凭据 find / -name config.php -o -name database.yml -o -name .env 2/dev/null # SSH 密钥与授权文件 find / -name id_rsa -o -name authorized_keys 2/dev/null # 历史记录 cat /root/.bash_history整理的时候要分类记录哪些是哈希、哪些是明文、哪些是密钥各自对应哪个服务。同时留意/etc/hosts、SSH 配置/root/.ssh/config、known_hosts、以及各类服务的连接配置这些能帮你画出内网拓扑。实操心得所有拿到的凭据我都会在报告里标注来源路径和有效范围。这个习惯来自一次教训——当时我拿到一个数据库密码以为只能连本机结果报告里没写清楚客户误以为影响范围很小。后来补做了横向验证才发现这个密码在多台机器上复用。把来源和范围写清楚比单纯列一堆密码有价值得多。4.3 清理与报告不留痕才叫专业清理不是擦掉证据而是把测试过程中对系统造成的改变恢复原状。包括删除你上传的枚举脚本和利用文件、恢复你修改过的配置、移除你创建的测试账号和备用通道、清理你添加的定时任务和 SUID 文件。系统性的做法是在开始测试时就记录下每一步的改动收尾时逐条回滚。报告部分要把整个链条写清楚初始访问点是什么、用了哪条提权路径、每一步的命令和输出、最终拿到什么级别的权限、影响范围有多大。提权路径要写得让客户的技术人员能复现同时配上修复建议——比如某 SUID 文件属主应为非 root、计划任务脚本应使用绝对路径、配置文件中不应明文存储凭据。一份好的报告客户照着能修同行照着能复现这才算完整。5. 常见问题与排查技巧实录这一节是我这些年踩坑攒下来的经验按现象、原因、处理的方式整理。很多问题不是知识盲区而是操作细节。5.1 提权失败时的排查顺序当你明明觉得有洞但就是打不通别急着换方向按这个顺序回头查第一确认当前的真实身份。有些人跑了半天利用代码其实早就通过某个 SUID 或者 sudo 拿到 root 了只是没意识到——先id一下再说。第二确认利用代码的运行前提。SUID 利用需要文件确实带 SUID 且属主是 rootPATH 劫持需要脚本真的用相对路径且 PATH 里有可写目录内核利用需要对版本、架构、编译选项。任何一条不满足都会失败而且是悄无声息地失败。第三确认执行环境。容器、受限 shell、只读文件系统、安全模块如某类强制访问控制都会让原本可行的利用失效。判断是不是容器可以看/.dockerenv是否存在、/proc/1/cgroup的内容、以及文件系统挂载情况。第四确认是否有防护拦截。有些系统装了主机入侵检测或文件完整性监控会拦截你上传或执行特定文件表现就是命令跑了但没反应。这种情况下要观察系统日志或告警行为来判断。5.2 常见现象速查表现象可能原因处理思路sudo -l需要密码但不知道密码规则未配 NOPASSWD转为从凭据泄露角度找密码SUID 清单里全是系统自带无第三方 SUID 或已修复转向配置层cron、服务、PATH内核版本低但利用失败发行版已回补补丁查发行版补丁级别别只看内核号反弹 shell 秒断非交互终端或网络策略换端口、换协议、升级 TTY找到可写脚本但不被 root 执行触发条件未满足确认调用方身份和触发时机提权后命令报 command not foundPATH 被重置用绝对路径或重新设置 PATH写入的文件在别处看不到处于容器独立文件系统结合容器判断找宿主机挂载点5.3 几条不那么好写进文档的经验最后分享几条我个人的体会。第一条是关于耐心提权里最难的不是技术而是在一堆看似无用的信息里找到那条线索。我做过一次靶场前两个小时一无所获最后是在一个不起眼的.bash_history里发现管理员用sudo跑过一个自定义脚本而那个脚本可写——整条链就通了。如果当时急着换目标就错过了。第二条是关于记录从拿到低权限 shell 的那一刻起就养成把每条命令和输出都存下来的习惯。用script记录整个会话或者手动把关键输出复制到本地。事后写报告、复现问题、或者向客户解释全靠这些记录。我吃过记性好的亏——当时觉得这个细节我记得住结果三天后写报告时怎么也想不起来具体是哪个文件。第三条是关于分寸提权测试里最容易失控的是内核利用和权限修改。我的原则是——能用只读方式验证的绝不做写操作能用配置层路径的绝不碰内核能通过快照恢复的环境才允许做高风险尝试。技术能力体现在用最小的动作达成目标而不是用了多少高级技巧。还有一个特别实用的习惯给每个候选路径建一个清单逐条标记已确认可利用、已确认不可用、待验证。这样你不会重复劳动也不会在收尾时漏掉某个改了一半的配置。看起来笨但一个项目几十条线索的时候这个清单能救命。这套流程走到最后你会发现自己对 Linux 这台机器的理解上了一个台阶——你不再只是用它而是开始从权限和信任关系的角度看它。这个视角才是这份笔记真正想传递的东西。