Home > ラーニング > セキュアコーディング > CERT セキュアコーディングスタンダード > 01. プリプロセッサ (PRE)
既存のAPIを変更するなど、ある識別子をグローバルに他の識別子と変更することで既存のコードを修正する場合に、マクロが活用されることがよくある。一般にこのようなアプローチはリスクをともなうものだが、とくに、よりセキュアでない関数の関数名への置き換えは危険が大きい。
Internet Systems Consortium (ISC) の Dynamic Host Configuration Protocol (DHCP) にはかつて、複数のバッファオーバーフロー条件をつくりこむ脆弱性が存在した。[VU#654390] ISC DHCP は vsnprintf() 関数を使って様々なログファイル文字列を組み立てていた。vsnprintf() は Open Group Base Specification Issue 6 [Open Group 04] や C99 [ISO/IEC 9899:1999] で定義されている。vsnprintf() をサポートしないシステムのために、vsnprintf() 関数を vsprintf() に定義する C インクルードファイルが作成された。以下のコード例にそれを示す:
#define vsnprintf(buf, size, fmt, list) \ vsprintf(buf, fmt, list)
vsprintf() 関数は範囲チェックを行わない。したがって、サイズ引数は破棄され、信頼できないデータが引数に使われるとバッファオーバーフローにつながる可能性がある。
解決法は、ライブラリ関数に vsnprintf() が欠けている場合に vsnprintf() を実装するコードをインクルードすることである。 この解決法は、vsnprintf() を提供していないシステムではシンボル __USE_ISOC99 が定義されていないことを仮定している。
#include <stdio.h> #ifndef __USE_ISOC99 /* vsnprintf() を再実装 */ #include "my_stdio.h" #endif
セキュアな関数をよりセキュアでない関数に置き換えることは非常にリスクの高いプラクティスである。なぜなら、ディベロッパーは、(実際には行っていない)関数がセキュリティ上のチェックを行ってくれていると信じこんでしまうからである。これはたとえば、ディベロッパーが ISO/IEC TR 24731-1 関数 (「STR07-C. TR 24731 を使用し、文字列操作を行う既存のコードの脅威を緩和する」を参照) のように全てのプラットフォームで利用できるとは限らない、よりセキュアな関数を採用しようとするときに、懸念事項になるかもしれない。
| レコメンデーション | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
|---|---|---|---|---|---|
| PRE09-C | 高 | 高 | 中 | P18 | L1 |
PRE09-C. Do not replace secure functions with less secure functions