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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2022-1015-1016 — Davidによって発見され文書化されたCVE-2022-1015およびCVE-2022-1016のスペイン語翻訳 | Kitploit
ツール/GitHubGitHub/zanezhub/cve-2022-1015-1016
特権昇格脆弱性分析エクスプロイト学習と教育バイナリエクスプロイト
GitHubzanezhub/cve-2022-1015-1016

CVE-2022-1015-1016

Davidによって発見され文書化されたCVE-2022-1015およびCVE-2022-1016のスペイン語翻訳

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

人気

すべて見る →

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

すべてのツールを探索

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

すべてのツールを見る →
共有
ウェブサイト

CVE-2022-1015 & CVE-2022-1026

このREADME.mdは、Davidのブログの翻訳です。DavidはLinuxカーネルでCVE-1015および1016を発見しました。原文を読むには彼のウェブサイトをご覧ください。

彼のソーシャルメディアはこちら:

  • Twitter
  • Github

nf_tablesにおけるLinuxの2つの新たな脆弱性の分析

2022年4月2日公開

  • CVE-2022-1015は、入力引数の検証不足に起因するout-of-boundsアクセスを引き起こし、リモートコード実行やローカル特権昇格につながる可能性があります。
  • CVE-2022-1016は、スタック上に割り当てられた変数の初期化不良に関連しており、カーネルからユーザースペースへの広範なデータ漏洩に利用される可能性があります。

これらの問題は、最新のUbuntuおよびRHELのデフォルト設定で悪用可能であると考えられます。CVE-2022-1015のPoC(Proof of Concept)は、Arch Linuxのカーネルバージョン5.16-rc3をターゲットとして作成しました。

この文書は、Linuxカーネルの機能とセキュリティに関する基礎知識を持つ読者を対象としています。ネットワークスタックに詳しくない方にも理解しやすいよう、できるだけ平易に記述するよう努めました。

以下は読み進め方のガイドです:

  • 脆弱性そのものについて読みたいだけなら、セクション4から始めてください。
  • カーネルサブシステムの背景知識も欲しい場合は、セクション2から始めてください。
  • さらに詳細な背景に興味があるなら、文書全体をお読みください。

1. 背景

2月中旬、GoogleのセキュリティプログラムはkCTF報奨金プログラムの継続を発表し、nsjailサンドボックス内の非特権プロセスからrootユーザーへの権限昇格を可能にするLinuxカーネルのエクスプロイトに対して、31,337ドルから91,337ドルの報奨金を提供するとしました。

貧乏な学生である私は、明らかにこれに惹かれました。これが「現実世界」の脆弱性を探す初めての試みでしたが、CTFで自分のチームと冒険する中で、セキュリティの観点からLinuxカーネルに親しんでいました。何時間も(ほとんど進歩せずに、しかしLinuxに関する知識は増えて)過ごした後、nf_tablesモジュールにいくつかの脆弱性を発見することができました。

残念ながら、結局このモジュールはGoogleのkCTFルールには含まれていなかったため、これらの2つの脆弱性に対して報奨金は得られませんでした。しかしもちろん、それでも報告し、CVE-2022-1015用のLPE(ローカル特権昇格)エクスプロイトを作成しました。

1.1 ターゲットの特定と監査戦略

さて、あなたはLinuxにいくつかの脆弱性を見つけようと決意しました。次はどうする? Linuxは巨大なプロジェクトであり、木を見て森を見ず(細部に集中しすぎて本当に重要なことを見失う)になりがちです。さらに悪いことに、多くの部分は文書化されておらず、何が起こっているのか理解するために大量のコードを読む必要があります。

