Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
codeql-sample-polkit — polkit CVE-2021-4034를 codeql로 탐색하는 모든 단계 | Kitploit
도구/GitHubGitHub/hohn/codeql-sample-polkit
Static AnalysisVulnerability AnalysisCode AnalysisPapers & ResearchLearning & Education
GitHubhohn/codeql-sample-polkit

codeql-sample-polkit

polkit CVE-2021-4034를 codeql로 탐색하는 모든 단계

저장소 보기
24년 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

-- 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 범위 분석 라이브러리로 살펴볼 수 있습니다.

polkit/src/programs/pkexec.c의 pkexec의 main() 함수는 다음과 같은 구조를 가집니다: #+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와 관련된 표현식의 rhs / lhs로 제한.

확인할 버전:

  • 2009년 이후의 모든 Polkit 버전이 취약합니다; 첫 버전은 2009년 5월 (커밋 c8c3d83, "Add a pkexec(1) command").

  • /a/ 데이터베이스를 [[https://lgtm.com/projects/g/freedesktop/polkit/ci/#ql][lgtm에서]] 얻을 수 있으며, 현재 <2022-02-11 금> 버전은 =...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 DB 구축 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은 polkit이 아닌 PolicyKit을 사용합니다.
    • Ubuntu:
      • 18.04에도 mozjs78이 없습니다 (mozjs52만 있음)
      • 22.04에는 mozjs78이 있습니다

Ubuntu 22.04는 하드웨어, VM (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
 # /usr/local/bin에 이전 meson 설치
 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
 #     등.

 # ---------------------------------
 # codeql 설정 -- 여전히 root

 # 가져오기 -- codeql cli 및 라이브러리 검색 및 추출
 # 사용법: grab 버전 url 접두사
 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"
     # lib 가져오기
     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용 codeql 데이터베이스 빌드 (여전히 mozjs-78 사용)
 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

db를 호스트의 영구 위치에 복사 #+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][문서]] 참조

#+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][Build polkit and codeql db]]에서 수행한 대로 빌드합니다.

다음에서는 데이터베이스에 대해 다음 디렉토리 구조를 가정합니다: #+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 > 0=으로 =n=을 사용하는 모든 위치를 올바르게 식별합니다.

이 쿼리는 취약한 버전의 코드인 =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

도구 다운로드