例) 危険なコーディング
1 char cStr[256];
2 ZeroMemory(cStr, sizeof(cStr));
3 strcpy(cStr, src); ← srcのサイズが256バイトを超えていた場合オーバーフロー!
修正)
1 char cStr[256];
2 ZeroMemory(cStr,0, sizeof(cStr));
3 strncpy(cStr, src, sizeof(cStr)-1);
危険な関数 | 代替関数 |
gets | fgets |
strcat | strncat |
strcpy | strncpy |
sprintf | snprintf |
vsprintf | vsnprintf |
危険な例)
#include <stdlib.h>
main (int argc, char* argv[]) {
printf(argv[1]);
}
修正例)
#include <stdlib.h>
main (int argc, char* argv[]) {
printf("%s",argv[1]);
}
危険な関数 |
printf |
sprintf |
fprintf |
vsprintf |
snprintf |
vsnprintf |
※書式文字列の脆弱性
書式文字列(フォーマットストリング)とは、printf関数等で使用される書式を指定する文字列
のことである。リストの例では、入力された文字列のみ指定されており、書式文字列が省略された
形で呼び出されている。
リスト)
#include <stdlib.h>
main (int argc, char* argv[]) {
printf(argv[1]);
}
通常の文字列が入力される場合は問題ないが、書式文字列を含んだ入力を与えることで攻撃ができる。
printf関数では、書式文字列が指定されると、対応する変数が引数で与えられているものとして
動作するため、下図のように不正な動作となってしまう。
下図は単純な例であるが、不正コードを入力させ、実行させることも可能である。
"%n"を入力 |
printf(argv[1]); |
戻りアドレス |
引数1
|
実際のスタック領域 |
printf関数は、引数2があるものとして動作する。 |
printf("%n",<引数2>); |
戻りアドレス |
引数1
|
引数2
|
書換えられる! |
"%n"を入力 |
printf(argv[1]); |
戻りアドレス |
引数1
|
実際のスタック領域 |
printf関数は、引数2があるものとして動作する。 |
printf("%n",<引数2>); |
戻りアドレス |
引数1
|
引数2
|
1) scanf系関数を使用するときは、上限サイズを指定
scanf系の関数には、上限サイズを省略した書式が記述できてしまうため、上限サイズを指定した
書式を記述する。または、上限サイズを指定できるfgets関数に置き換える。
危険な例)
char buffer[256];
int num;
num = fscanf(stdin, "%s", buffer);
修正例①)
char buffer[256];
int num;
num = fscanf(stdin, "%255s", buffer);
修正例②)
char buffer[256];
fgets(buffer, 256, stdin);
危険な関数 |
scanf |
sscanf |
fscanf |
vfscanf |
vscanf |
vsscanf |