「平均的な人は自由になりたくない。彼は単に安全になりたいだけだ。」-HLメンケン
私は非常に安全なCを書き込もうとしています。以下に、私が使用しているテクニックのいくつかをリストし、私が思うほど安全であるかどうかを尋ねます。私のコード/先入観を細かく裂くことを躊躇しないでください。最も些細な脆弱性を見つけたり、新しいアイデアを教えてくれたりする答えは、高く評価されます。
ストリームからの読み取り:
GNU Cプログラミングチュートリアルgetlineによると:
getline関数は、realloc関数を介して、必要に応じてメモリのブロックを自動的に拡大するため、スペースが不足することはありません。getlineが非常に安全である理由の1つです。[..] getlineは、入力行の長さに関係なく、入力行を安全に処理できることに注意してください。
getlineは、すべての入力で、ストリームからの読み取り時にバッファオーバーフローが発生しないようにする必要があると思います。
- 私の仮定は正しいですか?これがエクスプロイトにつながる可能性のある入力および/または割り当てスキームはありますか?たとえば、ストリームの最初の文字が奇妙な制御文字である場合、おそらく0x08 BACKSPACE(ctl-H)です。
- getlineが安全であることを数学的に証明するために何か作業が行われましたか?
Mallocは失敗時にNullを返します:
mallocでエラーが発生した場合、mallocはNULLポインターを返します。NULL(0x0)ポインターにポインター演算を適用できるため、これにはセキュリティ上のリスクがあります。したがって、ウィキペディアでは
/* Allocate space for an array with ten elements of type int. */
int *ptr = (int*)malloc(10 * sizeof (int));
if (ptr == NULL) {
/* Memory could not be allocated, the program should handle
the error here as appropriate. */
}
安全なsscanf:
sscanfを使用するとき、オーバーランの可能性を回避するために、抽出する文字列のサイズを入力文字列のサイズに割り当てる習慣があります。例えば:
const char *inputStr = "a01234b4567c";
const char *formatStr = "a%[0-9]b%[0-9]c":
char *str1[strlen(inputStr)];
char *str2[strlen(inputStr)];
sscanf(inputStr, formatStr, str1, str2);
str1とstr2はinputStrのサイズであり、inputStrからstrlen(inputStr)を超える文字を読み取ることはできないため、inputStrのすべての可能な値がバッファオーバーフローを引き起こすことを考えると、不可能のように思われますか?
- 私は正しいですか?思いもよらなかった奇妙なコーナーケースはありますか?
- これを書くためのより良い方法はありますか?すでにそれを解決した図書館?
一般的な質問:
私はたくさんの質問を投稿しましたが、誰もがそれらすべてに答えることは期待していません。質問は、私が探している種類の回答へのガイドラインです。私は本当に安全なCの考え方を学びたいです。
- 他にどのような安全なCイディオムがありますか?
- 常にチェックする必要があるコーナーケースは何ですか?
- これらのルールを適用するための単体テストを作成するにはどうすればよいですか?
- どうすればテスト可能性または証明可能な正しい方法で制約を適用できますか?
- Cに推奨される静的/動的分析技術またはツールはありますか?
- どのような安全なCプラクティスに従い、自分自身や他の人にそれらをどのように正当化しますか?
資力:
リソースの多くは回答から借りたものです。
- DavidWheelerによるLinuxおよびUnix用の安全なプログラミングHOWTO
- セキュアCプログラミング-SUNMicrosystems
- 例による安全でないプログラミング
- NOPSをさらに追加-これらの問題をカバーするブログ
- CERTセキュアコーディングイニシアチブ
- flawfinder-静的分析ツール
- ヤニック・モイによる安全性を証明するためのThmProversの使用
- libsafe