浅析Linux系统常规提权手段的原理与技巧

文章目录

  • 前言
  • 0、提权基础认知
  • 1、sudo滥用提权
  • 2、SUID特殊权限
  • 3、passwd文件提权
  • 4、shadow文件提权
  • 5、SSH登录密码爆破
  • 6、通过计划任务提权
  • 7、劫持环境变量提权
  • 8、利用通配符->提权
  • 9、其他潜在提权路径
  • 10、内核cve漏洞提权
  • 总结

前言

Linux 系统被广泛应用于部署各类应用服务(相比 Windows 而言便宜很多),在渗透测试过程中,通过 Web 服务漏洞(比如文件上传漏洞)拿到服务器 Shell 后,经常会发现所获得的 Shell 仅有较低的权限,而为了进一步获得高权限 Shell(root),避免不了地就是进一步进行提权。本文来学习、总结下 Linux 系统一些常规的提权手段的原理与技巧。

0、提权基础认知

此章节引用自:《Linux 提权原理及10种提权姿势详解 | OSCP备考指南》。作者讲得很好,系统性地解释了一些基础的问题。

在开始学习 Linux 提权之前,我们需要先理解以下三个问题:

  1. 什么是系统提权?
  2. 为什么获取的 shell 会有高低权限的区别?
  3. 为什么我们需要进行提权?

只有理解了以上的三个问题,才能做到在后续学习具体的提权技巧时,能够知其然并知其所以然。

0x1 什么是提权?

首先我们来看一下什么是系统提权?

一次完整的渗透测试流程,一般包含以下 8 个步骤:
浅析Linux系统常规提权手段的原理与技巧_第1张图片
在渗透测试前期,我们会想尽办法通过「某个漏洞攻击」获取到目标主机系统上的一个 shell 用于执行系统命令,从而达到控制目标主机的目的,也就是图中的第 4 步。

当我们获取到的初始 shell 为低权限用户时,需要想办法提升权限为高权限用户,这个过程就叫做系统权限提升,简称「提权」 (对应图中第5步)。

0x2 为什么 shell 会有高低权限的区别?

有些同学会有一个疑惑:为什么同样是通过漏洞攻击获取到的 shell ,有时候是低权限,有时候又是高权限呢?

下面以一个简单的例子来说明:
浅析Linux系统常规提权手段的原理与技巧_第2张图片
通常情况下 Web 服务架构如上图所示:后端 linux 服务器通过 Tomcat 中间件提供 Web 服务。

如今的计算机操作系统都是基于多用户设计的,通常一台计算机上同时存在着多个不同权限的系统用户,而在 Linux 服务器上,每个服务都需要先赋予某个用户权限才能运行。

假设 tomcat 服务以普通用户 www-data 的权限运行并提供 Web 服务,此时如果黑客通过 Web 漏洞获取到 shell,此 shell 就是一个 www-data 用户权限的 shell,此时就需要提权。反之,若 tomcat 是以 root 用户权限运行,那黑客获取到的 shell 就是 root 权限。

0x3 为什么要提权?

在渗透测试中,高权限 shell 能带来以下好处:

  1. 高权限能对更多的文件进行「增删改查」操作,便于进一步收集主机系统中的敏感信息;
  2. Linux 系统的 root 权限可获取 shadow 文件中的密码 Hash,若内网环境中存在「账户/密码复用」的情况,可用于横向扩展;
  3. Windows 系统中的 system 权限可提取内存中的密码 Hash,可进一步用于域渗透。

简而言之,获取更高权限的 shell,能为渗透测试后期的工作带来便利。

1、sudo滥用提权

日常使用 Linux 系统我们会发现:当普通用户执行特殊命令时,在命令前加上 sudo,此时系统会让你输入密码以确认终端机前操作的是你本人,确认后系统会将该命令的进程以超级用户的权限运行。同时在一定的时间段内,再次执行 sudo 的命令时不再询问密码,超出此时间段(一般为 5 分钟)后需要再次输入密码。
浅析Linux系统常规提权手段的原理与技巧_第3张图片
与此同时,从官网下载的 Ubuntu 虚拟机镜像或者 Kali 镜像都默认支持我们直接通过使用 sudo 命令来给自行创建的普通用户临时赋予 root 权限执行命令,那么如果所有 Linux 用户都能通过 sudo 命令直接获得 root 用户的身份执行命令了(虽然这个过程需要验证普通用户的密码,但是并不验证 root 用户的密码),我们哪还需要做什么 Linux 提权,直接 sudo 不就完了?

