| 著作一覧 |
厚木方面で見たことある。
TechEDの安全コードのセッションで、テオ(シーオか?)はMSが雇ったことがあるハッカーの中でも特別な存在で、まさにCをしゃべるために生まれてきたみたいだった、といような余談の中で、そのテオのありがたいお言葉として「幾らコードを眺めてもわからん、それが算術演算がらみのバグだ」ってのを紹介していた。Cをしゃべる男がそういうくらいだから我々凡人はコードを眺める以前の段階から攻めなきゃならない。
で、その理由はCの型上げ規則が複雑だということととかいろいろ。
// len.c (注:このコードがセッションに出てきたわけではない。思い出しながら再構成している)
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#if defined(BUG)
int SIZE = 1024;
#else
size_t SIZE = 1024;
#endif
void copy(char* p, int off, int len) {
char buff[SIZE];
int end = strlen(p);
if (off + len > end) {
printf("argment overflow: bad off=%d, len=%d, real=%d\n", off, len, end);
} else if (len + 1 > SIZE) {
printf("buffer overflow: bad off=%d, len=%d, real=%d\n", off, len, end);
} else {
strncpy(buff, p + off, len);
buff[len] = 0;
puts(buff);
}
}
int main(int argc, char* argv[]) {
copy("abc", 0, SIZE_MAX - 1);
}
に対して
$gcc len.c -o len;./len buffer overflow: bad off=0, len=-2, real=3 $gcc -DBUG len.c -o len;./len セグメント例外 (core dumped)
コードの見た目は引数の長さを越えたり、バッファ長を越えたりしないように検証しているように見える。しかし、SIZEという定数の型の違いで正しく弾くこともできれば、死ぬこともできる。
結論は、負になるはずが無い長さを符号付きの型で宣言するな、というのが教訓(っていうか、そのためのsize_t)。
#追記:もう、strncpyとかsnprintfとかは常識なので、今の攻撃側のトレンドは上の例のような算術オーバーフローを利用したバッファオーバーフローらしい。ジェズイットを見習え |