Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
codeql-sample-polkit — 探索 polkit CVE-2021-4034 的所有阶段,使用 codeql | Kitploit
工具/GitHubGitHub/hohn/codeql-sample-polkit
静态分析漏洞分析代码分析论文与研究学习与教育
GitHubhohn/codeql-sample-polkit

codeql-sample-polkit

探索 polkit CVE-2021-4034 的所有阶段,使用 codeql

查看仓库
254年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

-- coding: utf-8 --

  • polkit pkexec 漏洞

** 概述 本仓库使用 CodeQL 研究 polkit pkexec 漏洞。 包含

  • 构建数据库的说明
  • 构建好的数据库
  • 一系列用于演示如何发现该漏洞的查询

已完成事项:

  • polkit 源码 / 数据库构建
  • 针对易受攻击源码的 codeql 查询
  • CFG 图示

待办事项:

  • 增强 codeql 查询以同时处理已修补的源码
  • 命令行说明

** 漏洞详情 Polkit pkexec 漏洞 [[https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-2021-4034][(CVE-2021-4034)]] 源于与 argv 相关的数组越界错误,并在此基础上进一步利用。越界部分的问题 我们可以通过 codeql 范围分析库来研究。

pkexec 的 main() 函数位于 polkit/src/programs/pkexec.c,其结构如下 #+begin_src text 435 main (int argc, char *argv[]) 436 { ... 534 for (n = 1; n < (guint) argc; n++) 535 { ... 568 } ... 610 path = g_strdup (argv[n]); ... #+end_src

主要思路:

  • 对 argc 使用简单的范围分析。
  • 将表达式的右值/左值限制为与 argc 相关的部分。