先直接给结论:实际上并不是每一个新创建的用户都可以使用 sudo 提升命令的权限,要想使一个用户具有使用 sudo 的能力,需要 root 用户将其用户名、可以执行的特定命令、按照哪种用户或用户组的身份执行等信息注册到 /etc/sudoers 配置文件中,才可完成对该用户的授权。

0x00 为什么需要 sudo

使用 su 命令可以让普通用户切换到 root 身份。但当多人使用同一台主机时,大家都使用 su 切换到 root,那必然都知道 root 的密码,而且 root 操作会有风险,知道的人越多也更容易泄露。为了避免这类问题,解决方案是使用 sudo 命令,他可以让你切换至 root 权限去执行命令而无需知道 root 密码。

0x01 sudo命令的特点

在 sudo 中,不仅可以为用户提供 “运行方式” 属性,还可以限制在有或没有密码的情况下可以执行的命令。如果在 sudoers 文件中配置了带密码的“运行方式”,系统将提示用户输入其帐户的密码,而不是目标用户的密码。

另一个特点是,与 su 不同的是,一旦成功验证了 sudo 访问权限,它将为您的帐户缓存提升权限而不是存储密码,因此可以以另一个用户身份运行命令而无需实际输入密码,除非超时和没配置 NOPASSWD 选项。

0x02 Sudoers 文件格式

sudo 权限的配置文件是/etc/sudoers,如果还包括从其它文件包括配置,可以使用@includedir /etc/sudoers.d。它允许使用 ID 或别名为组和用户配置访问权限。

#授权规则配置文件
/etc/sudoers
/etc/sudoers.d
#安全编辑授权规则文件和语法检查工具
visudo

找个 Ubuntu 系统查看下默认的/etc/sudoers文件的特点:
浅析Linux系统常规提权手段的原理与技巧_第4张图片
可以看到是个仅 root 用户只读的文件。其中的配置语法:

root	ALL=(ALL:ALL) ALL
  • 第一个 ALL 表示允许从任何终端、机器访问 sudo;
  • 第二个 (ALL) 表示 sudo 命令被允许以任何用户身份执行;
  • 第三个 ALL 表示所有命令都可以作为 root 执行;

这条配置代表的是:root 用户可以在任何机器上,通过 sudo 命令以任何用户的身份执行任何指令。
浅析Linux系统常规提权手段的原理与技巧_第5张图片
上述配置的通用表示形式如下

<user/group list> (<host list> or ALL) = [<runas-user:runas-group>] [<tag list>] (<command list> or ALL)

在小括号 () 中的字段是必需的,或者使用ALL;而在中括号 [] 的字段是额外。如果没有,那么默认是 (ALL:ALL) 并且会忽略。

举个例子,现在假设允许用户 amit 代表用户 terabyte 执行所有命令,并且任何组也不需要密码来执行此操作。具体的配置如下所示:

amit ALL=(terabyte) NOPASSWD: ALL
$ sudo id
[sudo] password for amit: 
Sorry, user amit is not allowed to execute '/usr/bin/id' as root on h3ll.
$ sudo -u terabyte id
uid=1000(terabyte) gid=1000(terabyte) groups=1000(terabyte)
  1. 上述第一条命令:sudo 已成功通过身份验证,但在 sudoers 配置中找不到以 root 身份运行的配置;
  2. 上述第二条命令:sudo 使用相同的权限提升,因为它是在超时之前访问的,并且配置为以 terabyte 用户身份运行。

如果要检查当前用户可以使用 sudo 运行什么命令以及以哪个用户身份运行,请使用 sudo -l 命令。

$ sudo -l
Runas and Command-specific defaults for amit:
    Defaults!/etc/ctdb/statd-callout !requiretty

User amit may run the following commands on h3ll:
    (terabyte) NOPASSWD: /bin/bash

上述配置则表示用户 amit 可以以 terabyte 用户身份运行命令 /bin/bash 而无需输入任何密码:
浅析Linux系统常规提权手段的原理与技巧_第6张图片

0x03 Sudoers进阶实操

在 Ubuntu 中我使用按照镜像时创建的 tr0e 用户新建 test 用户,然后 su 命令切换到 test 用户后进一步尝试使用sudo useradd test2 命令来创建 test2 用户,发现系统会提示 test 用户默认无权限执行 sudo 命令:
浅析Linux系统常规提权手段的原理与技巧_第7张图片

此时切换回 tr0e 用户,执行 sudo vim /etc/sudoers 命令编辑配置文件并加入一条新的配置(表示允许 test 用户通过 sudo 命令获得 root 身份运行所有指令):

test  ALL=(root) ALL

