32

バッファ オーバーフローについて聞いたことがありますが、その原因を知りたいです。

誰かが小さなバッファ オーバーフローの例を見せてもらえますか? 新しい(そして、それらは何に使用されますか?)

4

12 に答える 12

33

バッファ オーバーフローの古典的な例:

// noone will ever have the time to type more than 64 characters...
char buf[64];
gets(buf); // let user put his name

ほとんどの場合、バッファ オーバーフローだけが意図的に発生することはありません。これは、いわゆる「off-by-one」エラーが原因で最も頻繁に発生します。配列サイズの計算を 1 つ間違えたことを意味します。おそらく、終端の null 文字を考慮するのを忘れたか、その他の理由が原因です。

しかし、それはいくつかの邪悪なものにも使用できます。実際、ユーザーはこの穴を長い間知っていて、たとえば 70 文字を挿入します。最後の文字には、スタックスロットを上書きする特別なバイトが含まれています。ユーザーが入力したのは名前ではなく、以前にコンパイルしてダンプしたシェルコードだったからです。それが実行されます。いくつかの問題があります。たとえば、そのバイナリ コードに "\n" を含めないようにする必要があります (gets がそこで読み取りを停止するため)。危険な文字列関数を混乱させる他の方法では、文字列関数がバッファへのコピーを停止するため、バイナリ ゼロが問題になります。人々は使用しましたxorゼロバイトを明示的に書き込まずに、同じ値を2回使用してゼロも生成します。

それが古典的なやり方です。しかし、そのようなことが起こったことを伝えることができるいくつかのセキュリティ ブロックや、スタックを実行不可能にするその他のものがあります。しかし、今説明したよりもはるかに優れたトリックがあると思います。一部のアセンブラーの男は、おそらくそれについて長い話をすることができます:)

それを回避する方法

バッファが実際に十分な大きさであるかどうか100%確信が持てない場合は、最大長の引数を取る関数も常に使用してください。「ああ、数が5文字を超えない」などのゲームをプレイしないでください。いつか失敗します。科学者がその数がある程度の大きさを超えることはないと述べたあるロケットを思い出してください。しかし、ある日、それ実際にはより速くなり、その結果、整数オーバーフローが発生し、ロケットがクラッシュしました (これは、歴史上最も高価なコンピューター バグの 1 つであるAriane 5のバグに関するものです)。

たとえば、 gets の代わりに use を使用しますfgetssprintfそして、適切で利用可能な場所で使用する代わりにsnprintf(または istream などの C++ スタイルのものだけを使用する)

于 2009-02-22T02:27:43.383 に答える
28

バッファ オーバーフローは、基本的に、メモリの細工されたセクション (またはバッファ) が意図した範囲外に書き込まれた場合です。攻撃者がプログラムの外部からこれを行うことができた場合、任意のメモリ位置を操作できる可能性があるため、セキュリティ上の問題が発生する可能性がありますが、最新のオペレーティング システムの多くはこのような最悪のケースから保護しています。

意図した範囲外での読み取りと書き込みは一般に悪い考えと見なされますが、「バッファ オーバーフロー」という用語は、一般に、境界外での書き込みに対して予約されています。これは、攻撃者がコードの実行方法を簡単に変更できるようにするためです。ウィキペディアには、バッファー オーバーフローと、それらを悪用するさまざまな方法に関する優れた記事があります。

自分でプログラムする方法に関しては、次の簡単な問題になります。

char a[4];
strcpy(a,"a string longer than 4 characters"); // write past end of buffer (buffer overflow)
printf("%s\n",a[6]); // read past end of buffer (also not a good idea)

それがコンパイルされるかどうか、および実行時に何が起こるかは、おそらくオペレーティング システムとコンパイラに依存します。

于 2009-02-22T02:12:27.507 に答える
13

最新の Linux OS では、余分な実験を行わないと、バッファ オーバーフローを悪用することはできません。なぜ ?この最新の GNU C コンパイラでは、 ASLR (Address Stack Layer Randomization) とスタック プロテクターによってブロックされるためです。ASLRによってメモリがランダム メモリに分類されるため、メモリを簡単に見つけることはできません。プログラムをオーバーフローさせようとすると、スタック プロテクターによってブロックされます。

