バグ:おなじみの関数(printf)を使っていたら痛い目に

Posted: 2013年04月15日

文字列操作(書式文字列処理)で書いてしまうバグを紹介します。
有名なものであり、しっかりとした参考書には記載されているとおもいます。

プログラムプログラム:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
    if (argc <= 2) {
        // 引数が足りない
        return 1;
    }

    printf(argv[1]);

    // 処理

    return 0;
 }

このプログラムにどのように文字列操作(書式文字列操作)にバグが存在すると思いますか?

  • フォーマット文(第一引数)に直接指定している
  • 書式(format)を用いないならば処理が遅いprintfを使う必要がない

改善版プログラム改善版プログラム:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
    if (argc <= 3) {
        // 引数が足りない
        return 1;
    }

    puts(argv[1]);

    // 処理

    return 0;
 }

解説解説:

パフォーマンスのためにprintfをputsに変更しました。
また、別の要素も存在します。

printfの第一引数には、
固定値または、信頼できる文字列を設定することが求められます。
ユーザの入力やこの関数がAPIの場合は、他の関数からの入力は直接使用しないほうがいいでしょう

printfには、書式文字列攻撃という脆弱性があります。
関数の作り上の問題なのでprintfにと言うよりも、使う側が気をつけなければいけないことです。

簡単にどのような攻撃か書きますが
printfに%s,%xを用いてスタック上のメモリーを表示することが可能になります。
※第二引数がないため

printfに%nを用いてメモリー上の値を上書きします。
関数の戻り位置を変更し、好きなことができたら問題ですよね

そのため
最低でも

printf(_T(“%s”), argv[1])

くらいには修正すべきです。

書式辞書攻撃

カテゴリー: バグ, プログラム | タグ: , , | コメント無し »

コメント