API00-C. 関数のなかで引数を検証する
呼び出し元と呼び出し先の両方でテストを実施する防衛的プログラミングは、C/C++ のコミュニティにおいて、おもに性能上の問題から疑問視されている。C/C++ の基本方針は、呼び出し元か呼び出し先どちらか一方で検証処理を行うことである。
呼び出し元に引数を検証させることでコードが速くなる可能性がある。なぜなら無効な値を関数に渡されないようにする不変条件(invariant)を呼び出し元は知っているかもしれないからだ。一方、呼び出し先に引数の検証を要求すると、検証用コードが 1 つの場所にカプセル化されるため、コードサイズを縮小でき、一貫した適切な方法で検査を実行できる可能性が高くなる。
安全性とセキュリティの理由から、このコーディングスタンダードでは、呼び出し先の関数で引数を検証することを推奨する。引数の妥当性を検証することで、関数はある種の誤用に耐えられるようになり、また、関数を使用するアプリケーションの安全性も期待できる。さらに、引数の妥当性検証は、無効な引数の原因となった条件の特定を容易にする可能性がある。
違反コード
この違反コードでは、setfile()
と usefile()
が引数を検証していない。そのため、このライブラリ内で無効なファイルポインタが使用され、ライブラリの内部状態が破壊されたり、脆弱性が生じたりする可能性がある。
/* ライブラリの内部状態を設定する */ extern int setfile(FILE *file); /* 渡されたファイルを使用してアクションを実行する */ extern int usefile(); static FILE *myFile; void setfile(FILE *file) { myFile = file; } void usefile(void) { /* なんらかのアクションを実行する */ }
内部状態が機密情報やシステムの重要なデータを参照している場合、脆弱性はより深刻なものになる恐れがある。
適合コード
関数の引数を検証し内部状態を確認することで、プログラムの実行に一貫性を持たせ、潜在的な脆弱性を排除できるだろう。また、エラー発生時の安全性を確保するには、コミットまたはロールバックセマンティクス(エラー時にプログラムの状態を変化させない)の実装が望ましい。
/* ライブラリの内部状態を設定する */ extern errno_t setfile(FILE *file); /* 渡されたファイルを使用してアクションを実行する */ extern errno_t usefile(void); static FILE *myFile; errno_t setfile(FILE *file) { if (file && !ferror(file) && !feof(file)) { myFile = file; return 0; } /* エラー時の安全確保: myFile を変更しない */ return -1; } errno_t usefile(void) { if (!myFile) return -1; /* その他のチェックを実行し、必要に応じて * エラー条件を返す */ /* なんらかのアクションを実行する */ return 0; }
リスク評価
ライブラリ関数において引数を検証しないと、アクセス違反が発生したり、データの完全性が侵害されたりする可能性がある。そうした事態は、呼び出し元コードによるライブラリの呼び出し方に欠陥があることを示すものであるが、ライブラリを攻撃するために呼び出し元コードの脆弱性が悪用されている可能性があることに変わりはない。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
API00-C |
中 |
低 |
高 |
P2 |
L3 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
LDRA tool suite |
V. 8.5.4 |
|
|
関連するガイドライン
CERT C++ Secure Coding Standard | MSC08-CPP. Functions should validate their parameters |
MITRE CWE | CWE ID 20, Insufficient input validation |
参考資料
[Apple 2006] | Application Interfaces That Enhance Security |
翻訳元
これは以下のページを翻訳したものです。
API00-C. Functions should validate their parameters (revision 66)