SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

C/C++セキュアコーディング入門

sizeofオペレータを正しく使おう
――C/C++セキュアコーディング入門(5)

「動けばいいってもんじゃない」 脆弱性を作り込まないコーディング 第5回

Cyrus imapdでの誤用例

 次にCyrus imapdにおけるsizeofオペレータの誤用例を見てみましょう。以下のコードはCyrus imapdのコードからの抜粋です。

「cyrus-imapd-2.2.13/sieve/script.c」から
int do_action_list(..., char *actions_string, ...){

  ......

  switch(a->a){

  case ACTION_REJECT:
      ......
      snprintf(actions_string + strlen(actions_string),
               sizeof(actions_string) - strlen(actions_string),
               "Rejected with: %s\n", a->u.rej.msg);
      break;
  case ACTION_FILEINTO:
      ......
      snprintf(actions_string + strlen(actions_string),
               sizeof(actions_string) - strlen(actions_string),
               "Filed into: %s\n", a->u.fil.mailbox);
      break;
  case ACTION_KEEP:
      ......
      snprintf(actions_string + strlen(actions_string),
               sizeof(actions_string) - strlen(actions_string),
               "Kept\n");
      break;
  case ACTION_REDIRECT:
      ......
      snprintf(actions_string + strlen(actions_string),
               sizeof(actions_string) - strlen(actions_string),
               "Redirected to %s\n", a->u.red.addr);
      break;
  ......
  }

}

 このswitch文は、a->aの内容に応じた処理を行い、actions_stringが指すメモリ領域にログ情報を書き足していく部分です。各case節の中では、actions_stringの指すメモリ領域の、既に書き込まれている文字列の直後に新たにログ情報を書き込んでいます。その際、確保されているメモリ領域をはみ出さないように、snprintf()を使って、sizeof(actions_string)-strlen(actions_string)という式によって、書き込む文字数を制限しています。.

 しかし actions_stringはポインタでした。従ってsizeof(actions_string) は、actions_stringが指すメモリ領域のサイズではなく、ポインタのサイズを表しています。それは意図していたものよりずっと小さい数値であることは間違いありません。その結果、(ログが書き込まれていくにつれて)sizeof(actions_string)-strlen(actions_string)は負の値になってしまうと考えられます。しかし、snprintf()の引数としてはsize_t、すなわち符号無し整数型として扱われるため、大きな正の値として解釈され、実質的に書き込む文字数を制限できていないということになります。

 さらに悪いことに、書き込むログ情報を、攻撃者がある程度操作できる状況でした。攻撃者は入力を工夫することにより、actions_stringの指すメモリ領域の後ろに任意の値を書き込ませることができたのです。

 上書きされる部分に、プログラムの挙動を制御する変数やライブラリ関数のエントリテーブルなどが置かれていた場合、攻撃者はプログラムを乗っ取ることができる可能性が高くなります。実際、この問題は任意のコード実行に繋がる脆弱性としてCVEに登録されています(CVE-2009-2632CERT/CC VU#336053)。

 この問題を修正するために、開発者は、sizeofオペレータによるメッセージ領域のサイズの計算を止めるという方法を選択しました。

  • 確保するメモリ領域の大きさを表すシンボルを定義
  • #define ACTIONS_STRING_LEN 4096
    
  • snprintf()はすべて次のように修正:
  • snprintf(actions_string + strlen(actions_string),
             ACTIONS_STRING_LEN - strlen(actions_string),
             "Redirected to %s\n", a->u.red.addr);
    

 これによって、当初の意図どおりの動作を得ることができました。

「cyrus-imapd-2.2.13p1/sieve/script.c」から
#define ACTIONS_STRING_LEN 4096

int do_action_list(..., char *actions_string, ...){

  ......

  switch(a->a){

  case ACTION_REJECT:
      ......
      snprintf(actions_string + strlen(actions_string),
               ACTIONS_STRING_LEN - strlen(actions_string),
               "Rejected with: %s\n", a->u.rej.msg);
      break;
  case ACTION_FILEINTO:
      ......
      snprintf(actions_string + strlen(actions_string),
               ACTIONS_STRING_LEN - strlen(actions_string),
               "Filed into: %s\n", a->u.fil.mailbox);
      break;
  case ACTION_KEEP:
      ......
      snprintf(actions_string + strlen(actions_string),
               ACTIONS_STRING_LEN - strlen(actions_string),
               "Kept\n");
      break;
  case ACTION_REDIRECT:
      ......
      snprintf(actions_string + strlen(actions_string),
               ACTIONS_STRING_LEN - strlen(actions_string),
               "Redirected to %s\n", a->u.red.addr);
      break;
  ......
  }

}

 今回は、sizeofオペレータの使用上の注意点とそれに関連した誤用例を紹介しました。今回紹介した2つの誤用例はどちらも過去のバージョンも含めてソースコードが公開されています。具体的にどのような間違いだったか、どのように修正したのか、を確かめてみてください。

参考資料

修正履歴

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
C/C++セキュアコーディング入門連載記事一覧

もっと読む

この記事の著者

戸田 洋三(JPCERT コーディネーションセンター)(トダ ヨウゾウ(JPCERT コーディネーションセンター))

リードアナリストJPCERTコーディネーションセンター東京工業大学情報理工学研究科修士課程修了。学生時代は、型理論および証明からのプログラム抽出を研究。その後、千葉大学総合情報処理センターのスタッフとして、学内ネットワークの運営、地域ネットワーク、IPマルチキャストの実験ネットワークであるJP-MB...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4785 2010/01/22 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー