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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2021-3156-Heap-Based-Buffer-Overflow-in-Sudo-Baron-Samedit- — CVE-2021-3156の技術分析とエクスプロイト開発。Sudoのヒープベースのバッファオーバーフローで、主要なLinuxディストリビューションでのローカル権限昇格のための3つの動作するエクスプロイトが含まれます。 | Kitploit
ツール/GitHubGitHub/sornphut/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit-
特権昇格脆弱性分析エクスプロイトペネトレーションテスト論文と研究学習と教育バイナリエクスプロイト
GitHubsornphut/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit-

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2021-3156-Heap-Based-Buffer-Overflow-in-Sudo-Baron-Samedit-

CVE-2021-3156の技術分析とエクスプロイト開発。Sudoのヒープベースのバッファオーバーフローで、主要なLinuxディストリビューションでのローカル権限昇格のための3つの動作するエクスプロイトが含まれます。

リポジトリを見る
131年前未レビュー

Qualys セキュリティアドバイザリ

Baron Samedit: Sudo におけるヒープベースのバッファオーバーフロー (CVE-2021-3156)

======================================================================== 目次

概要 分析 悪用 謝辞 タイムライン

======================================================================== 概要

私たちは Sudo にヒープベースのバッファオーバーフローを発見しました (https://www.sudo.ws/)。この脆弱性は次のとおりです:

  • 認証なしで、任意のローカルユーザー(通常ユーザーおよびシステムユーザー、 sudoers と非 sudoers)によって悪用可能です(つまり、攻撃者は ユーザーのパスワードを知る必要はありません);

  • 2011年7月(コミット 8255ed69)に導入され、デフォルト設定において、 すべてのレガシーバージョン 1.8.2 から 1.8.31p2 と、 すべての安定版 1.9.0 から 1.9.5p1 に影響します。

私たちはこの脆弱性に対する3つの異なるエクスプロイトを開発し、 Ubuntu 20.04 (Sudo 1.8.31)、Debian 10 (Sudo 1.8.27)、 Fedora 33 (Sudo 1.9.2) で完全な root 権限を取得しました。他のオペレーティングシステムや ディストリビューションでも悪用可能である可能性が高いです。

======================================================================== 分析

Sudo が "shell" モード(shell -c command)でコマンドを実行するために実行される場合:

  • -s オプション(Sudo の MODE_SHELL フラグを設定する)による方法;

  • または -i オプション(Sudo の MODE_SHELL と MODE_LOGIN_SHELL フラグを設定する)による方法;

その場合、Sudo の main() の先頭で parse_args() は argv を書き換えます(行 609-617)。 すべてのコマンドライン引数を連結し(行 587-595)、すべてのメタ文字をバックスラッシュでエスケープします(行 590-591):


571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { 572 char **av, *cmnd = NULL; 573 int ac = 1; ... 581 cmnd = dst = reallocarray(NULL, cmnd_size, 2); ... 587 for (av = argv; *av != NULL; av++) { 588 for (src = *av; src != '\0'; src++) { 589 / quote potential meta characters */ 590 if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$') 591 *dst++ = '\'; 592 *dst++ = *src; 593 } 594 dst++ = ' '; 595 } ... 600 ac += 2; / -c cmnd */ ... 603 av = reallocarray(NULL, ac + 1, sizeof(char *)); ... 609 av[0] = (char )user_details.shell; / plugin may override shell */ 610 if (cmnd != NULL) { 611 av[1] = "-c"; 612 av[2] = cmnd; 613 } 614 av[ac] = NULL; 615 616 argv = av; 617 argc = ac; 618 }

その後、sudoers_policy_main() 内の set_cmnd() は、コマンドライン引数を ヒープベースのバッファ "user_args" に連結し(行 864-871)、 メタ文字のエスケープを解除します(行 866-867)。これは "sudoers の マッチングとロギングのため" です:


819 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { ... 852 for (size = 0, av = NewArgv + 1; *av; av++) 853 size += strlen(*av) + 1; 854 if (size == 0 || (user_args = malloc(size)) == NULL) { ... 857 } 858 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { ... 864 for (to = user_args, av = NewArgv + 1; (from = *av); av++) { 865 while (*from) { 866 if (from[0] == '\' && !isspace((unsigned char)from[1])) 867 from++; 868 *to++ = *from++; 869 } 870 *to++ = ' '; 871 } ... 884 } ... 886 }

残念ながら、コマンドライン引数が単一のバックスラッシュ文字で終わる場合、次のようになります:

  • 行 866 では、"from[0]" はバックスラッシュ文字であり、"from[1]" は 引数のヌル終端文字です(つまり、スペース文字ではありません);

  • 行 867 では、"from" がインクリメントされ、ヌル終端文字を指します;

  • 行 868 では、ヌル終端文字が "user_args" バッファにコピーされ、 "from" が再度インクリメントされ、ヌル終端文字の後の最初の文字を指します (つまり、引数の境界外です);

  • 行 865-869 の "while" ループは、境界外の文字を読み取って "user_args" バッファにコピーします。

言い換えると、set_cmnd() は、ヒープベースのバッファオーバーフローに対して脆弱です。 "user_args" バッファにコピーされる境界外の文字が、 そのサイズ(行 852-853 で計算)に含まれていないためです。

しかし理論上は、コマンドライン引数が単一のバックスラッシュ文字で終わることはありません: MODE_SHELL または MODE_LOGIN_SHELL が設定されている場合(行 858、 これは脆弱なコードに到達するための必要条件)、MODE_SHELL が設定され(行 571)、 parse_args() はすでにバックスラッシュを含むすべてのメタ文字をエスケープしています (つまり、すべての単一バックスラッシュを2番目のバックスラッシュでエスケープしています)。

しかし実際には、set_cmnd() 内の脆弱なコードと parse_args() 内のエスケープコードは、 わずかに異なる条件で囲まれています:


819 if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { ... 858 if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {

一方:


571 if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) {

では、私たちの疑問は次のとおりです: MODE_SHELL と MODE_EDIT または MODE_CHECK のいずれかを設定し(脆弱なコードに到達するため)、 デフォルトの MODE_RUN を設定しない(エスケープコードを回避するため)ことは可能でしょうか?

答えは、どうやら「いいえ」のようです: MODE_EDIT(-e オプション、行 361)または MODE_CHECK(-l オプション、行 423 および 519)を設定すると、 parse_args() は "valid_flags" から MODE_SHELL を削除し(行 363 および 424)、 MODE_SHELL のような無効なフラグを指定するとエラーで終了します(行 532-533):


358 case 'e': ... 361 mode = MODE_EDIT; 362 sudo_settings[ARG_SUDOEDIT].value = "true"; 363 valid_flags = MODE_NONINTERACTIVE; 364 break; ... 416 case 'l': ... 423 mode = MODE_LIST; 424 valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST; 425 break; ... 518 if (argc > 0 && mode == MODE_LIST) 519 mode = MODE_CHECK; ... 532 if ((flags & valid_flags) != flags) 533 usage(1);

しかし、私たちは抜け穴を見つけました: "sudo" の代わりに "sudoedit" として Sudo を実行すると、 parse_args() は自動的に MODE_EDIT を設定しますが(行 270)、 "valid_flags" をリセットせず、"valid_flags" にはデフォルトで MODE_SHELL が含まれます(行 127 および 249):


127 #define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_SHELL) ... 249 int valid_flags = DEFAULT_VALID_FLAGS; ... 267 proglen = strlen(progname); 268 if (proglen > 4 && strcmp(progname + proglen - 4, "edit") == 0) { 269 progname = "sudoedit"; 270 mode = MODE_EDIT; 271 sudo_settings[ARG_SUDOEDIT].value = "true"; 272 }

したがって、"sudoedit -s" を実行すると、MODE_EDIT と MODE_SHELL の両方を設定し(ただし MODE_RUN は設定しない)、 エスケープコードを回避し、脆弱なコードに到達し、単一のバックスラッシュ文字で終わるコマンドライン引数を介して ヒープベースのバッファ "user_args" をオーバーフローさせます:


sudoedit -s '' perl -e 'print "A" x 65536' malloc(): corrupted top size Aborted (core dumped)

攻撃者の観点から見ると、このバッファオーバーフローは理想的です:

  • 私たちはオーバーフローさせる "user_args" バッファのサイズを制御します(連結されたコマンドライン引数のサイズ、行 852-854);

  • オーバーフロー自体のサイズと内容を独立して制御します(最後のコマンドライン引数の直後に最初の環境変数が続きます。これらは行 852-853 のサイズ計算には含まれません);

  • オーバーフローさせるバッファにヌルバイトを書き込むことさえできます(単一のバックスラッシュで終わるすべてのコマンドライン引数または環境変数は、"user_args" にヌルバイトを書き込みます、行 866-868)。

たとえば、amd64 Linux では、次のコマンドは 24 バイトの "user_args" バッファ(32 バイトのヒープチャンク)を割り当て、 次のチャンクの size フィールドを "A=a\0B=b\0" (0x00623d4200613d41)、 fd フィールドを "C=c\0D=d\0" (0x00643d4400633d43)、 bk フィールドを "E=e\0F=f\0" (0x00663d4600653d45) で上書きします:


env -i 'AA=a' 'B=b' 'C=c' 'D=d' 'E=e' 'F=f' sudoedit -s '1234567890123456789012'

ツールをダウンロード