メモリのビット反転エラーとセキュリティの話
ハードウェアのエラーでメモリの内容が化けてしまうことが稀にある。大抵のDRAMエラーはせいぜいプログラムがクラッシュする結果になるだけだが、データ破壊になることもありえるし、悪意のある使い方をすればセキュリティ破りに使うこともできてしまう。ここではメモリエラーとセキュリティの話をしようと思う。
メモリのエラー率は意外なほど高い。データセンターで大規模なマシン群を対象に実際に観測したところ、1年間に1回以上のエラーが発生したDIMMモジュールは全体の8%にのぼったそうだ。DIMM 1枚に数百億個のメモリセルが実装されているといっても、このエラー率はちょっとびっくりするくらい大きな数字ではないだろうか? サーバでは普通はエラー訂正付きのDIMMを使うので1ビットのエラーは問題にならないが、エラー訂正のないコンシューマ機器ではこれは実際的な問題になりえる。
メモリエラーを利用したセキュリティ破りのテクニックがいくつかある。ビットスクワッティングというテクニックでは、大規模ウェブサイトとASCIIコードで1ビット違いのドメイン名を取得して、メモリエラーで迷い込んできたトラフィックを獲得するということを行う。実験では1ドメインにつき毎日1つ以上のリクエストが実際に送られてきたそうだ。
大規模なウェブサイトを運営している人なら、ビットスクワッティングがどれくらい効果的かを自分で推定してみることができる。HTTPリクエストにはUser-Agentのようにほぼ固定の文字列が含まれているので、これを利用してメジャーなUser-Agentと1ビット違いの文字列をログから探して、そのエラー率を求めればよい。やってみれば、ちらほらそういうリクエストが実際に見つかってびっくりすると思う。そういったリクエストはおそらくメモリエラーを起こしたクライアントから送られてきている。インターネットに繋がったコンシューマ機器が増えるに連れてビットスクワッティングは無視できない問題になるのかもしれない。
ハードウェアは一般的に高温で不安定になるので、暖めることでメモリエラーを誘発することもできる。ある論文では、Javaサンドボックスのセキュリティを突破するために、ハードウェアを100℃くらいに加熱してメモリエラーを誘発して、指すことが不可能なはずの領域を指しているリファレンスを作り、それを橋頭堡に権限を奪取するというテクニックが紹介されていた。ルール破りの荒技のようだが、セキュリティ破りにルールなどないのだ。
完全にソフトウェアだけでメモリエラーを誘発することも不可能ではない。これはかなり最近に発見された手法なのだが、ローハンマーというテクニックでは、キャッシュをバイパスしつつ同一のアドレスに通常ありえない頻度で激しくアクセスすることで、物理的に隣接するメモリセルに想定を超える電気的な影響を与えてビット反転を引き起こすということを行う。これに別のテクニックを組み合わせればサンドボックス内のアプリからカーネル権限を取得することができてしまう。ローハンマーの対処法はあるといえばあるのだが、ファームウェアやハードウェアの変更が必要なので、現存するコンピュータでは脆弱なハードウェアがたくさんあるはずだ。
というわけでメモリというのはそこまで信頼が置けるものではないし、メモリエラーを利用していろいろ楽しいことができてしまうのも事実だ。こういうのを知るのは面白いけど現実に体験したいとは思わないだろう。信頼性が必要な場合はECC付きのメモリを使うのが無難だ。