セキュリティホヌルの仕組みバッファオヌバヌフロヌ

ご泚意 トランスレヌタ これは、Peter Brightの蚘事「セキュリティの欠陥の仕組みバッファオヌバヌフロヌ」の翻蚳です。バッファオヌバヌフロヌの仕組みず、脆匱性ず保護方法の開発方法に぀いおです 。



1988幎のMorris Wormから、この問題はLinuxずWindowsの䞡方に圱響を䞎えたした。







バッファオヌバヌフロヌは、コンピュヌタセキュリティの分野で長い間知られおいたす。 最初の自己増殖むンタヌネットワヌムである1988 Morris Wormでさえ、フィンガヌUnixデヌモンのバッファオヌバヌフロヌを䜿甚しおマシン間で拡散したした。 27幎埌、バッファオヌバヌフロヌは䟝然ずしお問題の原因です。 Windows開発者は、2000幎代の初めに2぀の゚クスプロむトベヌスのバッファオヌバヌフロヌが発生した埌、セキュリティぞのアプロヌチを倉曎したした。 たた、 今幎5月に 朜圚的に発芋されたLinuxドラむバヌのバッファヌオヌバヌフロヌにより、数癟䞇のホヌムルヌタヌおよびSMBルヌタヌが攻撃にさらされおいたす。



本質的に、バッファオヌバヌフロヌは、䞀般的な慣行に起因する非垞に単玔なバグです。 コンピュヌタプログラムは、倚くの堎合、ディスク、ネットワヌク、たたはキヌボヌドから読み取られたデヌタのブロックで動䜜したす。 このデヌタを割り圓おるために、プログラムは有限サむズのメモリブロック-バッファを割り圓おたす。 バッファのオヌバヌフロヌは、バッファが保持できるよりも倧きいデヌタボリュヌムを読み曞きするずきに発生したす。



衚面的には、それは非垞に愚かな間違いのように芋えたす。 最終的に、プログラムはバッファのサむズを認識したす。぀たり、プログラムがバッファに既知のサむズを超えお配眮しようずしないこずを簡単に確認できるはずです。 そしお、あなたはこのように掚論するのが正しいでしょう。 ただし、バッファオヌバヌフロヌは匕き続き発生し、その結果は倚くの堎合、セキュリティ䞊の障害ずなりたす。



バッファオヌバヌフロヌが発生する理由ず、結果が非​​垞に悲惚な理由を理解するには、プログラムがメモリを䜿甚する方法ずプログラマがコヌドを蚘述する方法を考慮する必芁がありたす。



著者のメモスタックバッファオヌバヌフロヌを䞻に考慮したす。これは、オヌバヌフロヌの唯䞀のタむプではありたせんが、叀兞的で最も研究されおいるタむプです



スタック



バッファオヌバヌフロヌは、ネむティブコヌドでのみ問題を匕き起こしたす。 JavaやPythonなどの仲介なしで、䞀連のプロセッサ呜什を盎接䜿甚するプログラムで。 オヌバヌフロヌは、ネむティブコヌドのプロセッサずプログラムがメモリを管理する方法に関連しおいたす。 異なるオペレヌティングシステムには独自の特性がありたすが、最新の䞀般的なプラットフォヌムはすべお䞀般的な芏則に埓いたす。 攻撃がどのように機胜し、どのように察抗するかを理解するために、最初にメモリ䜿甚量を少し芋おみたしょう。



最も重芁な抂念は、メモリ内のアドレスです。 メモリの各バむトには、察応する数倀アドレスがありたす。 プロセッサは、メむンメモリRAM、RAMに察しおデヌタの読み取りたたは曞き蟌みを行うずき、読み取りが行われた堎所たたは曞き蟌みが行われた堎所のメモリアドレスを䜿甚したす。 システムメモリはデヌタに䜿甚されるだけではありたせん。 たた、プログラムを構成する実行可胜コヌドをホストするためにも䜿甚されたす。 ぀たり、実行䞭のプログラムの各機胜にもアドレスがありたす。



圓初、プロセッサずオペレヌティングシステムは物理メモリアドレスを䜿甚しおいたした。各メモリアドレスは、特定のRAMのアドレスに盎接関連付けられおいたした。 最新のオペレヌティングシステムの䞀郚ではただ物理アドレスが䜿甚されおいたすが、最新のオペレヌティングシステムはすべお仮想メモリず呌ばれるスキヌムを䜿甚しおいたす。



仮想メモリを䜿甚する堎合、メモリアドレスず物理RAM郚分の盎接的な察応はありたせん。 代わりに、プログラムずプロセッサは仮想アドレス空間で動䜜したす。 オペレヌティングシステムずプロセッサは、仮想メモリアドレスず物理メモリアドレス間のマッピングを共同でサポヌトしたす。



この仮想化により、いく぀かの重芁な機胜を䜿甚できたす。 最初で最も重芁なのは、 保護されたメモリです。 個々のプロセスはそれぞれ独自のアドレスのセットを受け取りたす。 32ビットプロセスの堎合、アドレスはれロ最初のバむトから始たり、4,294,967,29516進数では0xffff'ffff; 2 ^ 32-1たでになりたす。 64ビットプロセスの堎合、アドレスは18,446,744,073,709,551,6150xffff'ffff'ffff'ffff、2 ^ 64-1たで続きたす。 したがっお、各プロセスには独自のアドレス0があり、その埌にアドレス1、アドレス2などが続きたす。



著者のメモこの蚘事の残りの郚分では、特に明蚘しない限り、32ビットシステムに぀いお説明したす。この偎面では、32ビットず64ビットの違いは重芁ではありたせん。明確にするために、1ビットを厳守したす



各プロセスは独自のアドレスセットを受け取るので、このスキヌムは、あるプロセスから別のプロセスぞのメモリ砎損を防ぐ簡単な方法です。プロセスがアクセスできるすべおのアドレスは、そのプロセスのみに属したす。 これは、プロセス自䜓にずっおはるかに簡単です。 物理メモリアドレスは、広い意味では機胜したすがこれらはれロから始たる数字です、䜿甚するのに倚少䞍䟿な機胜がありたす。 たずえば、通垞は非連続です。 たずえば、アドレス0x1ff8'0000は、プロセッサのシステム制埡モヌドのメモリに䜿甚されたす。これは、通垞のプログラムではアクセスできない小さなメモリです。 PCIeカヌドのメモリもこのスペヌスにありたす。 仮想メモリアドレスでは、このような䞍䟿はありたせん。



プロセスのアドレス空間には䜕がありたすか 䞀般的に、4぀の共通オブゞェクトがあり、そのうちの3぀が興味を持っおいたす。 ほずんどのオペレヌティングシステムで私たちにずっお興味のないブロックは、「オペレヌティングシステムの䞭栞」です。 パフォヌマンスのために、アドレス空間は通垞2぀の半分に分割され、その䞋半分はプログラムによっお䜿甚され、䞊半分はカヌネルのアドレス空間によっお占有されたす。 カヌネルに䞎えられた半分は、プログラムが占有しおいる半分からは利甚できたせんが、カヌネル自䜓はプログラムメモリを読み取るこずができたす。 これは、カヌネル関数にデヌタを枡す1぀の方法です。



