Sudo
默认情况下,sudo 命令允许您以 root 权限运行程序。在某些情况下,系统管理员可能需要赋予普通用户一定的权限灵活性。例如,初级 SOC 分析师可能需要定期使用 Nmap ,但无法获得完全的 root 访问权限。在这种情况下,系统管理员可以允许该用户仅以 root 权限运行 Nmap ,同时在系统的其余部分保持其常规权限级别。
任何用户都可以使用 sudo -l
命令检查其当前与 root 权限相关的情况。
https://gtfobins.github.io/ 是一个有价值的资源,它提供了有关如何使用您可能拥有 sudo 权限的任何程序的信息。
利用应用程序功能
某些应用程序在此上下文中不会存在已知的漏洞。您可能看到的此类应用程序是 Apache2 服务器。
在这种情况下,我们可以利用应用程序的某个功能,通过“黑客”手段泄露信息。如下所示,Apache2 有一个选项支持加载备用配置文件( -f
:指定备用的 ServerConfigFile)。
使用此选项加载 /etc/shadow
文件将导致包含 /etc/shadow
文件第一行的错误消息。
利用 LD_PRELOAD
在某些系统上,您可能会看到 LD_PRELOAD 环境选项。
LD_PRELOAD 是一个允许任何程序使用共享库的函数。这篇博文将带您了解 LD_PRELOAD 的功能。如果启用了“env_keep”选项,我们可以生成一个共享库,该库将在程序运行之前加载并执行。请注意,如果实际用户 ID 与有效用户 ID 不同,LD_PRELOAD 选项将被忽略。
该权限提升向量的步骤可概括如下;
- 检查 LD_PRELOAD(使用 env_keep 选项)
- 编写一个简单的 C 代码,编译为共享对象(.so 扩展名)文件
- 使用 sudo 权限和指向我们的 .so 文件的 LD_PRELOAD 选项运行该程序
C 代码将简单地生成一个 root shell,可以按如下方式编写;
|
|
我们可以将此代码保存为 shell.c,并使用 gcc 将其编译为共享目标文件,使用以下参数;
|
|
现在,我们可以在启动任何用户可以使用 sudo 运行的程序时使用这个共享对象文件。在我们的例子中,Apache2、find,或者几乎所有可以使用 sudo 运行的程序都可以使用。
我们需要通过指定 LD_PRELOAD 选项来运行程序,如下所示;
|
|
这将导致产生具有 root 权限的 shell。
SUID
Linux 的大部分权限控制依赖于控制用户与文件的交互。这通过权限来实现。现在,您知道文件可以具有读、写和执行权限。这些权限会根据用户的权限级别授予用户。SUID(设置用户标识)和 SGID(设置组标识)会改变权限级别。SUID 和 SGID 分别允许文件以文件所有者或组所有者的权限级别执行。
您会注意到这些文件有一个“s”位设置,显示其特殊权限级别。
find / -type f -perm -04000 -ls 2>/dev/null
将列出设置了 SUID 或 SGID 位的文件。
一个好的做法是将此列表中的可执行文件与 GTFOBins ( https://gtfobins.github.io ) 进行比较。点击 SUID 按钮将过滤掉已知在设置了 SUID 位的情况下可被利用的二进制文件(您也可以使用此链接获取预过滤列表 https://gtfobins.github.io/#+suid )。
上面的列表显示 nano 已设置 SUID 位。不幸的是,GTFObins 并没有给我们提供轻松的攻击机会。在现实生活中的提权场景中,我们需要找到一些中间步骤,以便利用我们掌握的任何微小的发现。
为 nano 文本编辑器设置的 SUID 位允许我们使用文件所有者的权限创建、编辑和读取文件。nano 的所有者是 root,这意味着我们可以以比当前用户更高的权限级别读取和编辑文件。目前,我们有两个基本的提权选项:读取 /etc/shadow
文件或将用户添加到 /etc/passwd
。
以下是使用这两个向量的简单步骤。
读取 /etc/shadow
文件
我们看到 nano 文本编辑器通过运行 find / -type f -perm -04000 -ls 2>/dev/null
命令设置了 SUID 位。
nano /etc/shadow
将打印 /etc/shadow
文件的内容。现在我们可以使用 unshadow 工具创建一个可被 John the Ripper 破解的文件。为此,unshadow 需要 /etc/shadow
和 /etc/passwd
文件。
unshadow工具的用法如下所示;
|
|
只要有正确的单词表和一点运气, John the Ripper 就能以明文形式返回一个或多个密码。
另一个选项是添加一个具有 root 权限的新用户。这将帮助我们规避繁琐的密码破解过程。以下是一个简单的方法:
我们需要获取新用户密码的哈希值。使用 Kali Linux 上的 openssl 工具可以快速完成此操作。
然后我们将此密码与用户名一起添加到 /etc/passwd
文件中。
一旦添加了我们的用户(请注意如何使用 root:/bin/bash
来提供 root shell),我们将需要切换到该用户,并且希望拥有 root 权限。
Capabilities
系统管理员可以使用另一种方法来提升进程或二进制文件的权限级别,即“功能”。功能有助于在更精细的层面上管理权限。例如,如果 SOC 分析师需要使用一个需要启动套接字连接的工具,那么普通用户将无法执行此操作。如果系统管理员不想授予此用户更高的权限,他们可以更改二进制文件的功能。这样,二进制文件就可以完成其任务,而无需更高权限的用户。
功能手册页提供了有关其用法和选项的详细信息。
我们可以使用 getcap
工具列出已启用的功能。
当以非特权用户身份运行时, getcap -r /
将生成大量错误,因此将错误消息重定向到 /dev/null 是一种很好的做法。
请注意,vim 及其副本均未设置 SUID 位。因此,在枚举文件查找 SUID 时,无法发现此权限提升向量。
GTFObins 有一个很好的二进制文件列表,如果我们发现任何设置功能,就可以利用这些二进制文件来提升权限。
我们注意到 vim 可以与以下命令和有效载荷一起使用:
这将启动一个 root shell,如下所示;
Cron Job
Cron Job用于在特定时间运行脚本或二进制文件。默认情况下,它们以其所有者的权限运行,而不是当前用户的权限。虽然正确配置的 Cron 作业本身并不会受到攻击,但在某些情况下,它们可能会提供提权途径。
这个想法很简单;如果有一个以 root 权限运行的计划任务,并且我们可以更改将要运行的脚本,那么我们的脚本将以 root 权限运行。
Cron job配置存储为 crontab(cron 表),以查看任务下次运行的时间和日期。
系统中的每个用户都有自己的 crontab 文件,无论是否登录都可以运行特定的任务。正如你所料,我们的目标是找到一个由 root 设置的 cron job,并让它运行我们的脚本(最好是一个 shell)。
任何用户都可以读取 /etc/crontab
下保存系统范围 cron job的文件
虽然 CTF 机器可以每分钟或每 5 分钟运行一次 cron job,但在渗透测试中,您更经常会看到每天、每周或每月运行的任务。
您可以看到, backup.sh
脚本已配置为每分钟运行一次。该文件的内容是一个简单的脚本,用于创建 prices.xls 文件的备份。
由于我们当前的用户可以访问此脚本,我们可以轻松地修改它以创建反向 shell,希望具有 root 权限。
该脚本将使用目标系统上可用的工具来启动反向 shell。
需要注意两点;
- 命令语法将根据可用的工具而有所不同。(例如,
nc
可能不支持您可能在其他情况下看到的-e
选项) - 我们应该始终优先启动反向 shell,因为我们不想在实际渗透测试过程中损害系统完整性。
该文件应如下所示;
我们现在将在攻击机器上运行一个监听器来接收传入的连接。
Crontab 始终值得检查,因为它有时可能导致简单的权限提升向量。以下情况在网络安全成熟度不高的公司中并不少见:
- 系统管理员需要定期运行脚本。
- 他们创建了一个 cron job来执行此操作
- 过了一段时间,脚本变得毫无用处,他们就删除了它
- 他们没有清理相关的 cron job
此变更管理问题导致可能利用 cron job进行攻击。
上面的例子显示了类似的情况,其中 antivirus.sh 脚本被删除,但 cron job仍然存在。
如果未定义脚本的完整路径(例如在 backup.sh 脚本中已定义),cron 将引用/etc/crontab 文件中 PATH 变量下列出的路径。在这种情况下,我们应该能够在用户主文件夹下创建一个名为“antivirus.sh”的脚本,并由 cron job运行它。
目标系统上的文件应该看起来很熟悉:
传入的反向 shell 连接具有 root 权限:
如果你偶然发现一个现有的脚本或任务被附加到 cron job中,那么花时间去了解该脚本的功能以及在上下文中如何使用任何工具总是值得的。例如,tar、7z、rsync 等工具可以利用它们的通配符功能来利用它们。
PATH
如果路径中存在用户拥有写入权限的文件夹,则可能会劫持应用程序来运行脚本 。Linux 中的 PATH 是一个环境变量,它指示操作系统在哪里搜索可执行文件。对于任何未内置于 Shell 或未使用绝对路径定义的命令, Linux 都会开始在 PATH 下定义的文件夹中搜索。(PATH 是我们这里讨论的环境变量,path 是文件的位置)。
通常,PATH 看起来像这样:
为了演示目的我们将使用以下脚本:
该脚本尝试启动名为“ thm ”的系统二进制文件,但该示例可以轻松地用任何二进制文件复制。
我们将其编译为可执行文件并设置 SUID 位。
我们的用户现在可以访问设置了 SUID 位的“路径”脚本。
一旦执行,“path”将在 PATH 下列出的文件夹中查找名为“ thm ”的可执行文件。
如果 PATH 下列出了任何可写文件夹,我们可以在该目录下创建一个名为 thm 的二进制文件,并让“path”脚本运行它。由于设置了 SUID 位,该二进制文件将以 root 权限运行。
可以使用“ find / -writable 2>/dev/null
”命令简单搜索可写文件夹。此命令的输出可以通过简单的剪切和排序序列进行清理。
一些 CTF 场景可以呈现不同的文件夹,但常规系统会输出类似我们上面看到的内容。
将其与 PATH 进行比较将帮助我们找到可以使用的文件夹。
我们在 /usr 下看到许多文件夹,因此可以更轻松地再次运行可写文件夹搜索以覆盖子文件夹。
另一种方法是使用下面的命令。
|
|
我们添加了“grep -v proc”来摆脱与正在运行的进程相关的许多结果。
不幸的是,/usr 下的子文件夹不可写
更容易写入的文件夹可能是 /tmp。此时,由于 PATH 中没有 /tmp,所以我们需要添加它。如下所示,“ export PATH=/tmp:$PATH
”命令可以完成此操作。
此时,路径脚本还将在 /tmp 文件夹下查找名为“ thm ”的可执行文件。
通过将 /bin/bash 复制为 /tmp 文件夹下的“ thm ”,创建此命令相当容易。
我们已经赋予了 /bin/bash 副本可执行权限,请注意,此时它将以我们的用户权限运行。在此上下文中,权限提升之所以成为可能,是因为路径脚本以 root 权限运行。