« IA-32e=AMD64の衝撃 | Main | IA-64に動的スケジューリング? »

2004.03.05

OSがバッファオーバーフロー攻撃から解放される日

AMD64で行われたIA-32に対する拡張はいろいろありますが、最も重要なのは実メモリ空間の拡張です。AMDはこの際、ページング機構で用いられるページテーブルエントリ(PTE)などの拡張にIntelがPAE(物理アドレス拡張)で行った拡張を流用しました。
IA-32のメモリ管理機構(MMU)が持つページング機構はここにあるような構造をしています(原書で言えば3.6あたり)。各ページではPTEによって書き込み許可/拒否とユーザ/スーパバイザの2種類の保護機構を利用することができます。PentiumProで導入されたPAEでは、ここにあるように(原書なら3.6.1や3.8あたり)、物理アドレスの拡張のために各テーブルのエントリは64bit化されています(といっても拡張32bit分のうち4bitしか使ってませんが)。AMD64では、このPTEなどの構造はほぼそのままに上位ビットをさらに使います。この辺はやはり原書:AMD64 Architecture Programmer's Manual Volume 2: System Programmingの5.1あたりを参照してください。

で、このアドレス拡張と同時に、もうひとつ保護機能に関して重要な拡張が行われています。それはPTEなどの最上位にNXビット(実行不許可ビット)という定義がされていることです。このビットがセットされたエントリに対応するページにあるコードをCPUが実行しようとすると保護例外が発生するもので、スタックやヒープに割り当てたメモリ領域にOSがセットすることを想定したものです。この拡張により、現在のOSやネットワークサービスプログラムが残してしまうセキュリティホールの主なものである「バッファオーバーフロー」攻撃に対し、不正コードを送り込まれて実行される可能性を激減させることができます(バッファオーバーフロー攻撃はそもそもこの種のデータ領域の境界チェックの不備を突いてデータ領域に不正コードを展開することから始まるのですから)。しかもこの機能、AMD64であれば64bitモードで実行していなくても、PAEが有効にされているだけで利用できるので、旧来の32bitOSでも利用できてしまいます。実際、AMDとマイクロソフトはWindows XPのSP2およびWindows Server 2003のSP1からこの機能を生かすことを発表しました

この機能の威力は絶大です。特にCやC++が主流言語として残っている現状ではバッファオーバーフロー脆弱性なんて世の中から消すことは絶望的だったわけですが、たとえ脆弱性が残っていてもせいぜいDoS攻撃に使えるだけ(*)で侵入されないということになるとシステム管理者としてもプログラマとしてもずいぶん気分が楽になります。SlammerやBlasterのようなワームも原理的には動作しえませんし、OpenSSH/SSLの穴にビクビクする必要もないはず。このOSの変更によって影響を受けるプログラムもJavaのJITなど、自己書き換えや動的コード生成を含むようなごく一部のもので済みます。多分OSの設定で、特定のプログラムだけこの機能を殺すようにしたり、あるいはアプリケーション側で特定のヒープ領域だけ実行可能にするようなAPIを呼び出すようにするんでしょうね。

ということでこの話、私にとっては待ちに待った、もっと早くやってほしかった機能拡張です。もっと大きく取り上げられてもよいと思うんですが、まだその重要性がよく理解されていないのでしょうか。残念です。