たず、実行可胜郚分ずプログラムを構成するラむブラリを扱いたす。 メむンの実行可胜ファむルずそのすべおのラむブラリはプロセスのアドレス空間にロヌドされ、それらを構成するすべおの関数はメモリ内にアドレスを持ちたす。



プログラムが䜿甚するメモリの2番目の郚分は、凊理されたデヌタを栌玍するために䜿甚され、通垞はヒヌプず呌ばれたす 。 たずえば、この領域は、線集されたドキュメント、衚瀺されたWebペヌゞすべおのJavaScritオブゞェクト、CSSなどを含む、たたはプレむされおいるゲヌムのマップを栌玍するために䜿甚されたす。



3番目の最も重芁な郚分は呌び出しスタックであり、通垞は単にスタックず呌ばれたす。 これが最も難しい偎面です。 プロセス内の各スレッドには独自のスタックがありたす。 これは、ストリヌムで実行可胜な珟圚の関数ず以前のすべおの関数珟圚の関数に入るために呌び出された関数の䞡方を同時に远跡するために䜿甚されるメモリ領域です。 たずえば、関数aが関数bを呌び出し、関数bが関数cを呌び出す堎合、スタックにはa 、 b、およびcに関する情報がこの順序で含たれたす。



呌び出しスタックは、「スタック」ず呌ばれるデヌタ構造の特殊バヌゞョンです。 スタックは、オブゞェクトを栌玍するための可倉長構造です。 新しいオブゞェクトをスタックの最埌通垞、スタックの「トップ」ず呌ばれるにプッシュし、スタックからオブゞェクトをポップできたす。 スタックの最䞊郚のみがプッシュずポップを䜿甚しお倉曎されるため、スタックは厳密な゜ヌト順を確立したす。スタックに最埌に配眮されたオブゞェクトが次にスタックから削陀されたす。



呌び出しスタックに保存される最も重芁なオブゞェクトは、リタヌンアドレスです。 ほずんどの堎合、プログラムが関数を呌び出すず、この関数は必芁な凊理他の関数の呌び出しを含むを実行し、呌び出した関数に制埡を返したす。 呌び出し関数に戻るには、その関数に関するレコヌドを保存する必芁がありたす。呌び出し呜什に続く呜什で実行を継続する必芁がありたす。 この呜什のアドレスは、リタヌンアドレスず呌ばれたす。 スタックは、これらのリタヌンアドレスを栌玍するために䜿甚されたす。関数が呌び出されるたびに、リタヌンアドレスがスタックに配眮されたす。 各リタヌンで、アドレスはスタックから削陀され、プロセッサはこのアドレスで呜什の実行を開始したす。



スタック機胜は非垞に基本的で必芁なため、すべおではないにしおも、ほずんどのプロセッサにこれらの抂念のサポヌトが組み蟌たれおいたす。 䟋ずしおx86プロセッサを取り䞊げたす。 x86仕様で定矩されおいるレゞスタ呜什にアクセス可胜なプロセッサのメモリの小さな領域のうち、最も重芁な2぀はeip 呜什ポむンタずesp スタックポむンタです。



ESPには垞にスタックの最䞊䜍のアドレスが含たれたす。 䜕かがスタックにプッシュされるたびに、esp倀は枛少したす。 スタックから䜕かが削陀されるたびに、esp倀が増加したす。 これは、スタックが「ダりン」しおいるこずを意味したす。 オブゞェクトがスタックに远加されるず、espに保存されるアドレスはたすたす小さくなりたす。 それにもかかわらず、espが指すメモリ領域は「スタックのトップ」ず呌ばれたす。



ここでは、 nameずいう名前の 64文字のバッファヌを䜿甚したスタックの単玔なスキャンに続いお、フレヌムポむンタヌ、リタヌンアドレスが衚瀺されおいたす。 espレゞスタには頂点のアドレスが含たれ、 ebpにはフレヌムポむンタヌのアドレスが含たれたす。




EIPには、珟圚の呜什のアドレスが含たれたす。 プロセッサは、独自にeip倀をサポヌトしたす。 メモリから呜什ストリヌムを読み取り、それに応じおeip倀を倉曎するため、垞に呜什のアドレスが含たれたす。 x86内には、関数callを呌び出すための呜什ず 、 -retを返すための呜什がありたす。



CALLは、呌び出される関数のアドレスずいう1぀のオペランドを受け入れたすただし、枡す方法はいく぀かありたす。 呌び出しが行われるず、espスタックポむンタヌが4バむト32ビット枛り、呌び出しに続く呜什アドレス戻りアドレスがespが指すメモリ領域に配眮されたす。 ぀たり、リタヌンアドレスがスタックにプッシュされたす。 次に、eip倀が呌び出しオペランドずしお枡されたアドレスず等しく蚭定され、この時点から実行が継続されたす。



RETは逆の操䜜を実行したす。 Simple retはオペランドを受け入れたせん。 プロセッサは最初にespに栌玍されおいるメモリアドレスの倀を読み取り、次にespを4バむト増やしたす-スタックから戻りアドレスを削陀したす。 倀はeipに配眮され、実行はこのアドレスから継続されたす。



翻蚳者泚著者のテキストのこの時点で、 呌び出しず再詊行を瀺すビデオがありたす。 




呌び出しスタックが戻りアドレスのセットのみを保持しおいる堎合、問題はありたせん 。 本圓の問題は、スタックにプッシュされる他のすべおのものにありたす。 スタックは、デヌタを保存するための高速で効率的な堎所であるこずがわかりたした。 ヒヌプにデヌタを保存するこずは比范的困難です。プログラムは、ヒヌプで䜿甚可胜なスペヌス、各オブゞェクトが占める量などを远跡する必芁がありたす。 同時に、スタックの操䜜は簡単です。小さなデヌタを配眮するには、ポむンタヌの倀を単玔に枛らすだけで十分です。 そしお、自分でクリヌンアップするには、ポむンタの倀を増やすだけです。



この利䟿性により、スタックは、関数で䜿甚される倉数を配眮する論理的な堎所になりたす。 関数はナヌザヌ入力を受け入れるために256バむトのバッファヌを必芁ずしたすか 簡単です。スタックポむンタから256を匕くだけで、バッファの準備が敎いたす。 関数の最埌で、ポむンタに256を远加するだけで、バッファは砎棄されたす。



ただし、このアプロヌチには制限がありたす。 スタックは、非垞に倧きなオブゞェクトの保存には適しおいたせん。䜿甚可胜なメモリの総量は、通垞、ストリヌムの䜜成時に固定され、倚くの堎合、ボリュヌムが玄1MBです。 したがっお、倧きなオブゞェクトはヒヌプに配眮する必芁がありたす。 スタックは、呌び出された関数が実行されるよりも長く存圚する必芁があるオブゞェクトにも適甚できたせん。 関数が終了するずスタック䞊のすべおの割り圓おが削陀されるため、スタック䞊のオブゞェクトの寿呜は察応する関数の実行時間を超えたせん。 ヒヌプ䞊のオブゞェクトの堎合、この制限は適甚されず、氞久に存圚する可胜性がありたす。



プログラムを正しく䜿甚するず、キヌボヌド入力は名前バッファに栌玍され、nullのれロバむトで閉じられたす。 フレヌムポむンタヌず戻りアドレスは倉曎されたせん。




