关联漏洞
标题:
polkit 缓冲区错误漏洞
(CVE-2021-4034)
描述:polkit是一个在类 Unix操作系统中控制系统范围权限的组件。通过定义和审核权限规则,实现不同优先级进程间的通讯。 polkit 的 pkexec application存在缓冲区错误漏洞,攻击者可利用该漏洞通过精心设计环境变量诱导pkexec执行任意代码。成功执行攻击后,如果目标计算机上没有权限的用户拥有管理权限,攻击可能会导致本地权限升级。
描述
Exploit for the PwnKit Vulnerability
介绍
# CVE-2021-4034 Exploit
Root exploit for the PwnKit vulnerability. Check out the original report
[here](https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt).
*Use this exploit with an express permission of the target system's owners.*
## Building
No dependencies needed besides libc. Just run `make`.
## Running
Running without options will execute the exploit:
```
[linux@linux ~]$ ./exploit
-----------------------------------------------------------------------------
__\ / __ __ _ __ _ __ | \ / _ ___
/ V |_ --- _)/ \ _)/| ---|_|/ \__)|_| | V |_) _/|_|
\__ |__ /__\_//__ | |\_/__) | | | \/__| |
-----------------------------------------------------------------------------
sh-5.1# whoami
root
sh-5.1#
```
You can customize the path to `pkexec` as well as the "from" charset:
```
[linux@linux ~]$ ./exploit -h
...
./exploit [-c] [-h] [-f from_charset] [-p /path/to/pkexec]
-----------------------------------------------------------------------------
-c Just teardown - don't exploit
-p <path> Path to pkexec (default: "/usr/bin/pkexec")
-f <from_charset> Custom "from" charset (default: "UTF-8")
-h Display this message
```
## What's the deal with `GIO_USE_VFS`?!
I saw a few people on social media ask why do some exploits fail if the
`GIO_USE_VFS=` is not defined? Why do they work with the older versions?
### The culprit
Commt `daf3d5c2d15466a267221fcb099c59c870098e03` in polkit is the culprit.
Here's the relevant part of the 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)
{
```
Versions prior to this commit are exploitable without the need to define the
`GIO_USE_VFS` variable. The versions after - are not exploitable unless this variable is defined.
The purpose of the commit is actually a red herring. It's not what the variable
means, it's *how its presence affects the program environment*. For the truth we must look to libc.
### Looking in libc
The environment of a process in libc is represented by an array of `char *`s,
pointed to by this global variable:
```c
char **environ;
```
`environ` lives on the heap and is occasionally relocated. You might
already know where this is going. Check out this code snippet from
[setenv.c](https://code.woboq.org/userspace/glibc/stdlib/setenv.c.html):
```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;
// ... skipping
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 *));
// ... skipping
last_environ = __environ = new_environ;
}
```
`__add_to_environ()` is called by both `setenv(3)` and `putenv(3)` to accomplish
what they promise - set an environment variable. If the environment variable in
question is **not** defined, `environ` has to be reallocated to accomodate
a new entry (a pointer to the new environment `key=value` pair). If it is
defined, the size of the `environ` array has not changed and thus there is no
reason for reallocation. For brevity I've omitted that part of the code - I
encourage you to check it out.
### Tying it all together
Now let's come back to the exploit. If you've gotten this far, you probably
already know the methodology behind this exploit (if not please check out the
[original report](https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt)).
We are trying to sneak in an environment variable by passing an empty program
arguments (`argv`) to `pkexec`. When `argc` is truly empty (not even a program
name), the environment variables, which are adjacent, clash with the arguments.
We abuse this behavior to force `pkexec` to write a canonical path of a
target executable into the environment. However, before we get to this part of the
code this happens:
```c
setenv ("GIO_USE_VFS", "local", 1);
```
If this variable is not present in the environment `environ` will be
reallocated, thus never clashing with `argv`. As a result, the out-of-bounds
write will not be affecting the program's environment, causing the
exploit to fail.
文件快照
[4.0K] /data/pocs/5d31ae38d897532776dcc9768a6bce724f71d869
├── [4.0K] exploit.c
├── [ 211] lib.c
├── [ 304] Makefile
└── [4.8K] README.md
0 directories, 4 files
备注
1. 建议优先通过来源进行访问。
2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。