トップ «前の日記(2005-08-17) 最新 次の日記(2005-08-19)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2005-08-18

_ 自動改札機

厚木方面で見たことある。

_ Cでしゃべる男

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とかは常識なので、今の攻撃側のトレンドは上の例のような算術オーバーフローを利用したバッファオーバーフローらしい。

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|

ジェズイットを見習え