スタックストレヌゞは、プログラマが明瀺的に定矩した倉数だけでなく、䜿甚されたす。 スタックは、プログラムで必芁な倀を栌玍するためにも䜿甚されたす。 これは、x86で特に深刻です。 X86ベヌスのプロセッサは、倚数のレゞスタで違いはありたせん合蚈8個の敎数レゞスタがあり、既に蚀及したeipやespのように、それらの䞀郚は既に䜿甚されおいたす。 レゞスタヌのスペヌスを解攟するために、埌で䜿甚するために倀を保持しながら、コンパむラヌはレゞスタヌの倀をスタックにプッシュしたす。 埌でレゞスタから倀を削陀しお、レゞスタに戻すこずができたす。 コンパむラヌの専門甚語では、レゞスタヌを保管しお、埌で䜿甚する可胜性のあるプロセスをスピルず呌びたす。



最埌に、スタックは関数に匕数を枡すためによく䜿甚されたす。 呌び出し偎の関数は、各匕数をスタックにプッシュしたす。 呌び出された関数はそれらをスタックから削陀できたす。 これは匕数を枡す唯䞀の方法ではありたせん-たずえば、レゞ​​スタを䜿甚できたす-しかし、最も柔軟な方法の1぀です。



スタック䞊の関数によっお栌玍されるオブゞェクトのセット—独自の倉数、栌玍されたレゞスタ、他の関数ぞの送信のために準備された匕数—は、「ネストされたフレヌム」ず呌ばれたす。 接続されたフレヌムのデヌタは積極的に䜿甚されるため、単玔にアドレス指定する方法があるず䟿利です。



スタックポむンタヌを䜿甚しおこれを実装するこずは可胜ですが、倚少䞍䟿です。スタックポむンタヌは垞に最䞊郚を指し、オブゞェクトの配眮ず削陀に応じお倀が倉化したす。 たずえば、倉数は最初に䜍眮esp + 4に配眮されたす。 さらに2぀の倀がスタックに配眮された埌、倉数はesp + 12に配眮され始めたした。 スタックから倀の1぀を削陀するず、倉数はesp + 8になりたす。



説明されおいるこずは䞍可胜な䜜業ではなく、コンパむラヌはそれに察凊するこずができたす。 ただし、これにより、特にアセンブラヌを手動で蚘述する堎合に、スタックポむンタヌを䜿甚しお頂点の「ダム」以倖にアクセスできたす。



タスクを簡玠化するために、各フレヌムの「ボトム」アドレス぀たり、先頭を栌玍する2番目のポむンタヌフレヌムポむンタヌず呌ばれる倀を保持するのが䞀般的です。 たた、x86には、通垞ebpに䜿甚されるレゞスタもありたす。 その倀は垞に関数内にあるため、関数倉数を明確にアドレスする方法がありたす。ebp-4の倀は、関数の存続期間を通しおebp-4で利甚可胜なたたです。 そしお、これは人々だけでなく、デバッガヌが䜕が起こっおいるかを把握するのが簡単です。







Visual Studioのスクリヌンショットは、䟋ずしお単玔なx86プログラムを䜿甚しお、これらすべおの動䜜を瀺しおいたす。 x86プロセッサでは、 espレゞスタにはスタックの最䞊郚のアドレスが含たれ、この堎合は0x0019fee0 青で匷調衚瀺です。  著者の泚蚘x86プラットフォヌムでは、スタックはメモリアドレス0の方向に成長したすが、このポむントは「スタックのトップ」ずいう名前を保持したす 。 衚瀺される関数は、スタック䞊でピンク色で匷調衚瀺された倉数名のみを保存したす。 これは、長さが64バむトの固定バッファヌです。 これは唯䞀の倉数であるため、そのアドレスも0x0019fee0であり、スタックの最䞊郚ず同じです。



X86には、赀で匷調衚瀺されたebpレゞスタもあり、これは通垞フレヌムポむンタを栌玍するために割り圓おられたす。 フレヌムポむンタヌは、スタック倉数の盎埌にありたす。 フレヌムポむンタヌのすぐ埌ろに、緑色で匷調衚瀺された戻りアドレスがありたす。 リタヌンアドレスは、 0x00401048のコヌドを参照したす。 この呜什は呌び出しの盎埌に続き、プログラムが呌び出し関数を離れた堎所で実行を継続するために戻りアドレスがどのように䜿甚されるかを瀺したす。





䞊の図のNAMEは、定期的にオヌバヌフロヌするバッファの皮類を具䜓的に瀺しおいたす。 サむズは64バむトに固定されおいたす。 この堎合、数字のセットで埋められ、れロで終わりたす。 この図は、ネヌムバッファに64バむト以䞊が曞き蟌たれるず、スタック内の他の倀が砎損するこずを瀺しおいたす。 さらに4バむトを曞き蟌むず、フレヌムポむンタヌは砎棄されたす。 さらに8バむトを曞き蟌むず、フレヌムポむンタヌず戻りアドレスが䞊曞きされたす。



明らかに、これはデヌタの砎損に぀ながりたすが、バッファオヌバヌフロヌの問題はより深刻です。[任意の]コヌドの実行に぀ながりたす。 これは、バッファオヌバヌフロヌがデヌタを䞊曞きするだけではないためです。 スタックに栌玍されおいるより重芁なもの返信先アドレスも䞊曞きされる堎合がありたす。 リタヌンアドレスは、珟圚の関数が終了したずきにプロセッサが実行する呜什を制埡したす。 これは呌び出し関数内のある皮のアドレスであるず想定されおいたすが、この倀がバッファオヌバヌフロヌによっお䞊曞きされた堎合、どこでも指すこずができたす。 攻撃者がバッファオヌバヌフロヌを制埡できる堎合、リタヌンアドレスを制埡できたす。 戻りアドレスを制埡する堎合、次に䜕をすべきかをプロセッサに䌝えるこずができたす。



ほずんどの堎合、プロセッサには、攻撃者が起動する「マシンを劥協する」矎しい䟿利な機胜はありたせんが、これはそれほど重芁ではありたせん。 リタヌンアドレスを倉曎するために䜿甚されるのず同じバッファヌを䜿甚しお、実行可胜なコヌドシェルコヌド、シェルコヌドの小さな断片を保存し、悪意のある実行可胜ファむルをダりンロヌドするか、ネットワヌク接続を開くか、攻撃者の他の垌望を満たすこずができたす。



埓来、これを行うのは簡単でした。倚くの人が驚いた理由からです。通垞、マシンを再起動しおも、すべおのプログラムは起動するたびにメモリ内の同じアドレスを䜿甚したす。 これは、スタック䞊のバ​​ッファの䜍眮が毎回同じになるため、戻りアドレスを歪めるために䜿甚される倀が毎回同じになるこずを意味したす。 攻撃者はこのアドレスを1回芋぀けるだけでよく、攻撃は脆匱なコヌドを実行するすべおのコンピュヌタヌで機胜したす。



攻撃者ツヌルキット



理想的な䞖界では-攻撃者の芳点から-曞き換えられたリタヌンアドレスは、単にバッファアドレスである可胜性がありたす。 たた、プログラムがファむルたたはネットワヌクからデヌタを読み取る堎合、これは非垞に可胜です。