需要检查的版本:

  • 自 2009 年起的所有 Polkit 版本均存在漏洞;第一个版本发布于 2009 年 5 月(提交 c8c3d83,“Add a pkexec(1) command”)。

  • 我们可以从 [[https://lgtm.com/projects/g/freedesktop/polkit/ci/#ql][lgtm]] 获取 /a/ 数据库,当前版本 <2022-02-11 Fri> 为 =...srcVersion_a6bedfd...= 但该版本已经包含了 polkit 补丁: #+BEGIN_SRC text commit a6bedfd09b7bba753de7a107dc471da0db801858 (origin/master, origin/HEAD, master) Author: Xi Ruoyao [email protected] Date: Thu Jan 27 10:16:32 2022 +0000

    root@kitploit:~
      jsauthority: port to mozjs-91
    

    commit a2bf5c9c83b6ae46cbd5c779d3055bff81ded683 Author: Jan Rybar [email protected] Date: Tue Jan 25 17:21:46 2022 +0000

    root@kitploit:~
      pkexec: local privilege escalation (CVE-2021-4034)
    

    #+END_SRC 我们可以看到问题已被修复: #+BEGIN_SRC text commit a2bf5c9c83b6ae46cbd5c779d3055bff81ded683 Author: Jan Rybar [email protected] Date: Tue Jan 25 17:21:46 2022 +0000

    root@kitploit:~
      pkexec: local privilege escalation (CVE-2021-4034)
    

    diff --git a/src/programs/pkcheck.c b/src/programs/pkcheck.c index f1bb4e1..768525c 100644 --- a/src/programs/pkcheck.c +++ b/src/programs/pkcheck.c @@ -363,6 +363,11 @@ main (int argc, char *argv[]) local_agent_handle = NULL; ret = 126;

    • if (argc < 1)
    • {
    • root@kitploit:~
       exit(126);
      
    • }
    • /* Disable remote file access from GIO. */ setenv ("GIO_USE_VFS", "local", 1); #+END_SRC
  • 因此我们需要 [[https://gitlab.freedesktop.org/polkit/polkit.git][源代码]] 并自行构建数据库,一个为补丁前版本,一个为补丁后版本。

下一节将介绍使用 Docker 容器的构建步骤。

** 构建 polkit 和 CodeQL 数据库 在获取 codeql 数据库之前,我们需要先完成 polkit 的构建环境设置。

构建的操作系统选项:

  • macOS 值得一试,但很快就会遇到麻烦。使用 =brew= 获取 依赖项在一定程度内可行,但 =mozjs-78= 依赖项是 spidermonkey 的特定版本,构建 /该/ 版本并不现实。 #+BEGIN_SRC sh # autoconf... 在 mac 上有点棘手 brew install autoconf automake libtool gtk-doc export PATH="/usr/local/opt/libtool/libexec/gnubin:$PATH" ./autogen.sh

    root@kitploit:~
    # 使用 meson?
    brew install meson ninja intltool glib gobject-introspection 
    

    #+END_SRC

  • Linux 是 polkit 的原生环境,但选择哪个发行版?mozjs-78 依赖项是 spidermonkey 的特定版本;此外,并非所有发行版都使用 polkit:

    • Debian 使用 PolicyKit,而非 polkit。
    • Ubuntu:
      • 18.04 也缺少 mozjs78(仅有 mozjs52)
      • 22.04 包含 mozjs78

Ubuntu 22.04 可以通过多种方式运行,包括物理机、虚拟机(vmware、 virtualbox、multipass 等),或另一台主机上的 docker 容器。对于此问题,我们可以使用 Docker 容器,并同时包含 codeql 命令行工具。

容器的定义位于 ./Dockerfiles 中,以下是构建 序列: #+BEGIN_SRC shell # 用于设置 qlbuild 容器的基础镜像 docker pull ubuntu:jammy docker images docker run --cpus 4 -m 8GB -ti ubuntu:jammy

root@kitploit:~
 # 待定制的镜像
 docker build -t qlbuild .

#+END_SRC 注意:在 Windows 和 Mac 上使用 docker desktop 时,内存和 CPU 限制必须 在那里调高。设置完成后,容器运行序列很简单 #+BEGIN_SRC sh # 以守护进程方式运行,以便断开连接时仍保持运行。 docker run -d -p 127.0.0.1:2020:22 --cpus 8 -m 16GB qlbuild

root@kitploit:~
 # 然后连接
 ssh -p 2020 test@localhost

#+END_SRC

在 Ubuntu 22.04 上构建 #+BEGIN_SRC sh # --------------------------------- # 系统设置/安装,以 root 身份: echo "deb-src http://archive.ubuntu.com/ubuntu/ jammy main restricted" >> /etc/apt/sources.list apt-get update apt-get install -y zile build-essential git cmake
meson ninja-build
libmozjs-78-0 libmozjs-78-dev
libdbus-1-3 libdbus-1-dev apt-get build-dep -y policykit-1 apt install unzip

root@kitploit:~
 # polkit 版本 a2bf5c9c 还需要一些额外的包
 apt install duktape duktape-dev
 # 将旧版 meson 安装到 /usr/local/bin
 pip3 install meson==0.60.3
 # 或者获取源码并使用:
 #     wget https://github.com/mesonbuild/meson/archive/refs/tags/0.60.3.tar.gz
 #     tar zxf 0.60.3.tar.gz
 #     etc.

 # ---------------------------------
 # codeql 设置 -- 仍为 root

 # 获取 -- 下载并解压 codeql cli 和库
 # 用法:grab 版本 平台 前缀
 grab() {
     version=$1; shift
     platform=$1; shift
     prefix=$1; shift
     mkdir -p $prefix/codeql-$version &&
         cd $prefix/codeql-$version || return

     # 获取 cli
     wget "https://github.com/github/codeql-cli-binaries/releases/download/$version/codeql-$platform.zip"
     # 获取库
     wget "https://github.com/github/codeql/archive/refs/tags/codeql-cli/$version.zip"
     # 修复属性
     if [ `uname` = Darwin ] ; then
         xattr -c *.zip
     fi
     # 解压
     unzip -q codeql-$platform.zip
     unzip -q $version.zip
     # 重命名库目录以供 VS Code 使用
     mv codeql-codeql-cli-$version/ ql
     # 删除压缩包
     rm codeql-$platform.zip
     rm $version.zip
 }    

 grab v2.7.6 linux64 /opt
 grab v2.6.3 linux64 /opt

 # ---------------------------------
 # 以用户 test 身份:
 # 获取 polkit 源码
 cd /tmp && git clone https://gitlab.freedesktop.org/polkit/polkit.git

 # 构建版本 0.119
 cd /tmp/polkit
 git checkout 0.119 
 git clean -fxd

 meson setup builddir
 meson compile -C builddir

 find builddir -name pkexec -ls
 : 139269     76 -rwxr-xr-x   1 test     root        76696 Feb 12 03:06 builddir/src/programs/pkexec

 # ---------------------------------
 # 为版本 0.119 构建 codeql 数据库
 cd /tmp/polkit
 git checkout 0.119 
 git clean -fxd

 # 照常运行配置步骤,不使用 codeql
 cd /tmp/polkit && rm -fR builddir
 meson setup builddir

 # 在 codeql 下运行构建步骤
 export CODEQL=/opt/codeql-v2.7.6/codeql/codeql
 $CODEQL --version

 $CODEQL database create  --language=cpp -s . -j 8 -v \
         polkit-0.119.db \
         --command='meson compile -C builddir'

 # 等待
 # TRAP import complete (10.2s).
 # Successfully created database at /tmp/polkit/polkit-0.119.db.

 # 快速检查以确保 pkexec 已被识别:
 unzip -v polkit-0.119.db/src.zip |grep pkexec
 : 29713  Defl:N     8477  72% 2022-02-14 20:12 bb39f235  tmp/polkit/src/programs/pkexec.c

 # ---------------------------------
 # 为版本 a2bf5c9c(已修补版本,仍使用 mozjs-78)构建 codeql 数据库
 cd /tmp/polkit
 git checkout a2bf5c9c 
 git clean -fxd

 # 照常运行配置步骤,不使用 codeql
 cd /tmp/polkit && rm -fR builddir
 /usr/local/bin/meson setup builddir

 # 使用 meson 0.61 时,配置会遇到错误
 #   actions/meson.build:3:5: ERROR: Function does not take positional arguments.
 # 快速搜索可找到
 #   https://lore.kernel.org/all/20220111222135.693a88f2@windsurf/T/
 # 进而找到
 #   [1/1] package/gobject-introspection: bump to version 1.70.0

 # 在 codeql 下运行构建步骤
 export CODEQL=/opt/codeql-v2.7.6/codeql/codeql
 $CODEQL --version

 $CODEQL database create  --language=cpp -s . -j 8 -v \
         polkit-a2bf5c9c.db \
         --command='/usr/local/bin/meson compile -C builddir'

 # 等待
 # TRAP import complete (7.2s).
 # Successfully created database at /tmp/polkit/polkit-a2bf5c9c.db.

 # 快速检查以确保 pkexec 已被识别:
 unzip -v polkit-a2bf5c9c.db/src.zip |grep pkexec
 :   30136  Defl:N     8647  71% 2022-02-14 21:27 6af18604  tmp/polkit/src/programs/pkexec.c

#+END_SRC

将数据库复制到主机上的永久位置 #+BEGIN_SRC sh # 从容器中复制 mkdir -p ~/local/polkit && cd ~/local/polkit scp -rq -P 2020 test@localhost:/tmp/polkit/polkit-0.119.db . scp -rq -P 2020 test@localhost:/tmp/polkit/polkit-a2bf5c9c.db .

root@kitploit:~
 # 保留原始文件
 zip -rq polkit-0.119.zip polkit-0.119.db 
 zip -rq polkit-a2bf5c9c.zip polkit-a2bf5c9c.db

#+END_SRC

TODO

推送容器以供复用,参见 [[https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#pushing-container-images][documentation]]

#+BEGIN_SRC sh

docker login ghcr.io -u USERNAME

docker push ghcr.io/OWNER/IMAGE_NAME:latest

docker pull ghcr.io/OWNER/IMAGE_NAME

#+END_SRC

接下来,进行查询开发环境的设置。

** 查询开发环境设置 查询可以通过 codeql cli 单独探索,或使用 codeql cli + VS Code 插件。对于这两种情况,都需要安装 cli(参见上面的 =grab()= 函数), 并从 [[./db]] 解压数据库,或按照 [[*Build polkit and codeql db][构建 polkit 和 codeql 数据库]] 中的方法自行构建。

下面,我们假设数据库采用以下目录结构: #+BEGIN_SRC text . ├── polkit-0.119.db │   ├── codeql-database.yml │   ├── db-cpp │   ├── log │   └── src.zip ├── polkit-0.119.zip ├── polkit-a2bf5c9c.db │   ├── codeql-database.yml │   ├── db-cpp │   ├── log │   └── src.zip └── polkit-a2bf5c9c.zip #+END_SRC

** 查询 查询在 [[./argv-out-of-bounds-*.ql]] 中逐步开发。

[[./argv-out-of-bounds-0.ql]] 中的第一步使用 AST 和变量 引用将结果缩小到问题的已知部分,如下所示。

#+BEGIN_SRC text declaration | 435 main (int argc, char *argv[]) | 436 { | ... init other var; | 534 for (n = 1; compare to argc | n < (guint) argc; update other var | n++) | 535 { | ... | 568 } | ... indexed read | 610 path = g_strdup (argv[n]); | ... | 629 if (path[0] != '/') | 630 { | ... | 632 s = g_find_program_in_path (path); | ... indexed write | 639 argv[n] = path = s; | 640 } #+END_SRC

值的探索从 [[./argv-out-of-bounds-1.ql]] 开始,尝试 通过以下方式使用 =SimpleRangeAnalysis= 库 #+begin_src javascript lowerBound(cmp.getLeftOperand().getFullyConverted()), "left lower bound", lowerBound(cmp.getRightOperand().getFullyConverted()), "right lower bound" #+end_src 这些边界对于类型而言是正确的,但过于宽泛——它们包含了 迭代的可能结果。我们只对静态确定的初始边界感兴趣, 即任何迭代发生之前的边界。

换句话说,这不是一个通用的数据流问题;我们只想检查 特定执行路径上的初始值传播。=for= 循环 使这个问题复杂化,循环内的操作也是如此。

我们真正想要的是查看完全绕过循环的执行路径。这 在 [[./argv-out-of-bounds-1.ql]] 的后半部分通过使用 =SsaDefinition= 完成。

查询 [[./argv-out-of-bounds-2.ql]] 清理了 [[./argv-out-of-bounds-1.ql]] 中的探索,并正确识别了所有使用 =n= 且已知索引值 =n > 0= 的位置。

此查询在易受攻击的代码版本 =polkit-0.119.db= 上报告结果。 接下来,需要对其进行检查和增强,使其在已修补版本 =polkit-a2bf5c9c.db= 上不报告任何结果。

TODO

** 从命令行运行查询

#+BEGIN_SRC sh

# 对数据库运行查询,将结果保存到数据库目录的 results/

# 子目录中,以供进一步处理。

codeql database run-queries -j8 --ram=20000 -- $DB $SRCDIR/example.ql

# 获取可用结果的一般信息

codeql bqrs info --format=text -- $DB/results/cpp-sample/example.bqrs

# 使用 bqrs decode 格式化结果。

codeql bqrs decode --output=cpp-simple.csv \

--format=csv --entities=all -- \

$DB/results/cpp-sample/example.bqrs

#+END_SRC

下载工具