私はまず、Linuxのセキュリティモデルを詳細に把握しようと試みました。バグを見つけることと、良いバグを見つけることは別物です。結局のところ、すべてのバグが同じように作られているわけではありません:

  • バグがroot権限を必要とする場合、セキュリティ上の境界線は意味をなさない(カーネルモジュール署名が有効でない限り)。
    • 思い浮かぶのは、多くの(仮想)ファイルシステムモジュールです。これらのファイルシステムをマウントできるのは初期rootユーザーのみです。例外は、FS_USERNS_MOUNTを指定するvfsで、その場合ユーザー名前空間でマウントできます。
  • バグにシステムコール経由でアクセスできない場合、おそらく悪用は不可能でしょう。
    • これは多くのハードウェアドライバーに当てはまります。物理的なアクセスがないためです。ただし、低レベルのネットワークドライバーは、Bluetoothや802.11.acなどを通じてデータを送信できる場合、依然として良いターゲットとなり得ます。
    • 明らかに、これは状況に依存します。
  • 多くのバグはCAP_SYS_ADMINまたはCAP_NET_ADMINを必要とします。
    • ユーザー名前空間はデフォルトで有効なので、これは問題になりません。
    • そうでなければ、まずコンテナ内でrootユーザー名前空間への権限昇格を行う必要があります。
  • すべてのモジュールがターゲットに存在するとは限りません。
    • Linuxは高度に設定可能な例外的なソフトウェアであり、すべての構成は多様な形で変化します。
    • カーネル構成は通常、/proc/config.gzからアクセスできます。モジュールはカーネルに組み込む(=y)か、別途コンパイルして実行時にロード(=m)できます。
    • /proc/modulesや/proc/kallsymsを使用できますが、モジュールはカーネルに動的にロードされる(例:request_module)ため、常に信頼できるとは限りません。
    • 確信が持てない場合は、モジュールと対話する小さなプログラムを作成してください。

これらの制約は、脆弱性を探すファイルシステムの範囲を絞り込むのに役立ちます。時間をかけて、狙うターゲットへの攻撃計画を立てるのは良い考えだと思います。

私は前述の点から教訓を得ました。前述したように、nf_tablesモジュールはkCTFで提供されたインスタンスにはロードされていませんでした。最初からこれに気づいていれば、失望を避けられたでしょう:p。一方で、もし気づいていたら、おそらく今頃このブログを読んでいることはなかったでしょう。結局うまくいったのだから、良しとしましょう。

COS(Googleのコンテナ最適化Linuxフォーク)にnf_tablesが含まれていなかった理由の説明は、こちらとこちらにあります。

1.2 nf_tables:なぜか?

上記の点を評価した後、最善の道はおそらくネットワークソースコードを見ることだと判断しました。そこにある多くの興味深い機能はCAP_NET_ADMINを必要としますが、前述したように実際には問題になりません。むしろ、特別な権限を必要とするコンポーネントは、カーネル開発者が誤った安心感を持つ可能性があるため、一般的に安全性が低いのではないかと推測しています。

さらに、もっと詳しく知りたいファイルシステムを選ぶ努力もしました。そうすれば、たとえバグが見つからなくても、多くの興味深いことを学べます。

私は多くのネットワークファイルシステムを調査しましたが、重要なものは見つかりませんでした。net/サブディレクトリをナビゲートした後、nf_tablesモジュールに出会いました。少し複雑そうに見えたので、時間をかけて理解することにしました。

2. netfilter入門

Netfilter(net/netfilter)は、カーネル内のかなり大きなネットワークサブシステムです。簡単に言えば、netfilterはネットワークスタック全体にフックを設置し、他のモジュールがハンドラを登録できるようにします。フックに到達すると、制御はそれらのハンドラに委譲され、それぞれのネットワークパケット構造を操作できます。ハンドラはパケットを許可、ドロップ、変更することができます。


4. CVE-2022-1015

nf_tables API(net/netfilter/nf_tables_api.c)を何時間か探索して、正確な動作を理解し始めた後、ユーザーが送信するレジスタに対する論理検証を調べてみることにしました。すると、いくつかの疑わしい動作を発見しました。自分が正気を失っているのかどうか考えた後、見つけた脆弱性をトリガーする小さなPoC(概念実証)を書きました。それは、スタックメモリの読み取りと書き込みを可能にするOOB(out-of-bounds)脆弱性です。

カーネルアドレスを漏洩させる方法を見つけた後、プログラムカウンタを乗っ取るのは非常に簡単でした。少しのROP(Return-Oriented Programming)を経て、rootシェルが現実のものとなりました。