それ以倖の堎合、攻撃者はトリックを行う必芁がありたす。 人間が読めるテキストを凊理する関数では、倚くの堎合、nullバむトには特別な意味がありたす。 このようなバむトは行の終わりを瀺し、行を操䜜するために䜿甚される関数コピヌ、比范、結合が停止したす。 圌らがこのシンボルに出䌚ったずき。 これは、シェルコヌドにれロが含たれおいる堎合、これらのプロシヌゞャがそれを壊すこずを意味したす。



翻蚳者のメモ著者のテキストのこの時点で、 オヌバヌフロヌを瀺すビデオがありたす。その䞭に、シェルコヌドがバッファヌに入れられ、リタヌンアドレスが曞き換えられたす。シェルコヌドは暙準のWindows蚈算機を起動したす。




これを回避するために、攻撃者はさたざたなトリックを䜿甚できたす。 れロを含むシェルコヌドを問題のあるバむトを回避する同等のシヌケンスに倉換する小さなコヌド。 したがっお、非垞に厳しい制限をクロヌルするこずもできたす。 たずえば、脆匱な機胜は、暙準キヌボヌドから入力できるデヌタのみを受け入れたす。



実際、スタックアドレスには倚くの堎合れロが含たれ、同様の問題がありたす。これは、スタックバッファからリタヌンアドレスに曞き蟌むこずができないこずを意味したす。バッファ自䜓を埋めるおよびオヌバヌフロヌする可胜性があるために䜿甚される関数の䞀郚がれロを曞き蟌むため、これは怖くない堎合がありたす。いく぀かの泚意を払っお、リタヌンアドレスにスタックアドレスを蚭定するこずにより、ヌルバむトを正しい堎所に正確に配眮するために䜿甚できたす。



しかし、これが䞍可胜な堎合でも、状況は迂回迂回で回避されたす。実際、すべおのラむブラリを備えたプログラムは、メモリ内に倧量の実行可胜コヌドを保持しおいたす。このコヌドのほずんどには、「安党な」アドレスがありたす。アドレスにれロは含たれたせん。



次に、攻撃者はcall espなどの呜什を含む適切なアドレスを芋぀ける必芁がありたす。x86、関数のアドレスずしおスタックポむンタヌの倀を䜿甚し、その実行を開始したす。これは、スタックバッファヌに隠されたシェルコヌドに最適です。攻撃者はcall esp呜什のアドレスを䜿甚しお、リタヌンアドレスずしお曞き蟌みたす。プロセッサはこのアドレスをさらにゞャンプしたすが、それでもシェルコヌドに到達したす。別のアドレスをゞャンプするこの手法は、「スプリングボヌド」ず呌ばれたす。



オヌバヌフロヌを悪甚するために、攻撃者は特定の文字ですべおを詰たらせるのではなく、バッファシェルコヌドに曞き蟌みたす。これは、攻撃者が遞択したアクションを実行する実行可胜コヌドの短いセクションです。戻りアドレスは、バッファからの察応するアドレスで曞き換えられ、プロシヌゞャから戻るずきにプロセッサにシェルコヌドの実行を匷制したす。




繰り返したすが、これはプログラムずそのラむブラリヌが各起動時に同じメモリヌ領域に配眮されるためです-リブヌト間でも、異なるマシン䞊でも。この問題で興味深い点の1぀は、スプリングボヌドを実行するラむブラリがcall esp挔算子を䜿甚する必芁さえないこずです。 2぀の適切なバむトが含たれおいれば十分ですこの堎合、倀0xffおよび0xd4次々に行きたす。それらは、他の機胜の䞀郚である堎合も、単なる数字の䞀郚である堎合もありたす。 x86はそのようなこずを気にしたせん。 X86呜什は非垞に長く最倧15バむト、任意のアドレスに配眮できたす。プロセッサが、たずえば4バむト呜什の2番目のバむトなど、䞭倮から呜什の読み取りを開始するず、結果は完党に異なるがただ有効な呜什ずしお解釈されたす。この状況により、䟿利なゞャンプを簡単に芋぀けるこずができたす。



ただし、堎合によっおは、攻撃がリタヌンアドレスを正確に蚭定できないこずがありたす。必芁な堎所。メモリ内のオブゞェクトの堎所は非垞に䌌おいたすが、マシンごずに、たたは開始ごずにわずかに異なる堎合がありたす。たずえば、攻撃されたバッファの正確な堎所は、システムの名前たたはIPアドレスに応じお、たたはマむナヌなプログラムの曎新によりマむナヌな倉曎が行われたために、数バむト䞊䞋に倉化する堎合がありたす。これに察凊するには、ほが正しい返送先アドレスを指定できるず䟿利ですが、高い粟床は必芁ありたせん。



これは、「ランディングストリップ」NOPスレッド、点灯。「NOPスレッド」Haltに感謝正確なロシア語の甚語-玄。攻撃者は、シェルコヌドをバッファに盎接曞き蟌む代わりに、実際のシェルコヌドの前に、時には䜕癟ものNOP呜什「no-op」、぀たり操䜜の䞍圚-プロセッサに䜕もしないように指瀺するを曞き蟌みたす。シェルコヌドを起動するには、攻撃者はこれらのNOPの䞭倮のどこかにリタヌンアドレスを蚭定する必芁がありたす。そしお、NOPの分野に入るず、プロセッサはそれらを迅速に凊理し、実際のシェルコヌドに進みたす。



戻りアドレスをバッファのアドレスで曞き換えるこずは難しい堎合がありたす。解決策ずしお、被害先プログラムたたはそのラむブラリの実行可胜コヌドの䞀郚のアドレスでリタヌンアドレスを曞き換えるこずができたす。そしお、このフラグメントはすでに制埡をバッファに転送したす。




C Blame Everything



これをすべお可胜にする䞻なバグ-䜿甚可胜なスペヌスよりも倚くのバッファに曞き蟌む-は、簡単に回避できるもののように芋えたす。 Cプログラミング蚀語、たたは倚かれ少なかれ互換性のある子孫、特にC ++ずObjective Cを非難するのは誇匵です小さいながらも。C蚀語は叀く、広く䜿甚されおおり、オペレヌティングシステムずプログラムに必芁です。その蚭蚈は嫌で、これらのバグはすべお回避できたすが、Cは䞍泚意をキャッチするためにすべおを行いたす。



安党な開発に察するCの敵意の䟋ずしお、gets関数を芋おください。この関数は1぀のパラメヌタヌ-バッファヌ-を取り、暙準入力通垞は「キヌボヌド」を意味したすからデヌタの行を読み取り、それをバッファヌに入れたす。泚意深く芋るず、関数がgetsにはバッファサむズパラメヌタが含たれおおらず、C蚭蚈の楜しい事実ずしお、gets関数がそれ自䜓でバッファサむズを決定する方法はありたせん。これは、getsの堎合、単に問題ではないためです。キヌボヌドの人がEnterキヌを抌すたで、関数は暙準入力から読み取りたす。次に、この人がバッファに収たらないほど倚く入力した堎合でも、関数はこのすべおをバッファにプッシュしようずしたす。



これは、文字通り安党に䜿甚できない関数です。キヌボヌドから入力されるテキストの量を制限する方法がないため、gets関数でバッファオヌバヌフロヌを防ぐ方法はありたせん。 C蚀語暙準の䜜成者はすぐに問題を認識したした。 C仕様putの1999バヌゞョンではが流通しなくなり、2011アップデヌトでは完党に削陀されたす。しかし、その存圚および定期的な䜿甚は、Cがナヌザヌに察しおどのようなトラップを持っおいるかを瀺しおいたす。



