Windows システムの「フォーマット文字列の脆弱性」とは正確には何ですか?どのように機能し、どのように防御できますか?
2 に答える
最も単純なフォーマット文字列攻撃は次のとおりです。
char buffer[128];
gets(buffer);
printf(buffer);
そこにもバッファオーバーフローの脆弱性がありますが、要点は次のとおりです。信頼できないデータ(ユーザーから)をprintf
、その引数をフォーマット文字列として使用する(またはそのいとこの1つに)渡すことになります。
つまり、ユーザーが「%s」と入力すると、情報開示の脆弱性が発生します。これはprintf
、ユーザー入力をフォーマット文字列として扱い、スタック上の次のものを文字列として出力しようとするためです。それはあなたのコードが言ったかのようですprintf("%s");
。に他の引数を渡さなかったためprintf
、任意の値が表示されます。
ユーザーが「%n」と入力すると、特権の昇格攻撃(少なくともサービス拒否攻撃)が発生する可能性があります。これは、%n形式の文字列によりprintf
、これまでに印刷された文字数が次の場所に書き込まれるためです。スタック上。この値を入れる場所を指定しなかったので、任意の場所に書き込みます。
printf
これはすべて悪いことであり、いとこを使用するときに非常に注意する必要がある理由の1つです。
あなたがすべきことはこれです:
printf("%s", buffer);
これは、ユーザーの入力がフォーマット文字列として扱われることは決してないため、その特定の攻撃ベクトルから安全であることを意味します。
Visual C ++では、注釈を使用して、__Format_string
への引数を検証するように指示できますprintf
。%n
デフォルトでは許可されていません。GCCでは__attribute__(__printf__)
、同じことを使用できます。
この擬似コードでは、ユーザーは「hello」のように、印刷する文字をいくつか入力します。
string s=getUserInput();
write(s)
それは意図したとおりに機能します。しかし、書き込みは文字列をフォーマットできるため、たとえば
int i=getUnits();
write("%02d units",i);
出力:「03ユニット」。そもそもユーザーが「%02d」と書いた場合はどうでしょうか...スタックにパラメーターがないため、他の何かがフェッチされます。それが何であるか、そしてそれが問題であるかどうかはプログラムに依存します。
簡単な修正は、文字列を出力するようにプログラムに指示することです。
write("%s",s);
または、文字列をフォーマットしようとしない別の方法を使用します。
output(s);
詳細情報が記載されたウィキペディアへのリンク。