4.1 ルート

式のinitルーチンがnetlinkユーザーメッセージからレジスタをパースするたびに、ソースレジスタかデスティネーションレジスタかに応じて、nft_parse_register_loadまたはnft_parse_register_storeルーチンが呼び出されます。いくつかコメントを追加しました:```c int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len) {

/* Given a netlink attribute and the length
 * that is required to read the requested data,
 * write a register index to `sreg` or return
 * an error on failure. */

u32 reg;
int err;


reg = nft_parse_register(attr);
err = nft_validate_register_load(reg, len);
if (err < 0)
    return err;

/* Write resulting index to the nft_expr.data structure. */
*sreg = reg;
return 0;

}


static unsigned int nft_parse_register(const struct nlattr attr) { / Convert a register to an index in nft_regs */

unsigned int reg;

/* Get specified register from netlink attribute */
reg = ntohl(nla_get_be32(attr));

switch (reg) {
/* If it's 0 to 4 inclusive,      
 * it's an OG 16-byte register and we need to
 * multiply the index by 4 (4*4=16) */
case NFT_REG_VERDICT...NFT_REG_4:
    return reg * NFT_REG_SIZE / NFT_REG32_SIZE;

/* Else we subtract 4, since we need to account
 * for the OG registers above. */
default:
    return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
}

/* So supplied values of 1, 2, 3, 4 map to
 * OG 16-byte registers, with indices 4, 8,
 * 12, 16
 * Supplied values of 5, 6, 7 overlap the verdict,
 * 8,9,10,11   overlap with OG register 1
 * 12,13,14,15 overlap with OG register 2
 * etc. */

}


static int nft_validate_register_load(enum nft_registers reg, unsigned int len) { /* We can never read from the verdict register, * so bail out if the index is 0,1,2,3 */ if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE) return -EINVAL;

/* Invalid operation, bail out */
if (len == 0)
    return -EINVAL;

/* If there would be an OOB access whenever
 * `reg` is taken as index and `len` bytes are read,
 * bail out.
 * sizeof_field(struct nft_regs, data) == 0x50 */
if (reg * NFT_REG32_SIZE + len > sizeof_field(struct nft_regs, data)) 
    return -ERANGE;

return 0;

}

`*_store` のバリアントは実質的に同一ですが、いくつかの条件下で *verbdict* への書き込みを許可する点が異なります。最後のバリデーションを確認した後、ここで何かが本当におかしいです:```c
if (reg * NFT_REG32_SIZE + len > sizeof_field(struct nft_regs, data))

これは integer overflow のように見えますね。reg に、len を加えたときにオーバーフローを起こすような値を4倍したものを含ませることができれば、条件を満たせます。nft_parse_register_load では、reg の最後の貴重なバイトがポインタ u8 *sreg に書き込まれ、後でインデックスとして使用される nft_expr に落ち込みます。```c *sreg = reg;

本当にできるのか?`reg` はルーチンのバリデーションにおける `enum nft_registers` です。いずれにせよ、`nft_parse_register` の範囲である `0x00000001` から `0xfffffffb` までの値を渡すことができます。しかし、`nft_validate_register_load` において `reg` は32ビット値なのでしょうか?コンパイラは、より小さな型で全ての値を表現できる場合、*enum types* を縮小することが知られています。別の意見も聞いてみましょう。

GCC マニュアルより引用:```
The integer type compatible with each enumerated type (C90 6.5.2.2, C99 and C11 6.7.2.2).
Normally, the type is unsigned int if there are no negative values 
in the enumeration, otherwise int. If -fshort-enums is specified,
then if there are negative values it is the first 
of signed char, short and int that can represent all the values, 
otherwise it is the first of unsigned char, unsigned short and unsigned int 
that can represent all the values.

On some targets, -fshort-enums is the default; this is determined by the ABI.

¿TL;DR? ABIと最適化の程度に依存します。このオプションがLinuxビルドでデフォルトで有効になっているかどうかについて、具体的な証拠は見つかりませんでした。

ツールをダウンロード