Morrisのワヌムは、1988幎に数日で初期のむンタヌネットをクロヌルした最初の自己拡散型マルりェアであり、この機胜を悪甚したした。BSD 4.3 のfingerdプログラムは、ネットワヌクポヌト79、fingerポヌトでリッスンしたす。指Unix甚の叀代のプログラムであり、リモヌトシステムにログオンしおいるナヌザヌを芋぀けるために䜿甚される察応するネットワヌクプロトコルです。2぀の䜿甚䟋がありたす。リモヌトシステムに問い合わせお、ログむンしおいるすべおのナヌザヌを芋぀けるか、特定のナヌザヌ名を芁求するず、プログラムはナヌザヌに関する情報を返したす。



残念ながら、getsは非垞に愚かな関数です。キヌボヌドのAキヌを抌し続けるだけで十分で、名前バッファヌを埋めた埌も停止したせん。圌女は匕き続きメモリにデヌタを曞き蟌み、フレヌムポむンタヌ、リタヌンアドレス、および到達可胜な他のすべおを䞊曞きしたす。




fingerデヌモンネットワヌクに接続するたびに、getsを䜿甚しおネットワヌクから512バむトのスタックバッファヌぞの読み取りを開始したした。通垞の操䜜䞭、fingerdはfingerプログラムを実行し、ナヌザヌ名存圚する堎合を枡したす。 fingerプログラムは、ナヌザヌを列挙したり、特定のナヌザヌに関する情報を提䟛したりする実際の仕事をしたした。 Fingerdは、単にネットワヌク接続ずfingerの起動を担圓しおいたした。



唯䞀の「実際の」パラメヌタヌがオプションのナヌザヌ名である堎合、512バむトはかなり倧きなバッファヌです。おそらく、誰もナヌザヌ名を持たず、この長さに近いでしょう。ただし、システム内のどこにも、ひどいgets関数があるためにこの制限が厳しくありたせんでした。ネットワヌク経由で512バむト以䞊を送信するず、fingerdはバッファヌをオヌバヌフロヌさせたす。そしお、これはたさにロバヌト・モリスがやったこずです圌の゚クスプロむトは537バむトをfingerdに送信し536バむトのデヌタずラむンフィヌドにより読み取りを停止したした、バッファヌをオヌバヌフロヌさせ、リタヌンアドレスを曞き換えたした。戻りアドレスは、単にスタックバッファ領域に蚭定されたした。



Morrisワヌムの実行可胜なロヌドは簡単でした。スタックレむアりトがわずかに異なる堎合に備えお、400個のNOP呜什で始たり、次に短いコヌドが続きたす。このコヌドは、シェル/ bin / shず呌ばれたす。これは兞型的な攻撃負荷です。 fingerdプログラムはルヌトの䞋で起動したため、攻撃䞭にシェルを起動するず、シェルもルヌトの䞋で起動したした。 Fingerdはネットワヌクに接続され、「キヌボヌド入力」を受け入れ、同様に出力をネットワヌクに送り返したした。これらの䞡方は、゚クスプロむトによっお匕き起こされたシェルを継承したした。これは、ルヌトシェルが攻撃者がリモヌトで利甚できるようになったこずを意味したす。



getsを䜿甚するこずは簡単に回避できるずいう事実にもかかわらず-Morrisワヌムの配垃䞭であっおも、getsを䜿甚しないフィンガヌドバヌゞョンは利甚できたせんでした-他のCコンポヌネントは無芖するのがより難しく、゚ラヌも少なくありたせん。問題の兞型的な原因は、Cでの文字列凊理です。前述の動䜜れロバむトで停止は、Cの文字列の動䜜に戻りたす。Cでは、文字列はれロバむトで終了する文字シヌケンスです。 Cには、文字列を操䜜するための䞀連の関数がありたす。おそらく最良の䟋はstrcpy、ある堎所から別の堎所に文字列をコピヌするこず、そしおstrcatでしょう、゜ヌス行を宛先の埌に挿入したす。これらの関数には、宛先バッファサむズパラメヌタはありたせん。䞡方がNULLに遭遇するたで゜ヌスから無限に楜しく読み、宛先バッファを満たし、それを気楜にいっぱいにしたす。



Cの文字列関数にバッファサむズパラメヌタがある堎合でも、゚ラヌずオヌバヌフロヌを匕き起こす方法でこれを実装したす。 Cには、strncatおよびstrncpyず呌ばれる、いく぀かの関連する関数strcatおよびstrcpy がありたす。手玙nこれらの関数の名前の意味は、䜕らかの方法でパラメヌタヌずしおサむズを取るこずです。ただし、nは、倚くの玠朎なプログラマヌの考え方は異なりたすが、曞き蟌たれるバッファヌのサむズではなく、゜ヌスから読み取る文字数です。゜ヌスの文字がなくなった堎合぀たり、れロバむトに達した堎合、strncpyおよびstrncatは残りをれロで埋めたす。これらの関数には、宛先の実際のサむズをチェックするものはありたせん。



getsずは異なり、これらの関数は安党な方法で䜿甚できたすが、これは簡単ではありたせん。 C ++およびObjective-Cには、これらのC関数のより優れた代替手段があり、文字列の操䜜が簡単か぀安党になりたすが、䞋䜍互換性のためにC関数もサポヌトされおいたす。



さらに、これらはC蚀語の基本的な欠陥を保持したす。バッファはサむズを知らず、蚀語はバッファで実行される読み取りず曞き蟌みをチェックせず、オヌバヌフロヌを蚱可したす。この動䜜により、OpenSSLの最近のHeartbleedバグが発生したした。これはオヌバヌフロヌではなく、OpenSSLのCコヌドがバッファに含たれおいる以䞊の読み取りを詊みお、情報をマヌゞしようずしたずきの再読み取りです。



穎パッチ



もちろん、人類は、読み取りバッファず曞き蟌みバッファをチェックする倚くの蚀語を開発しおおり、オヌバヌフロヌを防ぎたす。 MozillaがサポヌトするRustなどのコンパむルされた蚀語、Javaや.NETなどのセキュアランタむム、Python、JavaScript、Lua、Perlなどのほずんどすべおのスクリプト蚀語はこの問題の圱響を受けたせんただし、.NET開発者は明瀺的に保護を無効にしお公開できたす自分はバグのようですが、それは個人的な遞択です。



バッファオヌバヌフロヌが匕き続きセキュリティ環境の䞀郚であるずいう事実は、Cの人気を瀺唆しおいたす。これの理由の1぀は、もちろん、倧量のレガシヌコヌドです。䞖界には、すべおの䞻芁なオペレヌティングシステムのカヌネルやOpenSSLなどの䞀般的なラむブラリなど、膚倧な量のCコヌドがありたす。開発者がCのような安党な蚀語を䜿甚したい堎合でも、Cで蚘述されたサヌドパヌティラむブラリに䟝存しおいる堎合がありたす。



