メモリ タギング拡張 (MTE)

Reading time: 9 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

メモリ タギング拡張 (MTE) は、バッファオーバーフローや使用後解放の脆弱性などのメモリ関連エラーを検出し防止することで、ソフトウェアの信頼性とセキュリティを向上させるように設計されています。MTEは、ARMアーキテクチャの一部として、各メモリ割り当てに小さなタグを付け、そのメモリを参照する各ポインタに対応するタグを付けるメカニズムを提供します。このアプローチにより、実行時に不正なメモリアクセスを検出でき、任意のコードを実行するための脆弱性を悪用するリスクが大幅に低減されます。

メモリ タギング拡張の動作方法

MTEは、メモリを小さな固定サイズのブロックに分割し、各ブロックにタグを割り当てることによって動作します。通常、タグは数ビットのサイズです。

そのメモリを指すポインタが作成されると、同じタグが付与されます。このタグは、メモリポインタの未使用ビットに保存され、ポインタを対応するメモリブロックに効果的にリンクします。

https://www.youtube.com/watch?v=UwMt0e_dC_Q

プログラムがポインタを介してメモリにアクセスすると、MTEハードウェアはポインタのタグがメモリブロックのタグと一致するかどうかを確認します。タグが一致しない場合、それは不正なメモリアクセスを示します。

MTEポインタタグ

ポインタ内のタグは、上位バイトの4ビットに保存されます:

https://www.youtube.com/watch?v=UwMt0e_dC_Q

したがって、16の異なるタグ値を持つことができます。

MTEメモリタグ

すべての16Bの物理メモリには、対応するメモリタグがあります。

メモリタグは、専用のRAM領域に保存され(通常の使用ではアクセスできません)、16Bのメモリタグごとに4ビットのタグを持ち、最大でRAMの3%を占めます。

ARMは、専用のRAMメモリ内でこれらのタグを操作するために、次の命令を導入します:

STG [<Xn/SP>], #<simm>    Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>]       Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP>      Insert Random [pointer] Tag
...

チェックモード

同期

CPUは命令実行中にタグをチェックし、一致しない場合は例外を発生させます。
これは最も遅く、最も安全です。

非同期

CPUは非同期にタグをチェックし、一致しない場合はシステムレジスタの1つに例外ビットを設定します。これは前のものより速いですが、一致しない原因となる正確な命令を特定できず、例外を即座に発生させず、攻撃者に攻撃を完了する時間を与えます。

混合

???

実装と検出の例

ハードウェアタグベースのKASAN、MTEベースのKASAN、またはカーネル内MTEと呼ばれます。
カーネルアロケータ(kmallocなど)は、このモジュールを呼び出し、使用するタグを準備し(ランダムに)、カーネル空間に割り当てられたものと返されたポインタに付加します。

要求されたサイズに対して十分なメモリグラニュール(各16B)のみをマークすることに注意してください。したがって、要求されたサイズが35で、60Bのスラブが与えられた場合、最初の16*3 = 48Bにこのタグがマークされ、残り無効なタグ(0xE)マークされます。

タグ0xFすべてのポインタに一致します。このポインタを持つメモリは、任意のタグを使用してそのメモリにアクセスすることを許可します(一致しません)。このタグが攻撃されたメモリで使用されている場合、METが攻撃を検出するのを防ぐ可能性があります。

したがって、0xEと0xFが予約されているため、タグを生成するために使用できるのは14の値のみであり、タグの再利用の確率は1/17 -> 約**7%**です。

カーネルが無効なタググラニュールにアクセスすると、不一致検出されます。別のメモリ位置にアクセスした場合、メモリが異なるタグ(または無効なタグ)を持っていると、不一致が検出されます。攻撃者が運が良く、メモリが同じタグを使用している場合は、検出されません。確率は約7%です。

もう1つのバグは、割り当てられたメモリの最後のグラニュールで発生します。アプリケーションが35Bを要求した場合、32から48のグラニュールが与えられました。したがって、36から47のバイトは同じタグを使用していますが、要求されていません。攻撃者がこれらの追加バイトにアクセスすると、これは検出されません

**kfree()**が実行されると、メモリは無効なメモリタグで再タグ付けされるため、use-after-freeの際にメモリに再度アクセスすると、不一致が検出されます

ただし、use-after-freeの場合、同じチャンクが以前と同じタグで再割り当てされると、攻撃者はこのアクセスを利用でき、これは検出されません(約7%の確率)。

さらに、**slabpage_alloc**のみがタグ付きメモリを使用しますが、将来的にはvmallocstack、およびglobalsでも使用される予定です(ビデオの時点では、これらはまだ悪用可能です)。

不一致が検出されると、カーネルはさらなる悪用とエクスプロイトの再試行を防ぐためにパニックします(MTEには偽陽性はありません)。

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする