
現代のコンピューティングの分野において、セキュリティの懸念はオペレーティングシステム(OS)の脆弱性やソフトウェアのバグを超えて広がっています。抽象化の深層部で、プロセッサはパフォーマンスを最大化するための複雑なマイクロアーキテクチャ(パイプライン、キャッシュ、バッファ、実行エンジン)を進化させています。皮肉なことに、これらの機能は新しい微妙なセキュリティリスクをもたらし、マイクロアーキテクチャ攻撃と呼ばれるものを生み出します。こうした攻撃は、同時に実行するアプリケーション間でマイクロアーキテクチャの状態が意図せず共有され、漏洩することを悪用します。場合によっては完全に安全なソフトウェアであってもです。
この包括的なブログ記事は、マイクロアーキテクチャ攻撃を解き明かすことを目的としており、以下の内容をカバーします:
初心者、研究者、ソフトウェア開発者、またはサイバーセキュリティの専門家であれ、このガイドはこれらの強力な最新の攻撃を理解し、それに対抗するための知識を提供します。
マイクロアーキテクチャ攻撃は、プロセッサのハードウェアの低レベル設計における意図しない情報漏洩を利用する攻撃手法です。
典型的なソフトウェアの脆弱性とは異なり、マイクロアーキテクチャ攻撃はアプリケーションやOSのプログラムバグを必要としません。代わりに、キャッシュ共有や命令の再順序化など、現代のCPUがパフォーマンスを最大化しようとする方法を悪用します。
現代のCPUは、以下のような重要なハードウェア構造をアプリケーションや仮想マシン間で共有しています:
これらの構造が完全に隔離されていないため、1つのプロセスが他の影響を観察または推測することができます。攻撃者はこの暗黙の共有を利用して、メモリアクセスタイムのわずかな変化などの間接的な物理的影響を観察することで、秘密を抽出します。
大きく分けて2つのカテゴリがあります:
隠れたチャネルは、システムの設計によって意図されていない形で、2つのアクター(送信者と受信者)の間に通信経路を作り出します。1つのアプリケーションが共有リソースを調整し、もう1つのアプリケーションがこれを観察してメッセージを再構成します。
例:
サイドチャネル攻撃は、直接的な通信なしに機密情報を漏洩します。むしろ、被害者の活動によって「こぼれた」情報を利用します。
例:
これらのチャネルを利用することで、1つのプロセスが別のプロセスについて情報を推測することができ、時にはコンテナ、VM、またはユーザー領域を越えて行われることもあります。
異種コンピューティングシステムは、同じプラットフォーム上で、(一般用CPU、GPU、FPGA、AIアクセラレータなど) 複数のプロセッサタイプを組み合わせたもので、いくつかのメモリやマイクロアーキテクチャ状態を共有することがあります。
例えば、GPUとCPUがキャッシュ領域を共有しているとしましょう。GPU上で動作する低権限プロセスはキャッシュを「プライム」し、CPUで動作する高権限プロセスは無意識のうちに秘密をそのメモリアクセスを通じて明かすことがあります。その後、低権限プロセスは変化を観察し、保護された情報を推測することができます。
RISC-Vは、研究目的や商用埋め込みシステム向けとして急速に人気を博しているオープンソースのモジュラー命令セットアーキテクチャです。マイクロアーキテクチャ攻撃はx86やARMでよく研究されていますが、最近の研究でRISC-Vも同様に脆弱であることが示されています。
ポイント:どの命令セットやオープンソースハードウェアも免疫ではなく、共有マイクロアーキテクチャを備えたすべてのCPUは、特定の強化が施されない限り脆弱です。
新しい領域:スタックエンジン攻撃 (出典)
攻撃者と被害者が同じCPUを共有している場合、特定のスタック操作を実行し結果のタイミングを観測することで、攻撃者は被害者が最近のスタック活動について推測できる情報を得ることができます。
スペクターとメルトダウン(2018年)は、マイクロアーキテクチャ攻撃が理論上のものにとどまらず、数十億台のコンピュータに影響を与えることを理解させました。
[被害者プロセス] [攻撃者プロセス]
秘密データで命令を実行 キャッシュをプライムし、アクセスを時間計測
---[物理的にキャッシュを共有]---
プライムプローブは次のように動作するクラシックな攻撃です:
まるですべての座席にコインを置く(プライム)、他の誰かが入ってきて(被害者)が座った場所を見ていないまま確認し、どの座席が空いているかをチェックする(プローブ)かのように。
最近の攻撃はスタックエンジンの最適化をターゲットとしています:
強調しておくべきことは:生産システムへの実際の攻撃は、許可されていない限り違法です。しかしながら、側面チャネルとなる可能性を示すパフォーマンス測定は、研究および防御のために自分のテストマシン上で実施することができます。
キャッシュ共有をチェックするための簡単なタイミングプローブ(例: 仮想マシン内で)。
#!/bin/bash
buffer=/tmp/testmem
size=1024000
# 大きなバッファを確保
dd if=/dev/urandom of="$buffer" bs=1K count=1000
# 繰り返しメモリにアクセスしてキャッシュを“プライム”する
function prime_cache {
for i in $(seq 1 $size); do
tail -c +$i "$buffer" | head -c 1 >/dev/null
done
}
# アクセスを計測
function time_access {
/usr/bin/time -f "%e" dd if="$buffer" of=/dev/null bs=1K count=1000 2>&1
}
echo "キャッシュをプライムしています..."
prime_cache
echo "読み取りアクセスを計測しています..."
time_access
# その後、他のプロセスにメモリ集中型のワークロードを実行させて再度繰り返す
# タイミングが変更されるか比較し、キャッシュコンテクションを示す!
他のプロセスとのキャッシュ競合の証拠として大幅な変化を解釈します—潜在的にPrime+Probe攻撃が可能です。
Pythonのtimeモジュールとnumpy配列を用いて、反復メモリアクセスパターンをより正確に把握する方法。
import numpy as np
import time
# 大きな配列を確保する
arr = np.zeros((1024 * 1024 * 10,), dtype=np.uint8)
def probe_access():
ts = time.time()
# キャッシュロードを強制的に行うための全要素アクセス
for i in range(0, len(arr), 64):
arr[i] += 1
te = time.time()
print(f"アクセス時間: {te - ts:.6f} 秒")
# 初回実行:コールド状態(ページフォールトが発生するかもしれません)
probe_access()
# 2回目の実行:キャッシュがホットになりやすい
probe_access()
別の端末(または別プロセス)でメモリを大量に消費するスクリプト(例えば、stress-ngなど)を実行します。もう一度probe_access()を実行し、時間が増加することを観察します。
他のプロセスが実行された後に大きなアクセス時間が見られる場合、これはシステムのキャッシュがタイミング攻撃に対して脆弱であることを意味します。
マイクロアーキテクチャ攻撃の持続性を考慮して、セキュリティ管理者は何をするべきでしょうか?
# フラッシュ関連のCPU機能をチェック
grep . /proc/cpuinfo | grep -E 'flush|clflush|clwb'
# clflushが示される場合、キャッシュをクリアするための命令がソフトウェアで利用可能です
多くのCPUベンダーが以下のような機能を導入しています:
しかし、ほとんどの導入済みCPUは依然として脆弱であり、特にクラウド環境や複雑なハードウェアの使用において。
マイクロアーキテクチャ攻撃はもはや「理論上の好奇心」ではありません。プロセッサがより最適化され、より共有されるにつれて、内部設計の微妙さが熟練した攻撃者には強力なツールとなります。
特に、異種システムでは、CPU、GPU、アクセラレータがマイクロアーキテクチャ状態を共有するため、隠れたチャネルやサイドチャネルは単に可能性にとどまらず、一般的なものとなります。RISC-V CPUやスタックエンジンに対する最近の攻撃は、新しいアーキテクチャや最適化に対しても、これらのリスクが普遍的で持続的であることを示しています。
常に最新の情報を保持し、自分の環境をテストし、ソフトウェアとハードウェアの両方でより良い隔離を求めましょう。
この投稿は教育目的のみです。常に安全で管理された環境でテストしましょう。
このコンテンツが価値あるものだと感じたなら、私たちの包括的な47週間のエリートトレーニングプログラムで何が達成できるか想像してみてください。ユニット8200の技術でキャリアを transformed した1,200人以上の学生に参加しましょう。