浅析Linux系统常规提权手段的原理与技巧_第8张图片
接着再次测试,切换到 test 用户后执行 sudo useradd test2 命令即可成功获得权限创建新用户:
浅析Linux系统常规提权手段的原理与技巧_第9张图片

0x04 sudo用户组特权

细心的读者可以关注到, /etc/sudoers 文件中存在如下默认配置:
浅析Linux系统常规提权手段的原理与技巧_第10张图片
它代表的是 sudo 用户组可以通过 sudo 指令来获得任意用户的身份(包括 root)执行任意命令。

而安装 Ubuntu 虚拟机时创建的首个账户 tr0e,正好在 sudo 用户组里:
浅析Linux系统常规提权手段的原理与技巧_第11张图片
这也就解释了为什么我们创建的首个账户能够通过 sudo 指令获得 root 身份来执行任意命令。Kali 虚拟机的默认账户 kali 执行 sudo 可直接获得 root 权限也同理。
浅析Linux系统常规提权手段的原理与技巧_第12张图片

0x05 sudo滥用导致提权

从上面的基础知识中,我们不难得出结论:如果运维人员错误地将 Linux 系统一个普通用户加入 sudo 用户组,那么将导致该普通用户被攻击者控制(弱口令登录、反弹 shell)后,攻击者可以直接借助 sudo 指令提权到 root 权限执行任意命令。

排查系统是否存在此类危险账户配置的方法很简单:

#查看可以远程登录的用户
cat /etc/passwd | grep sh$    
#查看位于sudo用户组的用户
cat /etc/group | grep sudo

浅析Linux系统常规提权手段的原理与技巧_第13张图片
但是,有且仅有具有 sudo 用户组权限的用户才可以被用于提权吗?显然不是。

前面我们创建的 test 用户也可被用于提权:
浅析Linux系统常规提权手段的原理与技巧_第14张图片
上述 test 用户是被配置为允许以 root 身份执行任意命令,如果不是允许执行任意命令,而是单个命令,那就不能被用于提权了吗?自然也不是。

比如我们现在只允许 test 用户以 root 身份执行 find 指令,sudo vim /etc/sudoers 修改配置如下:

test  ALL=(root) /usr/bin/find

浅析Linux系统常规提权手段的原理与技巧_第15张图片
此时如何借助 find 指令提权到 root 并执行任意命令?很简单,可以使用 find 命令用来在指定目录下查找文件,并使用 find 指令的特有 -exec 参数来执行 /bin/bash,以获得 root shell

sudo find /home -exec /bin/bash \;

浅析Linux系统常规提权手段的原理与技巧_第16张图片
【补充】简单介绍下 find 指令的 -exec 参数,它用于 find 命令对匹配到的文件执行该参数所给出的 shell 命令,相应命令的形式为command { } \;,请注意{ }\;之间的空格。举个例子,查找当前目录下所有.txt文件并把他们拼接起来写入到 all.txt 文件中:

find . -type f -name "*.txt" -exec cat {} \; > all.txt

浅析Linux系统常规提权手段的原理与技巧_第17张图片

【More】实际上,假如普通用户被允许以 sudo 运行 find、cat、vi、more、less、nmap、perl、ruby、gdb、python 等任何编程语言编译器、解释器和编辑器,那么我们就可以通过这些命令,获得 root 权限。相应的利用方式请参见:Linux sudo提权 或者 Linux提权精讲之 sudo 方法。

常见可利用的指令归总如下:

允许 root 身份运行的指令 获得 root shell 手段
find sudo find / -exec /bin/bash \;
evn sudo env /bin/sh
more sudo more /etc/hosts --> !/bin/bash
vim sudo vim -c '!bash'
python sudo python -c 'import pty;pty.spawn("/bin/bash")'
awk sudo awk 'BEGIN {system("/bin/bash")}'
ftp sudo ftp --> ftp> !/bin/bash
ash sudo ash --> bash

综上所述,我们来总结下 sudo 滥用导致提权获得 root shell 的场景:

  1. 运维人员错误地将普通用户直接加入 sudo 用户组;
  2. 运维人员错误地给普通用户配置了 test ALL=(root) ALL 或者 test ALL=(ALL:ALL) ALL 这样的以 root 身份执行任意命令的权限;
  3. 运维人员错误地给普通用户配置了 test ALL=(root) /usr/bin/find这样的以 root 身份执行的危险指令;

实际攻击中,可以使用 sudo -l 命令快速判断当前用户可以使用 sudo 运行什么命令、以及以哪个用户身份运行。但需要注意的是,以上三个漏洞场景,如果未配置 NOPASSWD 选项的话,均需要输入当前普通用户的登录密码后才能完成 sudo 指令的执行,所以单纯拿到 Webshell 而不知道当前服务器登录用户的登录密码的情况下也是无法做到提权到 root shell 的。

最后反过来,如果作为防守方如何检查系统是否出现了因为 sudo 提权导致的入侵?可以通过 grep 命令过滤出 /var/log/auth.log 日志文件记录的 sudo 行为动作,从而清晰找到提权动作:

grep 'sudo' /var/log/auth.log

浅析Linux系统常规提权手段的原理与技巧_第18张图片

2、SUID特殊权限

0x01 Linux文件普通权限

先回顾下 Linux 的文件权限管理:Linux 的文件权限有 3 种,即对文件的读(用 r 表示)、写(用 w 表示)和执行(用 x 表示,针对可执行文件或目录)权限。
浅析Linux系统常规提权手段的原理与技巧_第19张图片
0x01 Linux文件特殊权限

除了 r、w、x 这三种常见的权限,其实 Linux 还有三种特殊的权限:

Linux权限 解释
SUID 用于二进制可执行文件上,用户将继承此程序所有者权限
SGID 用于二进制可执行文件上以及目录上,此目录新建的文件的所属组将自动从此目录继承
STICKY 用于目录上,表示此目录的文件只能由所有者自己来删除

相对完整的 Liunx 特殊权限介绍可参见:Linux中文件特殊权限suid、sgid、sticky(有图详细讲解),下文只介绍与 Linux 提权相关的 SUID 权限。

0x02 suid特殊权限应用

SUID 特殊权限只适用于可执行文件,它对目录是无任何意义的。只要用户设有 SUID 的文件执行权限,那么当用户执行此文件时,就会以文件所有者的身份去执行此文件,一旦文件执行结束后,身份的切换就随之消失。

例如用户想修改自己的密码,但是修改涉及到 /etc/shadow 文件,这个文件只有 root 权限才能修改,这时候 passwd 命令就设置了特殊权限,修改密码时临时使用了 root 的权限去修改 shadow 文件。
浅析Linux系统常规提权手段的原理与技巧_第20张图片
给文件设置或删除 SUID 权限的方式如下:

chmod u+s filename   #设置SUID位
chmod u-s filename   #去掉SUID设置
chmod 4750 file      # 在4750中,4说明SUID位被设置,7为所有者读写执行权限

执行 ls -l file 可以看到具备 suid 特殊权限的文件相应的携带s 属性,比如上面我们介绍的 passwdsudo 文件:
浅析Linux系统常规提权手段的原理与技巧_第21张图片

0x02 suid文件提权原理

suid(set uid) 作为 Linux 中的一种特殊权限,其特点是用户运行某个程序时,如果该程序有 suid 权限,程序运行进程的属主不是发起者,而是程序文件所属的属主。故 suid 可以让调用者以文件拥有者身份运行该文件,所以利用 suid 提权的核心就是运行 root 用户所拥有的 suid 的文件,那么运行该文件的时候就得获得 root 用户的身份了。

SUID 提权利用步骤:

  1. 查找具备 suid 权限且属主是 root 的文件;
  2. 查找对应文件的利用方法(不是所有文件均可利用,需要结合时间成本考虑是否进行利用);

先来看第一步:如何查找 SUID 文件?

find / -perm -u=s -type f 2>/dev/null
参数:
	/      表示从文件系统的顶部(根)开始,查找每个目录
	-perm  表示搜索后面的权限
	-u=s   表示查找 root 用户拥有的文件
	-type  表示我们正在寻找的文件类型
	f      表示普通文件,而不是目录或特殊文件
	2      表示到进程的第二个文件描述符,即 stderr(标准错误)
	>      表示重定向
	/dev/null 是一个特殊的文件系统对象,它会丢弃写入其中的所有内容。

或者:

find / -perm -4000 2> /dev/null
参数:
   -perm -4000 指的是寻找 4000 权限的文件,4000 指的就是 SUID 权限

在 Ubuntu 试着执行一下:

tr0e@ubuntu:~/Desktop$ find / -perm -u=s -type f 2>/dev/null
/usr/lib/openssh/ssh-keysign
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/xorg/Xorg.wrap
/usr/libexec/polkit-agent-helper-1
/usr/sbin/pppd
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/umount
/usr/bin/passwd
/usr/bin/pkexec
/usr/bin/su
/usr/bin/fusermount3
/usr/bin/vmware-user-suid-wrapper
……

接着来看看第二步:如何借助 suid 权限的文件完成提权?

依旧以 find 指令二进制文件为例来演示,手动赋予 suid 权限后进行提权:

