脆弱性の解説
IFDエントリのカウント値を示すtdir_countが1より大きいとき、タイプが'TIFF_ASCII'もしくは'TIFF_UNDEFINED'であれば、動的メモリ割り当てを行う_TIFFmalloc()が呼び出されます。_TIFFmalloc()は内部でmalloc()を呼び出すだけの関数です。このとき、割り当てるメモリのサイズは、式dp->tdir_count + 1の結果の値になります。
攻撃者がtdir_countの値として不正な0xFFFFFFFFを持つファイルをプログラムに読み込ませることができると、いったい何が起こるでしょうか。加算0xFFFFFFFF + 1の結果は符号無し整数のラップアラウンドの結果ゼロになり、malloc()はこのゼロを引数にとって呼び出されます。サイズ0のメモリ割り当ては言語仕様上「処理系定義」の動作となります。WindowsやLinuxなどの処理系では、たまたま呼び出しが成功し、プログラマが意図したよりも小さなメモリ領域が確保されることがあります。
この想定外のメモリ割り当てが行われた後でmemcpy()などメモリに書き込みを行う関数が実行されると、ヒープバッファオーバーフローが発生してしまいます。攻撃者が何らかの方法で、細工したTIFFファイルをユーザーに開かせることができれば、上述の処理が行われ、任意のコードが実行される恐れがあるわけです。
ユーザーからの入力、つまりTIFFファイルのヘッダ情報が適切かどうかの入力値検証(Input Validation)が不十分であったため、今回のような脆弱性が作り込まれてしまいました。
脆弱性の修正方法
この脆弱性は、CheckMalloc()を修正することで対応されました。以下がその修正内容です。皆さんが想定した通りの修正でしょうか。
--- tiff-v3.6.1/libtiff/tif_dirread.c 2003-12-22 17:22:15.000000000 +0900
+++ tiff-3.7.1/libtiff/tif_dirread.c 2004-12-21 04:29:27.000000000 +0900
@@ -62,11 +63,20 @@
static char *
-CheckMalloc(TIFF* tif, tsize_t n, const char* what)
+CheckMalloc(TIFF* tif, size_t nmemb, size_t elem_size, const char* what)
{
- char *cp = (char*)_TIFFmalloc(n);
+ char *cp = NULL;
+ tsize_t bytes = nmemb * elem_size;
+
+ /*
+ * XXX: Check for integer overflow.
+ */
+ if (nmemb && elem_size && bytes / elem_size == nmemb)
+ cp = (char*)_TIFFmalloc(bytes);
+
if (cp == NULL)
TIFFError(tif->tif_name, "No space %s", what);
+
return (cp);
}
修正されたコードでは、nmembの値とelem_sizeの値がゼロでないことをチェックし(size_t型変数が負の値をとらない性質を利用)、その上でbytesの計算結果が正しいことをチェックしています。bytes / elem_size == nmembをチェックすることで、元の式bytes = nmemb * elem_sizeで何らかの乗算エラー(この場合、符号無し整数のラップアラウンド)が発生していることを検出できます。malloc()は、この入力値検査をパスした場合にのみ、呼び出されるよう修正されていることが分かります。また、CheckMalloc()の引数の数が増えているので、これに応じて呼び出し側も修正されています。
CERT C セキュアコーディングスタンダード
前回に引き続き、今回の脆弱性も整数エラーがバッファオーバーフローを引き起こすというパターンでしたが、このパターンで作り込まれる脆弱性の数は少なくありません。この脆弱性を作り込まないためのガイドラインとして、CERT Cセキュアコーディングスタンダードから以下の2つを紹介します。
これらの情報を参考に、セキュアコーディングを実践していきましょう!
参考情報
- 『C/C++ セキュアコーディング』 Robert C. Seacord 著、JPCERTコーディネーションセンター 訳、アスキー、2006年11月
- 『CERT C セキュアコーディングスタンダード』 Robert C. Seacord 著、久保正樹/戸田洋三 訳、アスキー、2009年9月
- TIFF 6.0 Specification(PDF)
- 槻ノ木隆の「BBっとWORDS」その96「TIFFの特徴」
- INT30-C. 符号無し整数の演算結果がラップアラウンドしないようにする
- MEM04-C. サイズ0のメモリ割り当てを行わない
- CVE-2004-1308