最初に、ASLR を 0 にする必要があります。デフォルト値は 2 です。

root@bt:~# cat /proc/sys/kernel/randomize_va_space
2
root@bt:~# echo 0 > /proc/sys/kernel/randomize_va_space
root@bt:~# cat /proc/sys/kernel/randomize_va_space
0
root@bt:~#

これは、インターネットから入手した OLD STYLE バッファ オーバーフロー チュートリアルに関するものではありません。または aleph one チュートリアルは、システムで機能しなくなりました。

バッファ オーバーフロー シナリオに対するプログラムの脆弱性を作成できるようになりました

---------------------bof.c--------------------------
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
        char buffer[400];
        strcpy(buffer, argv[1]);

        return 0;
}
---------------------EOF-----------------------------

strcpy 関数を見ると、入力するバイト数をチェックせずに機能するため、スタックプロテクターなしでは危険です。C プログラムでスタック プロテクターをオフにするための追加オプション-fno-stack-protector dan -mpreferred-stack-boundary=2を使用してコンパイルします。

root@bt:~# gcc -g -o bof -fno-stack-protector -mpreferred-stack-boundary=2 bof.c
root@bt:~# chown root:root bof
root@bt:~# chmod 4755 bof

バッファー オーバーフロー SUID ルート アクセス シナリオを使用した C プログラムを作成しました。次に、プログラムのセグメンテーション違反を発生させるためにバッファに入れる必要があるバイト数を検索してみましょう

root@bt:~# ./bof `perl -e 'print "A" x 400'`
root@bt:~# ./bof `perl -e 'print "A" x 403'`
root@bt:~# ./bof `perl -e 'print "A" x 404'`
Segmentation fault
root@bt:~#

プログラムのセグメンテーション違反 (クラッシュ) を発生させるには 404 バイトが必要であることがわかります。EIPを上書きするには何バイト必要ですか? EIP 命令は後に実行されます。そのため、ハッカーは、プログラムのバイナリ SUID で必要なEIPを悪意のある命令に上書きします。プログラムが SUID ルートにある場合、命令はルート アクセスで実行されます。

root@bt:~# gdb -q bof
(gdb) list
1       #include <stdio.h>
2       #include <string.h>
3
4       int main(int argc, char** argv)
5       {
6               char buffer[400];
7               strcpy(buffer, argv[1]);
8
9               return 0;
10      }
(gdb) run `perl -e 'print "A" x 404'`
Starting program: /root/bof `perl -e 'print "A" x 404'`

Program received signal SIGSEGV, Segmentation fault.
0xb7e86606 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) run `perl -e 'print "A" x 405'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 405'`

Program received signal SIGSEGV, Segmentation fault.
0xb7e800a9 in ?? () from /lib/tls/i686/cmov/libc.so.6
(gdb)

プログラム GOT セグメンテーション違反の戻りコード。さらにバイトを入力して、EIP レジスターを見てみましょう。

(gdb) run `perl -e 'print "A" x 406'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 406'`

Program received signal SIGSEGV, Segmentation fault.
0xb7004141 in ?? ()
(gdb)

(gdb) run `perl -e 'print "A" x 407'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 407'`

Program received signal SIGSEGV, Segmentation fault.
0x00414141 in ?? ()
(gdb)

もう少し