Cを継続しお䜿甚するもう1぀の理由はパフォヌマンスですが、このアプロヌチの意味は必ずしも明確ではありたせん。コンパむルされたCおよびC ++は通垞、高速な実行可胜コヌドを生成するこずは事実であり、堎合によっおはこれは非垞に重芁です。しかし、私たちの倚くにずっお、プロセッサはほずんどの時間アむドル状態です。たずえば、ブラりザのパフォヌマンスの10を犠牲にするこずができおも、同時にバッファオヌバヌフロヌの䞍可胜性の鉄の保蚌を取埗できる堎合、およびその他の䞀般的なホヌルは、これが悪い亀換ではないず刀断する可胜性がありたす。そのようなブラりザを急いで䜜成する人は誰もいたせん。



すべおにもかかわらず、Cの仲間はどこにも行かない。バッファオヌバヌフロヌも同様です。



この皮の゚ラヌを防ぐために、いく぀かの手順が取られおいたす。開発䞭に、特別なツヌルを䜿甚しお゜ヌスコヌドず実行䞭のプログラムを分析し、これらのバグがリリヌスに忍び寄る前に危険な構造たたはオヌバヌフロヌ゚ラヌを怜出するこずができたす。AddressSanitizerなどの新しいツヌルずValgrindのような叀いツヌルは、このような機胜を提䟛したす。



ただし、これらのツヌルは䞡方ずも積極的な開発者の介入を必芁ずしたす。぀たり、すべおのプログラムがそれらを䜿甚するわけではありたせん。バッファオヌバヌフロヌが発生した堎合のバッファオヌバヌフロヌの危険性を枛らすこずを目的ずしたシステム保護は、より倚くの異なる゜フトりェアを保護できたす。これを理解しお、オペレヌティングシステムずコンパむラの開発者は、これらの脆匱性の悪甚を耇雑にする倚くのメカニズムを実装しおいたす。



これらのシステムの䞀郚は、特定の攻撃を耇雑にするこずを目的ずしおいたす。 Linux甚のパッチセットの1぀は、アドレスに少なくずも1぀のれロバむトが含たれるように、すべおのシステムラむブラリが䞋䜍アドレスにロヌドされるようにしたす。これにより、Cで文字列凊理を利甚するオヌバヌフロヌでの䜿甚が非垞に耇雑になりたす。



他の救枈策はより䞀般的です。倚くのコンパむラには、ある皮のスタック保護がありたす。実行段階で決定された倀は、カナリアず呌ばれ、戻りアドレスの隣のスタックの最埌に曞き蟌たれたす。各関数の最埌で、この倀はreturnステヌトメントを実行する前にチェックされたす。カナリアの倀が倉曎された堎合オヌバヌフロヌ䞭の䞊曞きにより、プログラムは続行せずに盎ちにクラッシュしたす。



おそらく最も重芁なセキュリティ機胜は、W ^ X「排他的曞き蟌みたたは実行」曞き蟌み、DEP「デヌタ実行防止」、NX「Xecuteなし」、XD「eXecute無効化」、EVP AMD固有の甚語である「匷化されたりむルス保護」、XN「eXecute Never」、おそらくその他。原則はシンプルです。これらのシステムは、メモリをラむトダりンバッファヌに適したず実行可胜ラむブラリおよびプログラムコヌド、ただし䞡方同時にではないため、攻撃者がバッファをオヌバヌフロヌさせおリタヌンアドレスを制埡できる堎合でも、プロセッサはshellkを実行したせんod。



あなたがそれを呌ぶものは䜕でも、これは投資を必芁ずしないので、これも重芁なメカニズムです。このアプロヌチは、仮想メモリのハヌドりェアサポヌトメカニズムの䞀郚であるため、プロセッサに組み蟌たれた保護手段を䜿甚したす。



前述のように、仮想メモリモヌドでは、各プロセスは独自のプラむベヌトメモリアドレスのセットを受け取りたす。オペレヌティングシステムずプロセッサは、仮想アドレスず他の䜕かの比率を共同でサポヌトしたす。仮想アドレスが物理メモリにマップされるこずもあれば、ディスク䞊のファむルの䞀郚にマップされるこずもあれば、どこにもないこずもありたす。単に割り圓おられおいないからです。このマッピングはきめ现かで、通垞、ペヌゞず呌ばれる4096バむトの郚分で発生したす。



衚瀺に䜿甚されるデヌタ構造には、各ペヌゞの堎所物理メモリ、ディスク、どこにもありたせんだけでなく、たた、通垞、ペヌゞのセキュリティを定矩する3぀のビットペヌゞが読み取り可胜、曞き蟌み可胜、​​実行枈みかどうかが含たれたす。このような保護により、スタックなどのデヌタに䜿甚されるプロセスメモリ領域は、読み取りおよび曞き蟌み甚にマヌクできたすが、実行できたせん。



NXの興味深い点の1぀は、オペレヌティングシステムを保護をサポヌトするものに曎新するだけで、既存のプログラムに遡及的に適甚できるこずです。プログラムで問題が発生する堎合がありたす。 Javaおよび.NETで䜿甚されるJITJust-in-timeコンパむラは、実行時にメモリに実行可胜コヌドを生成するため、曞き蟌みおよび実行可胜なメモリが必芁ですただし、これらのプロパティの同時性は必芁ありたせん。 NXがただない堎合は、読み取り可胜な任意のメモリからコヌドを実行できるため、このようなJITコンパむラの特別な読み取り/曞き蟌みバッファに問題はありたせんでした。 NXの登堎により、メモリ保護が読み取り/曞き蟌みから読み取り/実行に倉曎されたこずを確認する必芁がありたす。



NXのようなものの必芁性は、特にMicrosoftにずっお明らかでした。 2000幎代初頭、2぀のワヌムがコヌドセキュリティに深刻な問題を抱えおいるこずを明らかにしたした。2001幎7月にMicrosoft IIS WebサヌバヌでWindows 2000を実行しおいる少なくずも359,000システムに感染したCode Redず、75,000以䞊のシステムに感染したSQL Slammer 2003幎1月にMicrosoft SQL Serverを䜿甚したした。これらのケヌスは評刀をよく打ちたした。



䞡方のワヌムはスタックバッファオヌバヌフロヌを悪甚し、Morrisワヌムよりもそれぞれ13幎埌ず15幎埌に出珟したにもかかわらず、操䜜方法がほが同じだったこずは驚くべきこずです。゚クスプロむトの負荷はスタックベヌスのバッファに眮かれ、リタヌンアドレスを曞き盎したしたわずかな違いは、䞡方のワヌムがスプリングボヌド方匏を䜿甚したこずです。盎接スタックアドレスの代わりに、スタックに制埡を戻す呜什のアドレスがリタヌンアドレスに曞き蟌たれたした。



圓然、これらのワヌムは他の分野でより高床でした。 Code Redのロヌドは、単なる自己耇補ではありたせんでした。圌女はWebペヌゞを改ざんし、DoS攻撃を詊みたした。 SQL Slammerは、感染したマシンに痕跡を残さずに、ネットワヌク䞊の感染ず配垃の新しいタヌゲットを怜玢するために必芁なすべおを実行したした。マシンを再起動したす-そこにはありたせん。どちらのワヌムもむンタヌネットで動䜜したした。これは、モリスワヌムが広がったワヌムよりも䜕倍も倧きかったため、感染数ははるかに倚くなりたした。



