3

私の質問は、セキュリティの観点からです。一部のコードをクリーンアップしている最中ですが、現在のコードには制御されていないフォーマット文字列の脆弱性があることがわかりました。printf()次のようなものに文字列を渡しています。

void print_it(char * str)
{
    printf(str);

これは明らかに安全でないプログラミングと見なされますが、gcc でさえ、通常、少なくとも何らかの警告が表示されます。

警告: フォーマットは文字列リテラルではなく、フォーマット引数もありません

問題を「修正」するために、取得したものが文字列として扱われるようにすることができます

printf("%s", str);

しかし、長さ指定子を使用することで追加のセキュリティがあるかどうか疑問に思っていました。何かのようなもの:

printf("%.*s", (int)sizeof(str), str);

それがより安全になる理由は思いつきませんが、ここで明らかな何かが欠けていたとしても驚かないでしょう。

4

3 に答える 3

5

最近の C ショップが printf ステートメントをこれほど安全に保護しているわけではありません。これは、Fortran コードと対話するときに非常に一般的な、null で終了しない文字列を処理するときに使用されます。

厳密に言えば、暴走読み取りを防ぐためのセキュリティ上の利点になります。おそらく、違反したヌル文字に続いて機密データを印刷しようとしていたのでしょう。

しかし

printf("%.*s", (int)sizeof(str), str);

はるかに悪いです。「ヌル文字を無視して、とにかく完全な内容を出力する」と言っただけです。むしろ、スペースが埋め込まれた文字列をメモリの最後まで処理しない限り、これはさらに悪いことです。これは、文字列が Fortran から来た場合に当てはまります。

ただし、これ非常に重要です。

printf("%s", str);

重大なprintf(str)セキュリティ上の欠陥です。指定子を使用したprintf 攻撃について読んでください%n

于 2013-03-07T19:02:38.953 に答える
1

いくつかの追加のセキュリティがあります

printf("%.*s", (int)sizeof(str), str);

印刷されるのは多くてもバイト (通常は 4 バイトまたは 8 バイト) であるため、 0 で終了していない配列を指しているsizeof(char*)場合、メモリの多くを読み取ったり読み取ったりすることはありません。strchar

しかし、より一般的には、正当な理由がなくても出力を短くします。

あなたが意味した場合

printf("%.*s", (int)strlen(str), str);

printfの精度が必要な場合、strlen呼び出しは同じ無効なメモリアクセスを行うため、これはまったく無意味です。

于 2013-03-07T19:36:25.367 に答える
0

このアイデアは、配列がポインターに崩壊するときに配列が関数に渡される場合、またはそのことについて malloc されたポインターに対しては機能しません。sizeof(var)配列ではなく、ポインターのサイズを指定するためです。したがって、長さを指定するために printf() で使用することはできません。

これは、自動 (スタック割り当て) 配列にのみ適用されます。では、これはいつ役立つのでしょうか。次の 2 つのケースが考えられます。

1.配列のサイズを超えて配列に書き込む場合。

この場合、自分のものではない場所に書き込むことで、すでに未定義の動作を引き起こしています。話の終わり。

2. 文字列の末尾に null バイトがない場合 (ただし、配列の境界を越えていない場合)。

この場合、配列には有効なコンテンツが含まれていますが、null バイトは含まれていません。2 つの可能性があります。

2.a. 長さ指定子を使用すると、配列の内容全体が出力されます。そのため、配列内の初期化されていないバイトに (そのサイズ内であっても) アクセスすると、未定義の動作が発生します。%sそれ以外の場合は、UB を回避するために長さ指定子と共に printf() で使用するために、有効なコンテンツの長さを追跡する必要があります。この場合、有効なコンテンツの長さはすでにわかっています。したがって、有効なコンテンツ のみを印刷するように printf() に指示するのではなく、自分で単純に null で終了することができます。

2.b. たとえば、最初に配列全体をゼロで初期化したとします。この場合、配列は有効な文字列になるため、長さ修飾子は必要ありません。

なので、あまり役に立たないと言えます。

于 2013-03-07T19:35:27.873 に答える