find /usr/bin/su(具有suid权限的file) -exec whoami \;
find /usr/bin/su(具有suid权限的file) -exec /bin/bash -p \; -quit    # 利用find得到一个root权限的shell
find / -exec /bin/sh -p \;  # 一样可得到一个root权限的shell

浅析Linux系统常规提权手段的原理与技巧_第22张图片
注意:上述截图演示的过程中, sudo -k 命令是用于清除 tr0e 用户执行 sudo 命令时校验完密码之后的 5 分钟免密码认证窗口,使得重新执行 sudo 命令必需重新输入密码。

其它属主为 root 且具备 suid 特殊权限时,可用于提权到 root Shell 的常见文件(并非全部)与利用方法如下:

属主为 root 且具备 suid 特殊权限 获得 root shell 手段
find find /usr/bin/su(具有suid权限的file) -exec /bin/bash -p \; -quit
evn env /bin/sh -p
more more /etc/profile --> !/bin/sh -p
gdb gdb -nx -ex ‘python import os; os.execl("/bin/sh", “sh”, “-p”)’ -ex quit
python python -c ‘import os; os.execl("/bin/sh", “sh”, “-p”)’
awk awk ‘BEGIN {system("/bin/bash -p")}’
ftp ftp --> ftp> !/bin/bash
bash bash -p
ssh ssh -o ProxyCommand=’;sh -p 0<&2 1>&2’ x
php CMD="/bin/sh" --> php -r “pcntl_exec(’/bin/sh’, [’-p’]);”
time time /bin/sh -p

综上,如果一些属主为 root 的危险文件被赋予 SUID 特殊权限,将可被用于提权到 root。但是需要注意的是,find / -perm -4000 2> /dev/null这类查找系统 suid 特殊权限的命令被各大 HIDS 系统列入检测范围,很容易被检测出来。

3、passwd文件提权

/etc/passwd/etc/shadow 文件是 Linux 系统登录认证的关键文件,如果系统运维人员对 passwd 或 shadow 文件的内容或权限配置有误,则可以被利用来进行系统提权。在本章中,我们主要探讨 /etc/passwd 文件的提权方法, 利用 /etc/shadow 提权的方法会在下一章节讨论。

「理解 /etc/passwd 文件含义」

Linux 密码信息保存在两个文件中,分别为:/etc/passwd/etc/shadow,我们先了解一下 /etc/passwd 内容的含义。

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
……
hplip:x:127:7:HPLIP system user,,,:/run/hplip:/bin/false
gdm:x:128:134:Gnome Display Manager:/var/lib/gdm3:/bin/false
tr0e:x:1000:1000:Tr0e,,,:/home/tr0e:/bin/bash
redis:x:129:138::/var/lib/redis:/usr/sbin/nologin
sshd:x:130:65534::/run/sshd:/usr/sbin/nologin
test:x:1001:1001::/home/test:/bin/bash
test2:x:1002:1002:test2,1,2,3,4:/home/test2:/bin/bash

/etc/passwd 文件用于保存用户信息,每一行代表一个用户,每一行通过冒号分为七个部分:
浅析Linux系统常规提权手段的原理与技巧_第23张图片
主要来解释下其中两个字段:

  1. 第二个字段为 x 代表的是密码保存于 /etc/shadow 文件之中;
  2. 最后一个字段如果为 /bin/bash 代表用户可以使用 shell 登录,如果为 nologin 则表示不能通过 shell 登录的用户。

简单来说,当你登录 Linux 系统时会有以下几个步骤:

  1. 检测「输入的用户名」是否与 /etc/passwd文件中某一行第一个字段匹配;
  2. 若匹配成功,再对比该行第二个字段的密码,如果均匹配成功即登录成功;
  3. 登录成功之后所具有的权限,通过第三个字段 UID 和第四个字段 GID 确定。其中 UID=0 代表 root 用户(也就是说无论第一个字段代表的用户名是什么,只要 UID=0,则该账户就拥有 root 权限,这点在提权中非常重要);

由此可见,/etc/passwd 文件在 Linux 登录认证过程中起到非常关键的作用。试想,如果我们能够对 /etc/passwd 文件内容进行伪造、篡改,那就能很轻易的登录成功并获取任意用户权限

不过一般情况下,只有 root 用户拥有对 /etc/passwd 文件的写入权限,其他用户均只有读取权限。但有时候由于系统管理员的错误配置,也会给我们带来可乘之机。

「通过 /etc/passwd 文件提权」

通常来说,通过 /etc/passwd 提权的方法有两种:

  1. 如果具有 /etc/passwd 的 w (写入) 权限,可以直接添加一个 root 权限的用户;
  2. 如果 /etc/passwd 中存储 root 用户密码哈希,可以使用 john 进行破解;