他のOSの状況はまだよく調べてませんが、FreeBSD/AMD64はまだこれからみたいです(machdep.cのほうにはSince we don't use PG_NX yet,...なんて書いてありました)。前に見たときはstackを実行不可にしようとしてたみたいに読めたのですが動いてなかったのかなぁ・・・Linuxはどうなんでしょう?誰か教えてください。とにかく、Intelの参入によってAMD64/IA-32eは主流になりますから、あともう少し我慢すればOSのサポートも進んで、全てのパソコンやサーバがバッファオーバーフロー攻撃から解放される日が来るのでしょう。

ちなみにIA-32のMMUで特定のアドレス領域を実行不能にすることは今まででもできましたが、セグメントディスクリプタを使う必要がありましたので、現在のUNIXやWindowsの仮想記憶機構の構造ではかなりトリッキーなことをしないと使えません(昔FreeBSDで実現したらどうなるだろうとずいぶん考えたことがあるんですがあきらめました)。すっかり忘れがちですがIA-32はPaged segmentationが利用できる数少ないMMUを持っています(だからこそ32bitアドレスはリニアアドレスと呼ばれます。仮想アドレスとしてはセグメント指定をあわせて48bitになります。)し、そのセグメント機構をちゃんと使っていたOS/2はちゃんとデータやスタックはセグメントで分離されてて実行不可にされていました。私はMultics以来のセグメント機構を愛していましたのでOS/2 ver.3あらためOS/2 NTあらためWindows NTが、32bitリニアアドレスを採用すると聞いたときにずいぶん残念に思ったものです。もちろんその時には、あるメモリ領域を実行不可にすることの効果がセキュリティにまで及ぶとは夢想だにできなかったのですが。

(*)追記:首藤さんの指摘でちょっと言い過ぎたかと思い直しました。詳しくはコメントを。

(2004.03.06)
元麻布さんの64bitへ動き出したIAサーバの胎動ここでもちょっと触れられていたりします。しかしこれ見てあわてたのですが、確かにIA-32eではまだNXビットに対応するところがReservedにされていて、有効かどうか明らかじゃないのですね。しかし特許などの問題がないのなら(クロスライセンスしてるはずですよね)是非ここもあわせていただきたいものです。IA-64でもMMUに実行不許可機能つけてたはずですから、重要性を認識していないはずがないと思うのですが。
それにしてもこのページあちこちにlinkはられたみたいでご訪問者急増。


|

TrackBack

TrackBack URL for this entry:
http://app.cocolog-nifty.com/t/trackback/3940/265079

Listed below are links to weblogs that reference OSがバッファオーバーフロー攻撃から解放される日:

» WinXP SP2の影響 [哲太郎の備忘録]
自分にトラックバックする、なんてことをしてみるといいのでしょうか、なんてテストを兼ねて。 先日言ったNXbitのことに限らず、WinXP SP2でセキュリティ強... [Read More]

Tracked on 2004.03.09 at 07:32 AM

» 大丈夫でしょうか [哲太郎の備忘録]
OSがバッファオーバーフロー攻撃から解放される日とかいってましたが、さてよくよく考えるとなかなか一筋縄では行かないもので。  ここで既に保護の仕様が出ていること... [Read More]

Tracked on 2004.03.09 at 06:15 PM

» The Blog [The Blog]
Provides extranet privacy to clients making a range of tests and surveys available to their [url=http://chiki-puki.com/M18xNDgyNjY0]human[/url] resources departments. [Read More]

Tracked on 2007.08.29 at 05:48 AM

» Order Carisoprodol [Order Carisoprodol]
Cheap Hydrocodone [Read More]

Tracked on 2007.10.10 at 07:44 PM

Comments

てつたろ先生、大変ごぶさたです。

メモリ領域に実行可/不可の属性を持たせられるという機能をOSが持っていても、実際のところIA-32にはその機能がないため、働かない、と聞いてます。

以前、bugtraqかどこかで、スタックを実行不可にすることで攻撃を防げる/いや、あまり危険性が減るものではない、という議論を見ました。あまり防げない派の主張は、exploitコードはスタックに置かれるとは限らない云々というものでした。ヒープにexploitコードを置かれた場合や、return into libc(?)攻撃は、たしかに、スタックが実行不可でも可能なように思われます。

スタックを実行不可にすることの影響は、gccがnested functionの関数ポインタを扱う際に生成するtrampoline codeが働かなくなる、くらいしか知りません。
ヒープ実行不可の影響は、JavaやC#(?)のJIT…以外に何がありますでしょうか。

Posted by: しゅどう | 2004.03.05 at 09:11 AM

首藤さんご無沙汰です。HOKKE行きたかったけど無理でした(号泣)

まずこの話、IA-32ではなくAMD64/IA-32eで、各ページ単位で実行不可/許可する機能がMMUについたという話なんですが読みにくかったでしょうか(^^;しかも64bitモードではなく、PAEさえ有効なら32bitモードでも使えるというのが大きなポイントなんです。

bugtraqの議論は読んでませんがスタックやヒープを実行不可にしても完璧ではないのは理解しています。ですが、スタックとヒープさえ守れれば原理的にはnativeなコードを直接は送り込むことができないのは大きいと思います。あと怖いのはスクリプトなりJavaVMのコードなり.NetのCLIが直接送り込まれたりするようなケースなのですが、これらは結局は実行系が介在しますから、こんどはそちらがセキュリティをどうするかという話になってくるのだと思います(とりあえずはsand boxを実行系ごとにちゃんとして、ということなんでしょうね)。ret-to-libc攻撃に関しても、結局はスクリプトを送り込んでシェルを起動するとかいうのが定石手ではないかと思うのですが。もちろん上手く使えば条件分岐などはできないもののそれなりのnativeプログラムが書けるでしょうから怖いといえば怖いのですけど・・・まぁとにかく、完璧とはさすがにいいませんが随分robustになると思うのですが。

ヒープが実行不可だと困るプログラムは私はJIT系くらいしか知りません。それらを例外扱いすることでどれだけ脆弱性が増すのかというのがやはりポイントなのかと思います。

Posted by: Tetsu=TaLow | 2004.03.05 at 06:50 PM

すみません、つまらないことなのですが、文脈から察するに
s/開放/解放/g
なのではないかと思われます。
内容に関しては非常に参考になりましたです。はい。 (_o_)

Posted by: fukumori | 2004.03.06 at 11:06 PM

あらま福森さんまで。ご無沙汰してます。
ご指摘ごもっともです、お恥ずかしい。2箇所修正しておきました。

Posted by: Tetsu=TaLow | 2004.03.07 at 12:13 AM

うーん大変。Active Template Library(ATL)というのがありますが、
http://www.codeproject.com/cpp/SoloGenericCallBack.asp
こんなことをしてるそうです。自分の中にthunkコードを埋めて、それを関数のポインタとして渡すという。これheapの中ですから困りましたね。

Thunkといえば多重継承で
http://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/jangrayhood/
こんな話もあるようです。多重継承で仮想関数のthisからのエントリずれを補正するために、VisualC++ではadjuster thunkというものを使っているようですが、このthunkどこにあるんでしょう?調べておきます。コンパイラを更新するというのはこの話があるからなのかなぁ?

Posted by: Tetsu=TaLow | 2004.03.11 at 08:50 AM

いくつかの OS/プロセッサについて、ヒープの実行保護がどうなっているかを調べました。

日記 5/17分
http://www.shudo.net/diary/2004may.html#20040517

Linux 2.6.5 / Pentium 4 (Northwood) で保護ができたので、なんでだろう?と調べたら、exec-shield パッチがあたってました。
exec-shieldは、セグメント機構を使って頑張っているようです。面白いです。

Posted by: shudo | 2004.05.19 at 06:08 PM

すばらしい!ありがとうございました。exec-shieldそうなってたのかー。ちと調べてみます。

Posted by: Tetsu=TaLow | 2004.05.25 at 03:59 PM

http://d.hatena.ne.jp/hyoshiok/200407あたりにEM64TによるLinuxでの実装のお話を書きましたので御参考まで。

Posted by: hyoshiok | 2004.08.20 at 01:40 AM

Post a comment



(Not displayed with comment.)