5

私はC/C ++でのソケットプログラミングを紹介し、ソケットを介してクライアントプログラムとサーバープログラム間でデータを交換するために使用send()しています。recv()TCP

これが私のコードからのいくつかの関連する抜粋です:

server.c

char recv_data[1024];

// Socket setup and so on ommited...

bytes_recieved = recv(connected, recv_data, 1024, 0);
recv_data[bytes_recieved] = '\0';

client.c:

char send_data[1024];

// Setup ommited...

send(connected, send_data, strlen(send_data), 0);

recv()それ自体がバッファオーバーフローに対する保護を提供しますか?たとえば、3番目の引数を(たとえば4000)recv()が指すバッファよりも高い値に変更した場合、recv_dataこれによりバッファオーバーフローが発生しますか?(私は実際にこれを試しましたが、セグメンテーション違反をトリガーできないようです)。

私は実際に、これらの問題をよりよく理解するために意図的に脆弱なサーバープログラムを作成しようとしています。そのため、を介してオーバーフローを試みましたrecv()

修正

無関係ではありませんが、上記がで指定されclient.cたバイトを超えるバイトを送信する理由を見つけることになります。標準入力からそのバッファにデータを入力するために使用していますが、標準入力を介して1024バイトを超える数を入力すると、プログラムはすべてのバイトを受信することを示します。:)。forは送信されるバイト数を制限しませんか?1024strlen(send_data)gets(send_data)server.cstrlen(send_data)send()

4

3 に答える 3

10

たとえば、recv()の3番目の引数をrecv_dataが指すバッファーよりも高い値(例:4000)に変更した場合、これによりバッファーオーバーフローが発生しますか?

もちろんはい。ネットワークバッファに4000バイトのデータがある場合、それをバッファに入れます。重要な点は、バッファを取得する他のC APIと同様に、その長さは、呼び出し元がバッファの実際の長さを渡すと信じており、呼び出し元が誤った長さを渡す場合、障害は呼び出し元にあり、それがつながる可能性があるということです。未定義の動作に。

Cでは、配列を関数に渡すときに、呼び出された関数が配列のサイズを知る方法はありません。したがって、すべてのAPIは、ユーザーから提供された入力に依存します。

char recv_data[1024];

// Socket setup and so on ommited...

bytes_recieved = recv(connected, recv_data, 1024, 0);
recv_data[bytes_recieved] = '\0';

上記のコードは、1つ以上の方法で問題を引き起こす可能性があります。次の条件下では、未定義の動作が発生します。
(a)recvがを返す 場合-1、戻り値をチェックせずに、recv_dataバッファに直接インデックスを作成します。サイズの配列はからにアクセスする必要があります。
1024102401023

于 2013-03-03T15:46:52.667 に答える
5

これ

recv_data[bytes_recieved] = '\0';

1024バイトを受信した場合、バッファオーバーフローが発生する可能性があります。

あなたはこれを変更したいかもしれません

bytes_recieved = recv(connected, recv_data, 1024, 0);

になる

bytes_recieved = recv(connected, recv_data, 1024 - 1, 0);

そのため、 。bytes_recievedの最大有効インデックスである1023より大きくなることはありませんrecv_data


また、システムコール(recv()/ send())にはエラーチェックがありません。-1他の方法で結果を使用する前に、戻ってきたかどうかをテストします。


あなたの修正を参照する:

strlen()NUL引数が指す文字から最初の/文字までの文字数を返そうとし0ます。この数値は、終端を配置した場所に応じて、任意の値にすることができます0

この0ターミネータの検索がs引数に割り当てられたメモリの背後でstrlen()実行される場合、プログラムは最も確実に未定義の動作に遭遇するため、任意の値を返す可能性があります。

質問に答えるにsend_dataは、が0で終了していないstrlen()と、アプリが未定義の動作に遭遇するため、クラッシュしたりstrlen()、1024を超える値が返されたりする可能性があるため、send()この文字数を送信しようとします。

于 2013-03-03T15:45:45.637 に答える
0

recv()バッファよりも大きいバイトを送信した場合でも、へのrecv()後続の呼び出しでそれを送信できます。そのため、最初の呼び出しでバイトを送信し、受信バッファがバイトであるとするrecv()と、それbytes_receivedはまだ5000バイトであると言いました。すべてのデータを受信するまで、次の呼び出しで再びバイトを取得するだけです。したがって、ここにはバッファオーバーフローはないと思います。ちなみに、これはTCPのしくみです。50001000recv()10001000

于 2013-03-03T16:04:38.267 に答える