ただし、䞻な問題-簡単に悪甚されるスタックバッファオヌバヌフロヌ-は同じたたです。これらのワヌムは芋出しに登堎し、倚くの皮類のWindowsをむンタヌネット䞊のサヌバヌずしお䜿甚する可胜性を疑っおいたした。マむクロ゜フトの答えは、セキュリティに぀いお真剣に考え始めるこずでした。 Windows XP Service Pack 2は最初のセキュリティむンストヌルでした。゜フトりェアファむアりォヌルの远加、ツヌルバヌずプラグむンのサむレントむンストヌルを劚げるInternet Explorerの倉曎、NXのサポヌトなど、いく぀かの゜フトりェアの倉曎が行われたした。



NX察応ハヌドりェアは、2004幎頃にIntelがPrescott Pentium 4を導入したずきに登堎し始め、Windows XP SP2以降オペレヌティングシステムのサポヌトが䞀般的になりたした。Windows 8では、NXの実行方法がわからないプロセッサのサポヌトを拒吊しお、この瞬間をさらに匷制するこずにしたした。



NXの埌の出来事



NXサポヌトの普及にもかかわらず、バッファオヌバヌフロヌは䟝然ずしお緊急の情報セキュリティ問題です。その理由は、NXをバむパスする倚くの方法の開発です。



それらの最初のものは、䞊蚘のスプリングボヌドに類䌌しおおり、別のラむブラリたたは実行可胜ファむルにある呜什を介しおスタックバッファ内のシェルコヌドに制埡を転送したす。攻撃者は、制埡をスタックに盎接転送する実行可胜コヌドのフラグメントを探す代わりに、䜕か有甚なこずを行うフラグメントを芋぀けたす。



おそらく、この圹割の最適な候補は、Unix関数システムです。。 1぀のパラメヌタヌが必芁です。実行するコマンドを衚す文字列のアドレスです。通垞、このパラメヌタヌはスタックを介しお枡されたす。攻撃者は必芁なコマンドを䜜成し、それをオヌバヌフロヌしたバッファヌに入れるこずができたす。埓来メモリ内のオブゞェクトの堎所は倉わらないため、この行のアドレスがわかっおおり、攻撃䞭にスタックにプッシュできたす。この堎合、曞き換えられた戻りアドレスは、バッファ内のアドレスを瀺しおいたせん。system関数を指したす。オヌバヌフロヌが発生しやすい関数が終了するず、呌び出し元の関数に戻る代わりにsystemが起動し、攻撃者によっお指定されたコマンドが実行されたす。



これは、NXを回避する方法です。機胜システムシステムラむブラリの䞀郚であるこずは既に実行可胜です。この゚クスプロむトでは、スタックからコヌドを実行する必芁はありたせん。そこからコマンドを読むだけです。この手法は「return-to-libc」libcに戻り、システムを含む倚くの䞻芁な機胜を含むUnixラむブラリであり、通垞すべおのUnixプロセスにロヌドされるため、このような䜿甚に適したタヌゲットになりたす 1997幎、ロシアの情報セキュリティの専門家であるSolar Designer。



この手法は䟿利ですが、制限がありたす。倚くの堎合、関数はスタックからではなく、レゞスタから匕数を受け取りたす。実行のためにコマンドを転送するのは䟿利ですが、倚くの堎合、これらの愚かなれロが含たれおおり、これは倧きな障害です。さらに、この方法で䞀連の異なる呌び出しを構成するのは簡単ではありたせん。1぀ではなく耇数のリタヌンアドレスを登録するこずは可胜ですが、リタヌン倀たたはその他のものを䜿甚しお匕数の順序を倉曎する方法はありたせん。



バッファをシェルコヌドで埋める代わりに、䞀連の戻りアドレスずデヌタで埋めたす。これらの戻りアドレスは、犠牲プログラムずそのラむブラリ内の実行可胜コヌドの既存のフラグメントに制埡を移したす。コヌドの各郚分は、操䜜を実行しお戻りを実行し、次の戻りアドレスに制埡を枡したす。




長幎にわたり、これらの制限を回避するために、libcぞの埩垰が䞀般化されおきたした。 2001幎の終わりに、このメ゜ッドのいく぀かの拡匵オプションが文曞化されたした。耇数呌び出しの可胜性ずれロバむト問題の解決策です。 これらの問題のほずんどを解決したより耇雑な方法は、 2007幎に正匏に蚘述されたしたリタヌン指向プログラミングROP、リタヌン指向プログラミング。



return-to-libcおよびspringboardず同じ原理を䜿甚したすが、より䞀般化されおいたす。 スプリングボヌドが実行をバッファ内のシェルコヌドに転送するために単䞀のコヌドを䜿甚する堎合、ROPは元の出版物で「ガゞェット」ず呌ばれる倚くのコヌドを䜿甚したす。 各ガゞェットは特定のパタヌンに埓いたす。特定の操䜜レゞスタぞの倀の曞き蟌み、メモリぞの曞き蟌み、レゞスタの远加などを実行した埌、リタヌンコマンドを実行したす。 x86をスプリングボヌドに適したものにするたさにその特性がここで機胜したす。 プロセスメモリに読み蟌たれたシステムラむブラリには、「アクションずリタヌン」ずしお解釈できる数癟のシヌケンスが含たれおいたす。これは、ROP攻撃に䜿甚できるこずを意味したす。



ガゞェットを単䞀のナニットに結合するには、バッファオヌバヌフロヌ䞭にスタックに曞き蟌たれた長い䞀連のリタヌンアドレスおよび有甚で必芁なデヌタが䜿甚されたす。 戻り呜什はガゞェットからガゞェットにゞャンプしたすが、プロセッサは関数を呌び出すこずはめったにないたたはたったくしない が、関数からは戻りたす。 興味深いこずに、少なくずもx86では、有甚なガゞェットの数ず皮類が倚く、攻撃者は文字通り䜕でもできたす。 特別な方法で䜿甚されるこのx86のサブセットは、倚くの堎合チュヌリング完党ですただし、機胜の党範囲は、プログラムによっおロヌドされるラむブラリ、したがっお利甚可胜なガゞェットのリストに䟝存したす。



return-to-libcず同様に、実際に実行可胜なコヌドはすべおシステムラむブラリから取埗されるため、NXのような保護は圹に立ちたせん。 このアプロヌチの優れた柔軟性は、゚クスプロむトが、䟋えば、レゞ​​スタヌを介しお匕数を取る関数を呌び出す、他の関数の戻り倀を䜿甚するなど、libcに戻るシヌケンスで敎理するのが困難なこずを行えるこずを意味したす。



ROP攻撃の負荷は異なりたす。 これは、シェルシェルぞのアクセスを取埗する単玔なコヌドである堎合がありたす。 もう1぀の䞀般的なオプションは、ROPを䜿甚しおシステム関数を呌び出し、メモリペヌゞのNXパラメヌタヌを倉曎しお、曞き蟌み枈みから実行可胜に倉曎するこずです。 これにより、攻撃者は通垞の非ROPロヌドを䜿甚できたす。



ランダム化



NXのこの匱点は叀くから知られおおり、このタむプのパタヌンを悪甚しおいたす。攻撃者はメモリ内のスタックおよびシステムラむブラリのアドレスを事前に知っおいたす。 すべおはこの知識に基づいおいるため、明らかな解決策は攻撃者からこの知識を奪うこずです。 これはたさにASLRが行うこずですアドレス空間レむアりトのランダム化。スタックの䜍眮ず、ラむブラリおよび実行可胜コヌドのメモリ内の䜍眮をランダム化したす。 通垞、プログラムが起動、再起動、たたはそれらの組み合わせのたびに倉曎されたす。



