CVE-2026-40372とは?.NET 10.0.7で修正されたASP.NET Core権限昇格の影響範囲と対応手順
2026年4月21日、Microsoftは月例のPatch Tuesdayを待たずに.NET 10.0.7を配信しました。修正対象のCVE-2026-40372は、ASP.NET Core Data Protectionが認証Cookieやトークンの改ざん検知に使うHMAC検証が機能せず、攻撃者が有効な認証ペイロードを偽造できるという欠陥です。CVSSは9.1。ただし「.NET 10を使っている=危ない」ではありません。公式アドバイザリは被影響条件をかなり細かく絞り込んでおり、Web SDKで作った通常のASP.NET Coreアプリは既定で対象外になります。一方で「Windowsだから安全」と早合点すると取りこぼす構成もあります。まず自社が当事者かを正確に切り分け、当事者ならパッチとキーリング再生成をセットで実施する——この記事はその順序で判断材料を示します。
まとめ:CVE-2026-40372で今すぐやること
- 脆弱性:ASP.NET Core Data Protectionの認証付き暗号化で、HMAC検証タグがペイロードの誤ったバイト列から計算され、しかも計算結果が破棄されていた。結果として偽造ペイロードが検証を通る(CVE-2026-40372 / CVSS 3.1 9.1 / CWE-347 / 深刻度Important)。
- 修正版:.NET 10.0.7(ランタイム10.0.7、SDKは10.0.203または10.0.107)。2026年4月21日にOOBリリース。
- 対象:Microsoft.AspNetCore.DataProtection 10.0.0〜10.0.6。ただし公式の被影響条件を満たす構成に限る。Web SDKの通常のASP.NET Coreアプリは既定で対象外。逆にnet462/netstandard2.0アセットを消費する構成はWindowsでも対象。.NET 8.0.x / 9.0.x は非対象。
- やること:(1) 後述の条件で影響有無を判定 →(2) 10.0.7へ更新しNuGet参照ごと再ビルドして再デプロイ →(3) 対象かつ脆弱期間に外部公開していたならDataProtectionキーリングを失効 →(4) DB内のAPIキーやリフレッシュトークンなど、キーリング失効が届かない長期資産を個別に無効化。
10.0.7を当てれば偽造ペイロード自体は拒否されます。それでも(3)(4)が要るのは、なりすまし中にアプリが正規に発行してしまったトークンが生き残るからです。以下、判定から対処までを順に見ていきます。
CVE-2026-40372の中身:HMAC検証タグが「誤った範囲」で計算され破棄されていた
Data ProtectionはASP.NET Coreの暗号化基盤で、認証Cookie、AntiForgeryトークン、OpenID ConnectのstateやTempDataなど、クライアントに渡して後で戻ってくるデータの保護に使われます。仕組みは認証付き暗号化——暗号化した上でHMACの検証タグを付け、復号前にタグを照合して改ざんを弾きます。この「照合」が壊れていたのが今回の欠陥です。
Microsoftの公式アドバイザリ(dotnet/announcements #395)は、managed authenticated encryptorが「HMAC検証タグをペイロードの誤ったバイト列に対して計算し、計算したハッシュを破棄していた」と説明しています。誤った範囲で計算した上に結果を捨てるため、改ざんの検知そのものが成立しません。CWE-347(暗号署名の不適切な検証)に分類されるのはこのためです。
CVSS 3.1のベクタは AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N、スコア9.1。ネットワーク越しに、認証も利用者操作も不要で、機密性と完全性の両方に高い影響が出るという評価です(Microsoftの深刻度ラベル自体はImportant)。
偽造できるものと、復号できてしまう理由
アドバイザリは、攻撃者がData Protectionの真正性チェックを通過するペイロードを偽造でき、加えて保護済みペイロードの一部を復号し得るとしています。復号まで成立するのは、検証が機能しない状態がパディングオラクル型の条件を作るためで、Microsoft自身がこれを2010年のMS10-070(ASP.NETの旧暗号基盤で同種のパディングオラクル攻撃が成立した事例)に匹敵する能力だと位置づけています。
実務上のリスクは、Data Protectionで守っているものすべてに及びます。
- 認証Cookie(管理者を含む任意ユーザーへのなりすまし)
- AntiForgeryトークン(CSRF防御のバイパス)
- OIDCのstate/nonceなど認証フロー中の一時データ
- Data Protectionで保護して発行したパスワードリセットリンク・メール確認トークン
なお、確認時点の各ベンダーアドバイザリでは、実環境での悪用や公開PoCは報告されていません。とはいえ欠陥の性質上、悪用の難易度は高くないと見るべきです。
自分は影響を受けるのか:公式アドバイザリの被影響条件で判定する
ここが今回のCVEで最も誤解が多い部分です。「バージョンが該当したら全部危ない」という読み方は誤りで、公式アドバイザリは主構成(Primary)と副構成(Secondary)を分けて条件を明示しています。順に判定してください。
主構成:3条件をすべて満たす場合
アドバイザリのPrimary affected configurationは、次の3つをすべて満たす場合です。1つでも外れれば、この構成では対象外です。
- 条件1:Microsoft.AspNetCore.DataProtection 10.0.6 をNuGetから参照している(直接参照のほか、
.StackExchangeRedis、.EntityFrameworkCore、.AzureKeyVault、.AzureStorageなどを経由した推移的参照を含む) - 条件2:その10.0.6のNuGetバイナリが実行時に実際にロードされる
- 条件3:Linux・macOSなど非WindowsのOSで動作している
参照の有無は推移的依存まで含めて確認します。
# Linux / macOS
dotnet list package --include-transitive | grep -i DataProtection
# Windows (PowerShell)
dotnet list package --include-transitive | findstr /I DataProtection
アドバイザリの被影響パッケージ表は 10.0.0〜10.0.6 を対象としています。主構成の記述は10.0.6を名指ししていますが、この範囲に入るなら対象候補として判定を進めるのが安全です。
条件2が実は最大の関門:PrunePackageReferenceが既定でNuGet版を刈る
見落としやすく、そして直感と逆なのが条件2です。アドバイザリは、欠陥入りのNuGetバイナリが実行時にロードされるのはアプリが Microsoft.NET.Sdk.Web をターゲットしておらず、かつ Microsoft.AspNetCore.App の FrameworkReference も直接・推移的に持たない場合だと説明しています。加えて、.NET 10で既定有効の PrunePackageReference をオプトアウトしている場合も同様です。
裏返すと、Web SDK(Microsoft.NET.Sdk.Web)で作った標準的なASP.NET Core Webアプリは、PrunePackageReferenceがNuGet版を既定で刈り取り、共有フレームワーク側の正しいアセンブリを使うため、既定では対象外ということです。「LinuxコンテナでASP.NET Coreを動かしているから危ない」という直感は、この条件では成立しません。
実際に当事者になりやすいのは、次のような構成です。
- Web SDKを使わないコンソールアプリ・ワーカーサービス・クラスライブラリからDataProtectionを参照している(Webアプリ本体より、キーリングを共有する裏側のバッチやワーカーの方が該当しやすい)
PrunePackageReferenceを明示的に無効化している- フレームワーク依存だが、インストール済み共有フレームワークのバージョンがPackageReferenceのバージョンを下回る(アドバイザリの例:共有フレームワーク10.0.5+PackageReference 10.0.6は対象/共有フレームワーク10.0.6+PackageReference 10.0.6は対象外)
したがって判定で最初に開くべきは dotnet --info ではなく .csproj です。<Project Sdk="Microsoft.NET.Sdk.Web"> になっているか、PrunePackageReference を切っていないか、この2点を確認してください。
Windows例外が効かない構成:net462/netstandard2.0アセットを消費している場合
欠陥があるのはmanaged authenticated encryptorです。Windows上のASP.NET Core(net10.0ターゲット)は既定でWindowsのCNGベースの実装を使うため、この欠陥のあるコードパスを通りません。ここまでは「Windowsは対象外」で正しい。
ただし、公式アドバイザリにはWindows例外が適用されない副構成があります。DataProtection 10.0.0〜10.0.6 を参照し、ビルドが net462 または netstandard2.0 のターゲットフレームワークアセットを消費している場合です。これは、アプリが net10.0 をターゲットせずに10.0系パッケージを引いたとき(net8.0、net9.0、net481 など)に起こります。
この構成ではCNGパスがnet10.0アセットにしか存在しないため、OSを問わずmanaged実装を通ります。つまりWindows上でも影響を受けます。アドバイザリはこの母集団を「はるかに小さい」とし、主に次の2種類だと述べています。
- ASP.NET Core DataProtectionパッケージをたまたま使っている.NET Framework製のデスクトップ/サーバーアプリ
netstandard2.0をターゲットとし、10.0系のDataProtectionパッケージを参照しているライブラリ
構成別の判定早見表:対象・対象外の切り分け
| 構成 | 判定 | 理由 |
|---|---|---|
| Windows上のASP.NET Core(net10.0) | 対象外 | CNG実装を使い欠陥コードパスを通らない |
| .NET 8.0.x / 9.0.x のDataProtection | 対象外 | 当該コードパスは10.0開発時に混入・バックポートなし |
| Web SDK+共有フレームワーク10.0.6+PackageReference 10.0.6 | 対象外 | PrunePackageReferenceでNuGet版が刈られ共有FW側が載る |
| Linux+共有フレームワーク10.0.5+PackageReference 10.0.6 | 対象 | 欠陥入りNuGetコピーが実行時にロードされる |
| Linux+非Web SDK(コンソール/ワーカー/ライブラリ)で参照 | 対象 | FrameworkReferenceが無くNuGet版が載る |
| net462 / netstandard2.0 アセットを消費(OS問わず) | 対象 | CNGパスが無くmanaged実装を通る。Windows例外は適用外 |
判定に迷う場合は「対象」と見なして更新する方が安全です。10.0.7への更新自体は破壊的変更を伴わず、コストは低く済みます。
.NET 10.0.7への更新手順
2026年4月21日リリースの.NET 10.0.7が修正版です。ランタイムは10.0.7、SDKは10.0.203(10.0.2xx帯)と10.0.107(10.0.1xx帯)の2本が同時に出ています。どちらも同じ10.0.7ランタイムを含むので、いま使っているSDK帯に合わせて選べば構いません。global.jsonでSDKを固定しているプロジェクトは、そこに書かれた帯に合わせる必要があります。
Linuxサーバ・Dockerイメージの更新
パッケージマネージャ経由なら通常のアップグレードで入ります。
sudo apt-get update
sudo apt-get install -y dotnet-sdk-10.0 aspnetcore-runtime-10.0
dotnet --list-runtimes
コンテナはベースイメージのタグを10.0.7へ上げてイメージを再ビルドします。10.0 のような可変タグを使っていても、ローカルやレジストリのキャッシュで古い層が残ることがあるため、明示タグで固定してから再ビルドするのが確実です。
FROM mcr.microsoft.com/dotnet/aspnet:10.0.7 AS runtime
FROM mcr.microsoft.com/dotnet/sdk:10.0.7 AS build
よくある失敗:ランタイムだけ更新して再ビルドを忘れる
条件2の裏返しで、ホストのランタイムを10.0.7に上げただけでは、NuGetのDataProtectionを実行時にロードする構成のアプリは脆弱なままです。PackageReferenceのバージョンを10.0.7以上に更新し、restore・build・publishをやり直して再デプロイするところまでが1セットです。
dotnet add package Microsoft.AspNetCore.DataProtection --version 10.0.7
dotnet restore --force
dotnet publish -c Release
デプロイ後は再度 dotnet list package --include-transitive で、推移的に引かれた10.0.6が残っていないか、実際に載っているバージョンが10.0.7になっているかを確認してください。「更新したつもり」で終わっている事故が、この脆弱性で最も起きやすいパターンです。
パッチだけでは終わらない:DataProtectionキーリングの再生成
ここが今回の対応で最も判断を要する部分です。10.0.7を適用すると、脆弱期間に作られた偽造ペイロード自体は拒否されます。偽造されたペイロードは必然的にHMACバイトが全ゼロになるため、修正後の検証ルーチンが弾くからです。
問題はその先にあります。攻撃者が偽造Cookieで特権ユーザーになりすましている間に、アプリケーションが正規に署名して発行してしまったトークン——セッションリフレッシュトークン、APIキー、パスワードリセットリンクなど——は、暗号学的には何ら不正ではありません。したがって10.0.7へのアップグレードでは無効化されず、有効期限まで通り続けます。これを断ち切るには、DataProtectionのキーリングを失効させて信頼の起点を作り直す必要があります。
RevokeAllKeysによる一括失効と、全ユーザー強制ログアウトという代償
既存キーの一括失効は IKeyManager で行います。アドバイザリのサンプルは、同じキーリングにアクセスできるアプリから一度だけ実行する想定です。
var services = new ServiceCollection()
.AddDataProtection()
// 既存のリポジトリ・保護設定をここに再現する
.Services
.BuildServiceProvider();
var keyManager = services.GetRequiredService<IKeyManager>();
keyManager.RevokeAllKeys(
// リング内の全キーを失効させる。範囲を絞るなら10.0.6デプロイ直前の時刻を指定する
revocationDate: DateTimeOffset.UtcNow,
reason: "Emergency revocation after CVE-2026-40372 remediation");
RevokeAllKeys はキーリング内の全キーを失効済みとしてマークし、次のprotect操作で新しいキーが自動生成されます。副作用として全ユーザーが再ログインを求められ、発行済みAntiForgeryトークンもすべて再発行になります。これは想定された効果そのものです。裏を返せば「誰にも気づかれずに対応を終えた」なら、キーリングが回っていない可能性を疑うべきです。
影響を絞れるなら、より外科的な手段もあります。ある時刻Tより古いキーは脆弱なプロセスで使われていないと確証が持てる場合、RevokeKey(Guid keyId, string reason) で脆弱期間に有効だったキーだけを失効させられます。全ユーザーのログアウトを避けたいなら、まずこちらを検討してください。
実施タイミングは10.0.7のデプロイ完了後です。複数インスタンスでキーリングを共有している構成(Redisやblobストレージに永続化しているケース)では、全インスタンスが10.0.7で動いていることを確認してから失効させないと、更新の遅れたインスタンスが新しいキーを扱えず障害になります。
キーリング失効が届かない長期資産を個別に無効化する
キーリングの失効は、Data Protectionが保護しているペイロードにしか効きません。アプリケーションが自前でデータベースに保存している資産には届かないため、脆弱期間中に発行されたものは別途無効化が要ります。
- DBに永続化しているリフレッシュトークン・アクセストークン・セッションレコード
- 保護されたエンドポイント経由で発行したAPIキー
- 脆弱期間に送信され、まだ期限切れになっていないパスワードリセットリンク・メール確認トークン
- 保護ペイロード内に格納していた接続文字列・外部サービスのシークレット(漏洩したものとして発行元でローテーション)
逆に、認証エンドポイント経由でこうした長期資産を発行していないアプリなら、キーリングの失効だけで十分だとアドバイザリは明言しています。対応範囲は闇雲に広げず、ここで確定させてください。
そもそもキーリングを回すべきかの判断基準は、脆弱期間中にインターネットへ公開されていたかの一点です。閉域網の検証環境まで全ログアウトさせる必要はありません。逆に公開エンドポイントを持つ本番環境は、悪用の痕跡が見つかっていなくても回すのが妥当です。偽造の成功はサーバ側のログに正常な認証として記録されるため、「痕跡がない=安全」とは言えません。
それでもログを当たるなら、保護ペイロード(認証Cookie、AntiForgeryトークン、stateパラメータ)を受け付けるエンドポイントへの異常なリクエスト量を脆弱期間で確認します。パディングオラクル攻撃は1バイト復元するのに多数の試行を要し、通常トラフィックとは桁が違うためです。単一の認証エンドポイントに、値を変えたCookieやクエリパラメータで大量アクセスが継続していれば強い兆候です。
10.0.6の復号失敗バグからOOBリリースに至った経緯
今回のリリースが月例サイクルの外に出た理由は、発見の経路にあります。2026年4月14日のPatch Tuesdayで配信された.NET 10.0.6の適用後、「アプリケーションで復号が失敗する」という報告が4月16日にユーザーから寄せられました(aspnetcore issue #66335「CRITICAL BREAKING CHANGE in Microsoft.AspNetCore.DataProtection from 10.0.5 => 10.0.6」)。Microsoftがこの回帰バグを調査する過程で、同じコード変更がセキュリティ上の欠陥も生んでいたことが判明します。
つまり可用性の不具合(復号できない)の裏に、より深刻な完全性の欠陥(検証が機能しない)が隠れていたという構図です。次のPatch Tuesdayまで待てば1か月近く脆弱な状態が続くため、Microsoftは10.0.6のリリースから約1週間後の4月21日に10.0.7をOOB配信しました。
運用側の教訓は明確です。10.0.6を当てたあとに復号エラーが出て「相性問題」としてロールバックした環境は、10.0.6以前の脆弱なバージョンに留まっている可能性があります。そうした環境こそ優先的に10.0.7へ上げてください。定例パッチ適用後の異常は、単なる不具合ではなくセキュリティ告知の予兆であり得ます(Apache HTTP Server 2.4の脆弱性対応やNode.jsの脆弱性対応でも、まず影響条件の切り分けから入るのが定石です)。
よくある質問(FAQ)
.NET 10.0.7はどこから入手できますか?
Microsoftの公式ダウンロードページ、またはLinuxのパッケージマネージャ(dotnet-sdk-10.0 / aspnetcore-runtime-10.0)から入手できます。SDKは10.0.203と10.0.107の2本があり、どちらもランタイム10.0.7を含みます。global.jsonでSDK帯を固定している場合は、その帯に合う方を選んでください。
Windowsサーバで運用していますが影響を受けますか?
原則として受けません。欠陥があるのはmanaged authenticated encryptorで、Windows上のASP.NET Core(net10.0ターゲット)は既定でCNGベースの実装を使うため該当コードパスを通りません。ただし例外があります。アプリやライブラリが net462 または netstandard2.0 のアセットとしてDataProtection 10.0.0〜10.0.6を消費している場合、CNGパスが存在せずmanaged実装を通るためWindows上でも影響を受けます。.NET Framework製アプリやnetstandard2.0ライブラリでDataProtectionを参照しているなら、Windowsでも対象と考えて更新してください。
.NET 8や.NET 9は影響を受けますか?
受けません。問題のコードは.NET 10の開発中に入ったもので、8.0.xおよび9.0.xのサービシングブランチにはバックポートされていません。ターゲットフレームワーク・OS・共有フレームワークのバージョンを問わず対象外です。ただし、これらのアプリが10.0系のDataProtectionパッケージを参照している場合は前述の副構成に該当し得るので、参照バージョンを確認してください。
公式アドバイザリはどこで確認できますか?
GitHubの dotnet/announcements リポジトリのissue #395がMicrosoftのセキュリティアドバイザリ本体で、被影響条件と対応手順が記載されています。議論はaspnetcoreリポジトリのissue #66410で行われています。あわせて.NET Blogの「.NET 10.0.7 Out-of-Band Security Update」に更新手順がまとまっています。判定は必ず一次情報で最終確認してください。
キーリングを再生成するとユーザーはログアウトされますか?
RevokeAllKeys を使えばされます。既存キーがすべて失効し、そのキーで保護された認証Cookieは拒否されるため、全ユーザーが再ログインを求められます。脆弱期間に有効だったキーを特定できるなら、RevokeKey(Guid keyId, string reason) で該当キーだけを失効させることで影響範囲を狭められます。いずれの場合も事前にメンテナンス告知を出したうえで実施してください。