攻击场景一:/etc/passwd 写权限错误配置

假设 /etc/passwd 文件的权限配置错误,造成普通用户具有写权限。
浅析Linux系统常规提权手段的原理与技巧_第24张图片
那么,我们直接使用当前用户的 Shell 编辑 /etc/passwd 文件,修改 test 用户的配置,将其 UID 和 GID 由 1001 修改为 0:

# 原来的值
test:x:1001:1001::/home/test:/bin/bash
# 修改后的值
test:x:0:0::/home/test:/bin/bash

然后直接 su test 切换到 test 用户,发现其已经成功成为 root 权限的用户了:
浅析Linux系统常规提权手段的原理与技巧_第25张图片
当然,此处也可以直接由 tr0e 用户直接修改自身的 UID 和 GID,但是经验证,需要重启后才能生效,成为 root 用户。

进一步地,我们可以直接通过 /etc/passwd 文件新建用户并在密码占位符处添加指定的 hash 密码,同时授予该用户 root 权限(UID 设置为 0),从而通过 SSH 登录新建的用户,获得完整可控的 root shell。下面来完整看看如何实现。

1)首先,使用 perl 语言(Linux自带)生成带有盐值的密码(密码 123456):

perl -le 'print crypt("123456","addedsalt")'  # 输出结果:adrla7IBSfTZQ

在这里插入图片描述
2)往 /etc/passwd 文件中新增一个用户 test3:

test3:adrla7IBSfTZQ:0:0:root:/root:/bin/bash

然后 su test3 切换到 test3 用户或者 SSH 登录,即可获得 root shell:
浅析Linux系统常规提权手段的原理与技巧_第26张图片
同理,攻击者也可以通过 /etc/passwd 文件修改 root 用户的密码(使用特定 hash 值替换密码占位符的 X)来实现 root 账户的接管。

攻击场景二:/etc/passwd 存储用户密码 hash

假设如果 /etc/passwd 中存储了 root 用户密码 hash 值,而不是存储在 /etc/shadow中,可以通过使用 john 工具来进行密码暴力破解。
浅析Linux系统常规提权手段的原理与技巧_第27张图片
这个攻击场景的实际价值是:默认情况下,/etc/passwd 文件对于其他任意用户都是可读的,而 /etc/shadow 文件则只有 root 特权用户才可以读取,所以一旦用户的密码错误存储到了 /etc/passwd 文件中,那么将存在敏感信息泄露、用户密码存在暴力破解的风险。

但是这种情况一般只能发生在该主机曾经被入侵过,或者运维人员的错误配置造成的,因为 Linux 系统默认创建的用户密码并不会保存到 /etc/passwd 文件中。故此处只是提供一种特殊情况下的攻击利用场景,实际上更具价值的威胁场景是下一个章节即将提到的 /etc/passwd 文件内容泄露后导致的用户密码 hash 爆破的问题,故这部分暴力破解的工具方法留到下一章节讲解。

「简单总结一下本章节」

通过本章节的学习也更好地理解了 /etc/passwd 文件在 Linux 系统用户管理中的重要作用,对于运维人员来说,务必不要发生错误地将此文件的写权限赋予普通用户、或者将用户的登录密码 hash 值直接保存在该文件的情况。

4、shadow文件提权

上文已经提到了,/etc/shadow 文件里面的就是用户登录密码的 hash 值,但是只有 root 权限才可以查看。
浅析Linux系统常规提权手段的原理与技巧_第28张图片
该文件的配置每一行对应一个用户,通过冒号分隔开各个配置项,具体配置项结果如下:
浅析Linux系统常规提权手段的原理与技巧_第29张图片
我们重点关注下关于用户密码的第二个字段:

  1. 这个密码字段是单向不可逆的,目前 Linux 的密码采用的是 SHA512 散列加密算法,原来采用的是 MD5 或 DES 加密算法,SHA512 散列加密算法的加密等级更高,也更加安全;
  2. 所有伪用户的密码都是 “!!” 或 “*”,代表该用户没有设置密码,是不能登录的。当然,新创建的用户如果不设定密码,那么它的密码项也是 “!!”或 “*”,代表这个用户没有密码,不能登录;

「通过 /etc/passwd 文件提权」

通过 /etc/shadow 提权的方法有 3 种:

  1. 如果具有 /etc/shadow 的 w (写入) 权限,可以直接修改 root 密码;
  2. 如果具有 /etc/shadow 的 r (读取) 权限,可以通过读取 root 用户密码并使用 john 进行破解;
  3. 如果通过 Web 漏洞(比如路径穿越导致的任意文件读取)可读取到 /etc/shadow 文件内容,那么可以通过 john 进行用户密码 hash 值的暴力破解。