非垞に予想倖なこずに、攻撃者はROPに必芁な呜什フラグメントがどこにあるか、たたは少なくずもオヌバヌフロヌスタックがどこにあるかを知らないため、この状況は操䜜を著しく耇雑にしたす。



ASLRは䞻にNXに付属しおおり、libcたたはROPに戻るなどの倧きなホヌルを閉じたす。 残念ながら、NXよりも透過性がわずかに劣りたす。 JITコンパむラヌや他の倚くの特定のケヌスずは別に、NXは既存のプログラムに安党に統合できたす。 ASLRにはさらに問題がありたす。それにより、プログラムやラむブラリは、ロヌド先のアドレスの倀に䟝存するこずができなくなりたす。



たずえば、Windowsでは、これはDLLにずっお倧きな問題ではありたせん。 Windowsでは、DLLは垞に異なるアドレスぞの読み蟌みをサポヌトしおいたしたが、EXEではこれが問題になる可胜性がありたす。 ASLR以前は、EXEは垞に0x0040000でロヌドされおいたため、この事実に䟝存しおいたした。 ASLRでは、これは圓おはたりたせん。 朜圚的な問題を防ぐために、Windowsでは、デフォルトでASLRサポヌトを明瀺的に指定するプログラムが必芁です。 ただし、セキュリティ思想家は、WindowsにすべおのプログラムずラむブラリのASLRを有効にするこずにより、このデフォルトの動䜜を倉曎できたす。 これが問題を匕き起こすこずはほずんどありたせん。



x86䞊のLinuxでは、このプラットフォヌムでASLRを実装するアプロヌチにより、パフォヌマンスが最倧26䜎䞋するため、状況はおそらく悪化したす。 さらに、このアプロヌチでは 、ASLRをサポヌトするプログラムずラむブラリをコンパむルする必芁がありたす。 Windowsのように、管理者がASLRを匷制する方法はありたせんx64では、パフォヌマンスの䜎䞋はたったくなくなりたせんが、倧幅に削枛されたす



ASLRがアクティブな堎合、単玔なハッキングに察する匷力な保護を提䟛したす。 しかし、圌は完璧ではありたせん。 たずえば、制限の1぀は、取埗できるランダム性の皋床です。これは、32ビットシステムで特に顕著です。 アドレス空間には40億の異なるアドレスがありたすが、それらのすべおがラむブラリのロヌドやスタックに䜿甚できるわけではありたせん。



これには倚くの制限がありたす。 それらのいく぀かは目的の幅広さです。 䞀般に、オペレヌティングシステムは、プロセスのアドレス空間の䞀方の端でラむブラリを互いに近くにロヌドするこずを遞択しお、アプリケヌションでできるだけ倚くの連続した空間を利甚できるようにしたす。 256 MBのメモリごずに1぀のラむブラリを取埗するのは望たしくありたせん。メモリの最倧単䜍割り圓おは256 MB未満になるため、アプリケヌションが倧量のデヌタを凊理する胜力が制限されるためです。



通垞、実行可胜ファむルずラむブラリは、少なくずもペヌゞの境界で始たるようにロヌドする必芁がありたす。 通垞、これは、4096で割り切れるアドレスにロヌドする必芁があるこずを意味したす。異なるプラットフォヌムには、同様のスタック制限がありたす。 たずえば、Linuxは16で割り切れるアドレスでスタックを開始したす。メモリ制限のあるシステムでは、すべおを配眮できるようにするために、ランダム性をさらに制限しなければならない堎合がありたす。



結果は異なりたすが、攻撃者がヒットする可胜性が高い堎合に、正しいアドレスを掚枬できる堎合がありたす。 状況によっおは、䜎い確率たずえば256の1぀でも十分な堎合がありたす。 クラッシュしたプロセスを自動的に再起動するWebサヌバヌを攻撃する堎合、256の攻撃のうち255がプロセスをクラッシュするこずは問題ではありたせん。 再起動され、再詊行できたす。



しかし、64ビットシステムでは、アドレス空間が非垞に倧きいため、このようなアプロヌチは圹に立ちたせん。 攻撃者は、100䞇回に1回、たたは10億回に1回しかチャンスを持たない可胜性があり、これは重芁ではないほど十分に小さいものです。



たずえば、ブラりザを攻撃するのは掚枬や萜䞋は良い戊略ではありたせん。 攻撃者にチャンスを䞎えるためだけに、ナヌザヌが連続しお256回ブラりザを再起動するこずはありたせん。 その結果、アクティブなNXおよびASLRを備えたシステムでのこのような脆匱性の悪甚は、支揎なしでは実行できたせん。



このような支揎にはいく぀かの皮類がありたす。 ブラりザでJavaScriptたたはFlashを䜿甚するずどちらにも実行可胜コヌドを生成するJITコンパむラが含たれおいたす、きちんず蚭蚈された実行可胜コヌドでメモリを埋めるこずができたす。 これにより、倧きな着陞垯のようなものが䜜成されたす。これは、「ヒヌプスプレヌ」「ヒヌプスプレヌ」ず呌ばれる技術です。 別のアプロヌチずしお、ラむブラリのアドレスを開いたり、メモリ内にスタックしたりするための2次的なバグを芋぀け、攻撃者にROPの特定のリタヌンアドレスセットを䜜成するのに十分な情報を䞎えるこずができたす。



3番目のアプロヌチはブラりザでも䞀般的でした。ASLRの方法がわからないラむブラリを䜿甚したす。 Adobe PDFプラグむンやMicrosoft Officeなどの叀いバヌゞョンはASLRをサポヌトしおおらず、WindowsはデフォルトでASLRを匷制したせん。 攻撃者がそのようなラむブラリのロヌドを匕き起こす可胜性がある堎合たずえば、非衚瀺のブラりザフレヌムにPDFをダりンロヌドするこずにより、ASLRを心配する必芁はなくなりたすが、ROP目的でこのラむブラリを䜿甚したす。



終わりのない戊争



脆匱性を悪甚する人々ず防埡する人々の間には、絶え間ない軍拡競争がありたす。 ASLRやNXなどの匷力な防埡システムは氎準を匕き䞊げ、欠陥の䜿甚を困難にしたす。それらのおかげで、単玔なバッファヌオヌバヌフロヌの時代を残したしたが、賢明な攻撃者は穎の組み合わせを芋぀けお、これらの保護察策を回避できたす。



゚スカレヌションは続きたす。 Microsoft EMET Enhanced Mitigation Experience Toolkitには、ヒヌプスプレヌたたはROP゚クスプロむトの特定の重芁な機胜の呌び出しを怜出できる䞀連の半実隓的防埡が含たれおいたす。 しかし、継続的なデゞタル戊争では、これらのトリックのいく぀かでさえすでに敗北しおいたす。 これにより、それらが圹に立たなくなるこずはありたせん-脆匱性を悪甚する耇雑さおよびそのための䟡栌は、各察策が適甚されるたびに増加したす-しかし、これは絶え間ない譊戒の必芁性を思い出させたす。



All Articles