(gdb) run `perl -e 'print "A" x 408'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 408'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)

(gdb) i r
eax            0x0      0
ecx            0xbffff0b7       -1073745737
edx            0x199    409
ebx            0xb7fc9ff4       -1208180748
esp            0xbffff250       0xbffff250
ebp            0x41414141       0x41414141
esi            0x8048400        134513664
edi            0x8048310        134513424
eip            0x41414141       0x41414141 <-- overwriten !!
eflags         0x210246 [ PF ZF IF RF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
(gdb)

これで次のステップに進むことができます...

于 2010-12-07T09:31:54.040 に答える
10

バッファ オーバーフローは、バッファの末尾を超えて書き込むだけです。

int main(int argc, const char* argv[])
{
    char buf[10];
    memset(buf, 0, 11);
    return 0;
}
于 2009-02-22T02:11:42.627 に答える
5

既に述べたことに加えて、バッファ オーバーフローが発生したときにプログラムが「クラッシュ」する場合としない場合があることに注意してください。クラッシュするはずです。クラッシュすることを願っていますが、バッファ オーバーフローがアプリケーションが割り当てた別のアドレスに「オーバーフロー」した場合、アプリケーションは長時間正常に動作しているように見える場合があります。

Microsoft Visual Studio の新しいエディションを使用している場合は、sprintf の代わりに sprintf_s など、stdlib で新しい安全な対応物を使用することをお勧めします...

于 2009-02-22T02:21:43.630 に答える
1

プログラムのバッファオーバーフローをチェックしたい場合は、Valgrindなどのツールを使用して実行できます。彼らはあなたのためにいくつかのメモリ管理のバグを見つけるでしょう。

于 2009-02-22T09:03:14.663 に答える
1

これはそれを再現するのに十分なはずです:

void buffer_overflow() 
{
    char * foo = "foo";
    char buffer[10];

    for(int it = 0; it < 1000; it++) {
        buffer[it] = '*';
    }

    char accessViolation = foo[0];
}
于 2009-02-22T02:21:31.540 に答える
1

これは、受け取った回答に関する一般的なコメントです。例えば:

int main(int argc, char *argv[])
{
    char buffer[10];
    strcpy(buffer, argv[1]);
}

と:

int main(int argc, const char* argv[])
{
    char buf[10];
    memset(buf, 0, 11);
    return 0;
}

最新の Linux プラットフォームでは、これは期待または意図したとおりに機能しない場合があります。FORTIFY_SOURCE セキュリティ機能のため、動作しない場合があります。

memcpyFORTIFY_SOURCE は、 や などのリスクの高い関数の「より安全な」バリアントを使用しstrcpyます。コンパイラは、宛先バッファー サイズを推測できる場合、より安全なバリアントを使用します。コピーがコピー先のバッファ サイズを超える場合、プログラムは を呼び出しますabort()

テストのために FORTIFY_SOURCE を無効にするには、-U_FORTIFY_SOURCEまたはを使用してプログラムをコンパイルする必要があります-D_FORTIFY_SOURCE=0

于 2014-09-12T13:25:30.063 に答える
1

「古典的な」バッファオーバーフローの例は次のとおりです。

int main(int argc, char *argv[])
{
    char buffer[10];
    strcpy(buffer, argv[1]);
}

これにより、バッファ オーバーフロー パラメータをいじって、思いのままに微調整できます。本 " Hacking - The Art of Exploitation " (リンクは Amazon に移動します) は、バッファ オーバーフローをいじる方法について非常に詳細に説明しています (純粋に知的な演習として)。

于 2009-02-22T03:44:31.513 に答える
0

このコンテキストでは、バッファは特定の目的のために取っておかれるメモリの一部であり、バッファ オーバーフローは、バッファへの書き込み操作が最後を超え続けたときに発生するものです (別の目的を持つメモリへの書き込み)。これは常にバグです。

バッファ オーバーフロー攻撃は、このバグを利用して、プログラムの作成者が意図していないことを実行する攻撃です。

于 2009-02-22T02:11:51.407 に答える
0

正解は次のとおりです。このトピックについて詳しく知りたい場合は、Podcast Security Now を聞くことをお勧めします。エピソード 39 (少し前) で、彼らはこれについて深く議論しました。これは、本全体を消化する必要なく、より深い理解を得るための迅速な方法です。

(リンクには、複数のサイズのバージョンとトランスクリプトを含むアーカイブがあります。視覚的に重視している場合)。オーディオはこのトピックに最適な媒体ではありませんが、Steve はこれに対処するために驚異的な作業を行っています。

于 2009-02-22T08:33:07.077 に答える
0

バッファ オーバーフローは、割り当てられたメモリが保持できる範囲を超えて文字が挿入されることです。

于 2019-05-05T11:07:47.703 に答える