攻击场景1:/etc/shadow 写权限错误配置

此处假设的是运维人员错误地给 /etc/shadow 文件授予其他用户组的用户写权限,导致普通用户可以修改该文件,也就可以修改任意用户的登陆密码 hash 值,实现账户接管。

此处我直接修改下 test2 用户的 hash 值:

# 原有值
$y$j9T$rawXHGP/H68MmfmTc7BGU.$UF7.3HutpCVqirHdF7037l9SMtZ86l2KPzLVYTy5BJ4
# 篡改后的值,对应密码明文为123456
adrla7IBSfTZQ

可以成功 su 切换到 test2 用户,并使用新的篡改后密码登录:
浅析Linux系统常规提权手段的原理与技巧_第30张图片
对应的,从普通用户 shell 提权到 root shell 的话,我们修改 root 的密码 hash 即可。

攻击场景2-3:/etc/shadow 文件内容泄露

此处假设的是 /etc/shadow 文件内容泄露导致用户登录密码 hash,我们可以通过 john 工具(Kali Linux 自带)对其密码 hash 值进行暴力破解。

此处我以 Ubuntu 虚拟机 root 账户作为演示:
在这里插入图片描述
在攻击机 Kali 中,需要将获取到的 root 用户 hash 写入本地文件 hash.txt 中:

echo 'root:$y$j9T$XsMeGNJuLpQL/BKCp9T5k/$1KGT8QjtRatz7vvfbeviAYmd8nDBe7NadKjYQM7Wjx6:19728:0:99999:7:::' > hash.txt

然后运行 john 开始进行自动化密码破解:
浅析Linux系统常规提权手段的原理与技巧_第31张图片
可以看到,已经成功爆破出 root 用户的密码为 qwer1234。

关于 John 密码爆破工具的几点补充:

  1. 现在 John the Ripper 爆破 Linux 的 shadow 文件时需要加上 --format=crypt,否则会报错;
  2. 上述执行john --format=crypt hash.txt虽没指定本地密码本,但是从日志中可以看到,Kali 自动加载本地密码本/usr/share/john/password.lst进行爆破;
  3. 能否成功爆破出密码,密码本的密码数量和质量至关重要,故我们在实际的渗透过程中,可以给/usr/share/john/password.lst密码本添加特定的特征密码后再进行密码破解,比如针对特定企业、特定管理员姓名特征添加可能的密码(如 Xiaomi@123、Zhangsan@1995 等),会提高成功率;
  4. 注意,John 工具对于同一个破解文件中的同一条 hash 记录只会爆破一次,如果第二次执行 john hash.txt 是不会得到结果的。如果想查看上一次爆破的结果,可以使用 --show 来再次显示已经爆破的密码:
    浅析Linux系统常规提权手段的原理与技巧_第32张图片

「简单总结一下本章节」

如果运维人员错误地将 /etc/shadow 的写权限开放给普通用户,那么攻击者可以篡改任意用户的登录密码并实现账户接管;如果 /etc/shadow 文件信息泄露,那么 Linux 服务器的用户密码存在被暴力破解的风险。

5、SSH登录密码爆破

之前在前面一篇文章:《渗透测试-Vulnhub靶机DC-1实战》 中介绍给暴力破解 Linux 用户登录密码的另一种方法:使用 hydra + John 密码包进行 SSH 登录密码爆破,这也是获得 root 权限最常规、最原始、最粗暴的方法(但是实战中大概率会遇到目标服务器的 root 账户限制了远程登录失败的尝试次数,进行账户锁定或 ip 封锁),详情可参见该博文,本文不再赘述,仅记录方法思路。

6、通过计划任务提权

在前面的文章:《从0到1浅析Redis服务器反弹Shell那些事》中,介绍过 Linux 计划/定时任务的概念和使用。

定时任务(cron job)可以用来设置周期执行的命令,提权的原理为计划任务以 root 权限运行,计划任务中的脚本其他用户有写入的权限,或者脚本所属组为其他用户,则可以进行借助覆写计划任务提权(比如反弹 Shell)。

但是可以看到,默认情况下,定时任务文件属于 root 用户的情况下,其他用户都是不可写的,除非运维人员错误地进行了配置……
浅析Linux系统常规提权手段的原理与技巧_第33张图片
快速排查方法:

ls -alh /etc/cron*
sudo ls -l  /var/spool/cron/crontabs/

7、劫持环境变量提权

