■課題6:バッファオーバーフローの実験 サンプルプログラム(2)を実行せよ。このプログラムはgets()関数を用いて、標準入力からの入力をバッファ にデータを読み込むものであるが、結果を見ると、プログラム中で操作していないバッファdmy[]に値が入る ことがある。この原因を考察し、解決策を示せ。また、この問題によって引き起こされるTCP/IP通信におけるセ キュリティ上の欠陥はどのようなものが考えられるか、具体例を挙げて述べよ。


==bufovf.cソース============

include <stdio.h>       
#define BUFLEN 20  /*BUFLEN領域を20に変更*/
int main(int argc, char **argv){
 char *rtn;
   char dmy[BUFLEN];
   char buf[BUFLEN];
 memset(dmy, '¥0', BUFLEN); /*配列全体を初期化*/
   memset(buf, '¥0', BUFLEN); /*配列全体を初期化*/
 printf("before¥n");
 printf("buf(Len:%d) = %s¥n", strlen(buf), buf);
   printf("dmy(Len:%d) = %s¥n", strlen(dmy), dmy); 
 if((rtn = gets(buf)) == NULL){
           
   exit(-1); 
   }
       
 printf("after¥n");
   printf("buf(Len:%d) = %s¥n", strlen(buf), buf);
   printf("dmy(Len:%d) = %s¥n", strlen(dmy), dmy);
   }

<<実行結果>>

[root@pw031 j04031]% bufovf
before
buf(Len:0) =
dmy(Len:0) =
123456789101112131415161718192021222324252627282930
after
buf(Len:51) = 123456789101112131415161718192021222324252627282930
dmy(Len:19) = 1222324252627282930
上記の実行結果を見ると配列dmyに格納するようなプログラムは記述されていないがdmyに格納されているのが分かる。
これは指定したメモリ領域よりも大きいデータを格納しようとしたときに、領域溢れしてしまったデータ分をdmyに入れてしまった結果である。
このような状態をバッファオーバーフロー(またはバッファオーバーラン)と呼ぶ。
このような状態を起こす原因はgets関数にある。
gets関数は配列の長さを指定する事が出来ず文字配列しか渡されていない。
そのため実行結果のように配列以上の文字の入力を防げずプログラム上にない動作を起こしてしまう。
これを解決する際にはfgets関数を用いる。

fgets(文字配列,sizeof(文字配列),stdin)

fgets関数は文字配列だけでなく、文字の要素数も指定する事が出来る。
またgets関数とは異なり改行も配列要素に含まれ格納される。 変更したプログラムbufovf2.cを下記に示す。 ※変更したプログラムbufovf2.c※
#include <stdio.h>       
#define BUFLEN 20
int main(int argc, char **argv) {
 char *rtn;
   char dmy[BUFLEN];
   char buf[BUFLEN];
 memset(dmy, '¥0', BUFLEN);
   memset(buf, '¥0', BUFLEN);
 printf("before¥n");
 printf("buf(Len:%d) = %s¥n", strlen(buf), buf);
   printf("dmy(Len:%d) = %s¥n", strlen(dmy), dmy);
 if ((rtn = fgets(buf,BUFLEN,stdin)) == NULL) {
   exit(-1);
   }
 printf("after¥n");
   printf("buf(Len:%d) = %s¥n", strlen(buf), buf);
   printf("dmy(Len:%d) = %s¥n", strlen(dmy), dmy);
}
<<実行結果>>
[root@pw031 j04031]% bufovf2
before
buf(Len:0) =
dmy(Len:0) =
1234567890123456789012345678901234567890
after
buf(Len:19) = 1234567890123456789
dmy(Len:0) =
実行結果から見ると指定した要素数以上の文字列は格納されていない。
しかし文字数を見ると19となっている。これはfgets関数がgets関数と異なり改行文字も格納する関数であるからである。 <バッファオーバーフローによるTCP/IPのセキュリティ欠陥>

実験で行ったようなオーバーフローが起こった場合、プログラムのメモリ上に任意のプログラムを送り込み超えた領域にてプログラムを上書きすることが可能になってしまう。これにより、もし標的となったプログラムが高い権限で動作するものだった場合,その権限を乗っ取り対象コンピュータを自由に操ることができてしまう場合もある。
これがバッファオーバーフローの大きな問題のひとつである。
そうなるとあるサーバーの権限を乗っ取られた場合、不正アクセスを行った者が自由に権限内にてサーバー内のシステムを都合のよく動かせたり、ウィルスプログラムを作成し実行させる事によってコンピュータシステムを破壊させる事も可能となりうる。