web-dev-qa-db-ja.com

Format-Stringの脆弱性はどのように悪用されますか?

私はコードの脆弱性について読んでいて、これに遭遇しましたFormat-String Vulnerability

ウィキペディア 言う:

書式文字列のバグは、プログラマがユーザー指定のデータを含む文字列を印刷したいときに最もよく見られます。プログラマーは、誤ってprintf( "%s"、buffer)の代わりにprintf(buffer)を書く可能性があります。最初のバージョンでは、バッファをフォーマット文字列として解釈し、バッファに含まれるフォーマット命令を解析します。 2番目のバージョンは、プログラマが意図したとおり、単に文字列を画面に出力します。

Printf(buffer)バージョンで問題が発生しましたが、攻撃者が有害なコードを実行するためにこの脆弱性をどのように使用できるかまだわかりませんでした。誰かがこの脆弱性がどのようにエクスプロイトされる可能性があるか教えてください。

64
Atul Goyal

直接または間接的に、さまざまな方法でフォーマット文字列の脆弱性を悪用できる可能性があります。以下を例として使用してみましょう(関連するOS保護がないと仮定しますが、とにかく非常にまれです)。

_int main(int argc, char **argv)
{
    char text[1024];
    static int some_value = -72;

    strcpy(text, argv[1]); /* ignore the buffer overflow here */

    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);

    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}
_

この脆弱性の基礎は、可変引数を持つ関数の動作です。可変数のパラメータの処理を実装する関数は、本質的にそれらをスタックから読み取る必要があります。 printf()がスタック上の2つの整数を期待するフォーマット文字列を指定し、1つのパラメーターのみを提供する場合、2番目のパラメーターはスタック上の他のものでなければなりません。拡張により、およびフォーマット文字列を制御できる場合、2つの最も基本的なプリミティブを使用できます。


任意のメモリアドレスからの読み取り

[編集] 重要:ここでスタックフレームレイアウトについていくつかの仮定をしています。脆弱性の背後にある基本的な前提を理解している場合、それらは無視できます。OS、プラットフォーム、プログラム、構成によって異なります。

_%s_ formatパラメーターを使用してデータを読み取ることができます。 printf(text)の元のフォーマット文字列のデータを読み取ることができます。したがって、それを使用してスタックから何かを読み取ることができます。

_./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]
_

任意のメモリアドレスへの書き込み

_%n_形式指定子を使用して、(ほとんど)任意のアドレスに書き込むことができます。繰り返しますが、上記の脆弱なプログラムを想定し、上記のように_some_value_にある_0x08049794_の値を変更してみましょう:

_./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]
_

_some_value_指定子に遭遇する前に書き込まれたバイト数で_%n_を上書きしました(_man printf_)。書式文字列自体またはフィールド幅を使用して、この値を制御できます。

_./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]
_

試すべき多くの可能性とトリックがあります(直接パラメーターアクセス、ラップアラウンドを可能にする大きなフィールド幅、独自のプリミティブの構築)。これは氷山の一角に触れるだけです。 fmt文字列の脆弱性に関するより多くの記事(Phrackには多少優れているかもしれませんが、いくつか優れたものがあります)またはこのテーマに触れる本を読むことをお勧めします。


免責事項:例は[完全ではありませんが]本から引用されていますハッキング:搾取の芸術(第2版)ジョンエリクソン。

96

POSIXでサポートされているn$表記に誰も言及していないのは興味深いことです。攻撃者として書式文字列を制御できる場合、次のような表記を使用できます。

"%200$p"

200を読む番目 スタック上のアイテム(ある場合)。意図は、1から最大までのすべてのn$番号をリストすることであり、パラメーターがフォーマット文字列に表示される方法を再配列する方法を提供します。これは、I18N(L10N、G11N、M18N*)。

ただし、一部の(おそらくほとんどの)システムは、n$値を検証する方法に関してやや不十分であり、フォーマット文字列を制御できる攻撃者による悪用につながる可能性があります。 %n形式指定子と組み合わせると、ポインター位置に書き込むことができます。


* I18N、L10N、G11N、およびM18Nの頭字語は、それぞれ国際化、ローカリゼーション、グローバリゼーション、および多国籍化を表します。数字は、省略された文字の数を表します。

15

ああ、答えは記事にあります!

制御されていないフォーマット文字列は、1999年頃に発見されたセキュリティ脆弱性の一種であるソフトウェア脆弱性の一種です。以前は無害だと考えられていたフォーマット文字列のエクスプロイトは、プログラムのクラッシュまたは有害なコードの実行に使用できます。

典型的なエクスプロイトでは、これらの手法の組み合わせを使用して、プログラムにライブラリ関数のアドレスまたはスタック上の戻りアドレスを悪意のあるシェルコードへのポインターで上書きさせます。フォーマット指定子のパディングパラメータは、出力バイト数と%xトークンは、フォーマット文字列自体の先頭に到達するまでスタックからバイトをポップするために使用されます。フォーマット文字列の先頭は、%n formatトークンは、実行する悪意のあるコードのアドレスで上書きできます

それの訳は %nprintfwriteデータをスタックにある変数に書き込みます。しかし、それはそれが任意に何かに書き込むことができることを意味します。必要なのは、誰かがその変数を使用することです(値が制御方法を見つけたばかりの関数ポインターである場合は比較的簡単です)。

記事のリンクを見てください。彼らは 面白そうに見える

9
Mehrdad

this フォーマット文字列の脆弱性に関する講義ノートを読むことをお勧めします。何がどのように発生し、どのように発生するかを詳細に説明し、トピックの理解に役立つ可能性のある画像をいくつか掲載しています。

2
AndreyP

知る限り、主にプログラムをクラッシュさせる可能性があり、これはサービス拒否攻撃と見なされています。必要なのは、無効なアドレス(実際にはanythingをいくつかの%sが機能することが保証されています)、それは単純なサービス拒否(DoS)攻撃になります。

今、例外/シグナル/割り込みハンドラーの場合に何かをトリガーすることは理論的には可能ですが、それを行う方法を理解することは私を超えています同様に、任意のデータをメモリに書き込む方法も説明します。

しかし、なぜプログラムがクラッシュしたとしても誰も気にしないのでしょうか?それはユーザー(とにかくそれに値する人)に不便ではないでしょうか?

問題は、いくつかのプログラムが複数のユーザーによってアクセスされるため、それらのクラッシュは無視できないほどのコストになることです。または、システムの実行にとって重要な場合もあります(または、非常に重要なことをしている最中である場合もあります)。その場合、これはデータに損害を与える可能性があります。もちろん、メモ帳をクラッシュした場合、誰も気にしないかもしれませんが、CSRSS(実際には同様の種類のバグ、具体的にはダブルフリーのバグ)をクラッシュした場合、システム全体がダウンしてしまいます。


更新:

参照していたCSRSSバグについては、 このリンク を参照してください。


編集:

任意のデータの読み取りは、任意のコードの実行と同じくらい危険ですことに注意してください!パスワードやCookieなどを読み取る場合、任意のコードの実行と同じくらい深刻です-そして、これはtrivialです。十分なフォーマット文字列を試すだけの時間があれば。

0
Mehrdad