此部分参见:《Linux环境变量提权》、《在Linux中使用环境变量进行提权》,本章节未完待续。

8、利用通配符->提权

此部分参见:《来自上古的提权技术-通配符注入》、《利用通配符进行Linux本地提权》,本章节未完待续。

9、其他潜在提权路径

0x00 查找敏感文件提权

有时候通过查找服务器上的 Web 配置文件,可以发现数据库的连接账户和密码。登录数据库后,通过收集数据库中存储的用户密码,并且管理员如果存在密码复用的情况,即可完成提权。

0x01 通过跳板用户提权

有时候我们尝试了所有的方法,也无法直接提权到 root 权限,此时可以考虑先提权到其他用户,再通过其他用户的权限提权到 root 权限,而这个中间用户就被我们称为 —— 跳板用户。

0x02 通过历史记录提权

通过 historycat ~/.bash_history 命令当前用户使用过的历史命令,里面可能存在有用的提权信息,比如有的管理员为了方便登陆 mysql 或其他软件时,不经意间加上参数-p,从而将密码暴露出来,或者一些 .sh 脚本连接 mysql、 等,查看对应的配置文件即可拿到账号密码。
浅析Linux系统常规提权手段的原理与技巧_第34张图片

10、内核cve漏洞提权

Linux 内核漏洞可能会造成 Linux 系统崩溃、宕机、权限提升等,历史上存在诸多 Linux 内核相关的 CVE 提权漏洞,在上述常规配置错误的方法都无法成功提权时,可以考虑使用内核漏洞来提权。Github 上有不少的 Linux 本地提权漏洞汇总资源:Linux本地提权漏洞。

常见的 Linux 权限提升漏洞辅助工具:linux-exploit-suggester,它基于操作系统的内核版本号(程序会执行 “uname -r” 命令来获取 Linux 操作系统发行版本),返回一个包含了适用 exploits 的提示列表。
浅析Linux系统常规提权手段的原理与技巧_第35张图片
此部分关于通过内核 CVE 漏洞或 Linux 系统组件漏洞造成提权的漏洞原理、自动化检测,后面会单独学习、记录,此处仅简单记录。

总结

本文主要总结了 Linux 系统一些常见的错误配置导致权限提升的路径,这期间的实操过程也让自己进一步理解了 Linux 系统诸多特性的工作原理。作为安全人员,应当熟练掌握 Linux 的基础特性才能更好地挖掘潜在风险漏洞,而作为运维或开发人员,应当有意识地去避免因自身错误配置导致服务器存在安全风险。

最后,附上一些 Linux 系统提权漏洞信息收集常用的命令:

#以下命令用于查看用户和群组信息
cat /etc/passwd     #列出系统上的所有用户
cat /etc/group      #列出系统上的所有组
grep -v -E "^#" /etc/passwd | awk -F: '$3 == 0 { print $1}'  列出所有的超级用户账户
whoami              #查看当前用户
w                   #谁目前已登录,他们正在做什么
last                #最后登录用户的列表
lastlog             #所有用户上次登录的信息
lastlog –u %username%  #有关指定用户上次登录的信息

#以下命令用于查看系统信息(可用于内核提权)
uname -a    #打印所有可用的系统信息
uname -r    #内核版本
uname -n    #系统主机名。
uname -m    #查看系统内核架构(64位/32位)
hostname    #系统主机名
cat /proc/version    #内核信息
cat /etc/*-release   #分发信息
cat /etc/issue       #分发信息
cat /proc/cpuinfo    #CPU信息
cat /etc/lsb-release    # Debian 
cat /etc/redhat-release # Redhat

#定时任务提权检查
crontab -l          #枚举定时任务
ls -alh /etc/cron*  #列举查看定时任务权限

#以下命令用于查询具备 suid 特殊权限的文件
find / -perm -4000 2> /dev/null
find / -perm -u=s -type f 2>/dev/null

# sudo滥用提权检查
sudo -l  #查询当前用户可以使用 sudo 运行什么命令以及以哪个用户身份运行 
more /etc/sudoers | grep -v "^#\|^$" | grep "ALL=(ALL)"  # 查看拥有sudo权限的用户

# 检查用户登录认证文件的权限
ls -l /etc/passwd
ls -l /etc/shadow

以上关于配置错误导致提权的问题,如果对 Linux 系统不熟悉的话手动找基本是找不到的,所以也可以现成利用工具去查找:unix-privesc-check 或 linPEAS,此部分自动化检测的知识,后面会连同 CVE 提权漏洞探测、利用一块单独展开学习。

你可能感兴趣的:(渗透测试,Linux提权)