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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2025-40019-POC — CVE-2025-40019の概念実証 | Kitploit
ツール/GitHubGitHub/0xatharv/cve-2025-40019-poc
メモリフォレンジック脆弱性分析エクスプロイト論文と研究学習と教育バイナリエクスプロイト
GitHub0xatharv/cve-2025-40019-poc

CVE-2025-40019-POC

CVE-2025-40019の概念実証

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2025-40019 の概念実証

CVE-2025-40019 は、暗号化ソルトセクター初期化ベクトル機構 (crypto/essiv.c) における、関連認証データ (AAD) 長の初期化ベクトル (IV) サイズに対する検証不十分に起因する、範囲外メモリアクセスの脆弱性です。 このリポジトリに含まれるコードは単なるバグトリガーですが、このバグは容易に悪用可能です。

KernelCTF エントリ

私は kernelctf のスプレッドシートこちらでこのバグを見つけました。このバグに関するブログ記事や PoC がなかったため、Linux カーネルの暗号サブシステムを調査し、問題の原因を探ることにしました。

img

背景: ディスク暗号化理論とESSIV

ESSIV の必要性を理解するには、まずデータがディスクにどのように保存されるかを理解する必要があります。ディスク暗号化(LUKS や dm-crypt など)は通常、セクタ単位で動作します。各セクタは独立して暗号化される必要があり、1つのセクタを読み取るためにディスク全体を読み取る必要がありません。

ウォーターマーキング攻撃

標準のCBC(暗号ブロックチェーン)モードでは、暗号化操作ごとに初期化ベクトル(IV)が必要です。初期のディスク暗号化実装では、セクタ番号がIVとして使用されていました。 しかし、セクタ番号は予測可能であるため、攻撃者は「ウォーターマーキング攻撃」を実行できます。既知のセクタに特別に細工されたデータを書き込むことで、攻撃者は暗号文のパターンから特定ファイルの存在を推測でき、暗号化の機密性を実質的に回避できます。

ESSIV ソリューション

ESSIV(Encrypted Salt-Sector Initialization Vector)は、IV を予測不可能にするために設計されました。次のように動作します。

  1. 秘密暗号鍵 $K$ をハッシュして「ソルト」$S = H(K)$ を導出します。
  2. セクタ番号 $SN$ を、ソルトを鍵とする別の暗号で暗号化します ($IV = E_S(SN)$)。
  3. 得られた $IV$ が、そのセクタの実際のデータ暗号化に使用されます。 これにより、攻撃者がセクタ番号を知っていても、秘密鍵を知らなければ IV を予測できなくなります。

すべてのアルゴリズム(AES のような基本暗号、ESSIV のようなラッパーのいずれも)は、カーネルが呼び出しをルーティングするために使用する構造体を実装しています:

struct skcipher_alg {
    int (*setkey)(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen);
    int (*encrypt)(struct skcipher_request *req);
    int (*decrypt)(struct skcipher_request *req);
    // ...
    struct skcipher_alg_common co; // Contains ivsize, chunksize, etc.
};

根本原因

この脆弱性は、ユーザー提供のメタデータ(AAD長)が常に暗号変換の内部要件を満たすと想定している、古典的なケースです。 「インプレース」または復号化(!enc)パスでは、コードはオフセット req->assoclen - crypto_aead_ivsize(tfm) を計算します。しかし、req->assoclen < ivsize かどうかをチェックしておらず、そのためこのオフセットが負になる可能性があります。

static int essiv_aead_crypt(struct aead_request *req, bool enc)
{
	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
	const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
	struct aead_request *subreq = &rctx->aead_req;
	struct scatterlist *src = req->src;
	int err;

	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);

	/*
	 * dm-crypt embeds the sector number and the IV in the AAD region, so
	 * we have to copy the converted IV into the right scatterlist before
	 * we pass it on.
	 */
	rctx->assoc = NULL;
	if (req->src == req->dst || !enc) {
		scatterwalk_map_and_copy(req->iv, req->dst,
					 req->assoclen - crypto_aead_ivsize(tfm),    // <------- bug !
					 crypto_aead_ivsize(tfm), 1);
	} else {
		u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset;
		int ivsize = crypto_aead_ivsize(tfm);
		int ssize = req->assoclen - ivsize;
		struct scatterlist *sg;
		int nents;
        .
        .
        .

scatterwalk_map_and_copy 関数を見ると、scatterlist sg に memcpy しているだけであることがわかります:

static inline void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
					    unsigned int start,
					    unsigned int nbytes, int out)
{
	if (out)
		memcpy_to_sglist(sg, start, buf, nbytes);
	else
		memcpy_from_sglist(buf, sg, start, nbytes);
}

パッチ

このバグのパッチは非常に単純で、assoclen が ivsize より小さいかどうかをチェックするだけです:


diff --git a/crypto/essiv.c b/crypto/essiv.c
index d003b78fcd855a..a47a3eab693519 100644
--- a/crypto/essiv.c
+++ b/crypto/essiv.c
@@ -186,9 +186,14 @@ static int essiv_aead_crypt(struct aead_request *req, bool enc)
 	const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
 	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
 	struct aead_request *subreq = &rctx->aead_req;
+	int ivsize = crypto_aead_ivsize(tfm);
+	int ssize = req->assoclen - ivsize;
 	struct scatterlist *src = req->src;
 	int err;
 
+	if (ssize < 0)
+		return -EINVAL;
+
 	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
 
 	/*
@@ -198,19 +203,12 @@ static int essiv_aead_crypt(struct aead_request *req, bool enc)
 	 */
 	rctx->assoc = NULL;
 	if (req->src == req->dst || !enc) {
-		scatterwalk_map_and_copy(req->iv, req->dst,
-					 req->assoclen - crypto_aead_ivsize(tfm),
-					 crypto_aead_ivsize(tfm), 1);
+		scatterwalk_map_and_copy(req->iv, req->dst, ssize, ivsize, 1);
 	} else {
 		u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset;
-		int ivsize = crypto_aead_ivsize(tfm);
-		int ssize = req->assoclen - ivsize;
 		struct scatterlist *sg;
 		int nents;
 
-		if (ssize < 0)
-			return -EINVAL;
-
 		nents = sg_nents_for_len(req->src, ssize);
 		if (nents < 0)
 			return -EINVAL;

クラッシュ

ツールをダウンロード