Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2019-11932 — CVE-2019-11932の技術解説とエクスプロイトコード。Android版WhatsAppにおけるdouble-free脆弱性で、細工されたGIFファイルを介してリモートコード実行につながります。 | Kitploit
ツール/GitHubGitHub/infiniteloopers/cve-2019-11932
Androidセキュリティ脆弱性分析エクスプロイトモバイルセキュリティ学習と教育バイナリエクスプロイト
GitHubinfiniteloopers/cve-2019-11932

CVE-2019-11932

CVE-2019-11932の技術解説とエクスプロイトコード。Android版WhatsAppにおけるdouble-free脆弱性で、細工されたGIFファイルを介してリモートコード実行につながります。

リポジトリを見る
42116年前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2019-11932

WhatsAppのダブルフリー脆弱性がどのようにRCEになるか

このブログ記事では、Android版WhatsAppで発見したダブルフリー(二重解放)脆弱性と、それをRCEにした方法について共有します。この問題はFacebookに報告しました。Facebookはこの問題を認識し、WhatsAppバージョン2.19.244で正式にパッチを公開しました。Facebookはこの問題に対するCVE-2019-11932の確保も支援してくれました。

WhatsAppユーザーの皆さんは、このバグから身を守るため、最新のWhatsAppバージョン(2.19.244以上)に更新してください。

手順は以下のとおりです。

0:16 攻撃者が任意のチャネルを介してユーザーにGIFファイルを送信する

その1つは、WhatsAppのドキュメントとして送信する方法です(つまり、ペーパークリップボタンを押して「ドキュメント」を選択し、破損したGIFを送信します) 攻撃者がユーザーの連絡先リストにいる場合(つまり友人である場合)、破損したGIFはユーザーの操作なしに自動的にダウンロードされます。

0:24 ユーザーがWhatsAppの友人にメディアファイルを送信したいと考えます。そこでユーザーはペーパークリップボタンを押し、WhatsAppギャラリーを開いて友人に送信するメディアファイルを選択します。

WhatsAppギャラリーを開くだけでバグが発動するため、ユーザーは何も送信する必要がないことに注意してください。WhatsAppギャラリーを開いた後に追加の操作は必要ありません。

0:30 WhatsAppはすべてのメディア(受信したGIFファイルを含む)のプレビューを表示するため、ダブルフリーのバグとRCEエクスプロイトが発動します。

libpl_droidsonroids_gif の decoding.c における DDGifSlurp のダブルフリー脆弱性

WhatsAppユーザーがメディアファイルを送信するためにWhatsAppでギャラリービューを開くと、WhatsAppはlibpl_droidsonroids_gif.soというネイティブライブラリでGIFファイルを解析し、プレビューを生成します。libpl_droidsonroids_gif.soはオープンソースライブラリで、ソースコードは https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c で入手できます。

GIFファイルには複数のエンコードされたフレームが含まれます。デコードされたフレームを保存するために、rasterBitsという名前のバッファが使用されます。すべてのフレームのサイズが同じ場合、rasterBitsは再割り当てなしで再利用されます。ただし、以下の3つの条件のいずれかが満たされると、rasterBitsは再割り当てされます。

width * height > originalWidth * originalHeight

width - originalWidth > 0

height - originalHeight > 0

再割り当てはfreeとmallocの組み合わせです。再割り当てのサイズが0の場合、それは単なるfreeです。サイズが100、0、0の3つのフレームを含むGIFファイルがあるとしましょう。

最初の再割り当て後、サイズ100のinfo->rasterBitsバッファが得られます。

2回目のサイズ0の再割り当てで、info->rasterBitsバッファは解放されます。

3回目のサイズ0の再割り当てで、info->rasterBitsは再び解放されます。

これによりダブルフリーの脆弱性が発生します。トリガーとなる箇所はdecoding.cにあります。

int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth; int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight; const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height; if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) { void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, <<-- double-free here sizeof(GifPixelType)); if (tmpRasterBits == NULL) { gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; break; } info->rasterBits = tmpRasterBits; info->rasterSize = newRasterSize; }

Androidでは、サイズNのメモリのダブルフリーにより、直後のサイズNの2つのメモリ割り当てが同じアドレスを返すことになります。

(lldb) expr int $foo = (int) malloc(112) (lldb) p/x $foo (int) $14 = 0xd379b250

(lldb) p (int)free($foo) (int) $15 = 0

(lldb) p (int)free($foo) (int) $16 = 0

(lldb) p/x (int)malloc(12) (int) $17 = 0xd200c350

(lldb) p/x (int)malloc(96) (int) $18 = 0xe272afc0

(lldb) p/x (int)malloc(180) (int) $19 = 0xd37c30c0

(lldb) p/x (int)malloc(112) (int) $20 = 0xd379b250

(lldb) p/x (int)malloc(112) (int) $21 = 0xd379b250

WhatsAppのダブルフリー脆弱性がどのようにRCEになるか 読了時間 14分 このページの内容 デモ libpl_droidsonroids_gif の decoding.c における DDGifSlurp のダブルフリー脆弱性 PCレジスタの制御 ASLRとW^Xへの対処 すべてをまとめる 影響を受けるバージョン 攻撃ベクター このブログ記事では、Android版WhatsAppで発見したダブルフリー(二重解放)脆弱性と、それをRCEにした方法について共有します。この問題はFacebookに報告しました。Facebookはこの問題を認識し、WhatsAppバージョン2.19.244で正式にパッチを公開しました。Facebookはこの問題に対するCVE-2019-11932の確保も支援してくれました。

WhatsAppユーザーの皆さんは、このバグから身を守るため、最新のWhatsAppバージョン(2.19.244以上)に更新してください。

デモ https://drive.google.com/file/d/1T-v5XG8yQuiPojeMpOAG6UGr2TYpocIj/view

上記のリンクにアクセスできない場合のダウンロード用Googleドライブリンク https://drive.google.com/open?id=1X9nBlf5oj5ef2UoYGOfusjxAiow8nKEK

手順は以下のとおりです。

0:16 攻撃者が任意のチャネルを介してユーザーにGIFファイルを送信する その1つは、WhatsAppのドキュメントとして送信する方法です(つまり、ペーパークリップボタンを押して「ドキュメント」を選択し、破損したGIFを送信します) 攻撃者がユーザーの連絡先リストにいる場合(つまり友人である場合)、破損したGIFはユーザーの操作なしに自動的にダウンロードされます。 0:24 ユーザーがWhatsAppの友人にメディアファイルを送信したいと考えます。そこでユーザーはペーパークリップボタンを押し、WhatsAppギャラリーを開いて友人に送信するメディアファイルを選択します。 WhatsAppギャラリーを開くだけでバグが発動するため、ユーザーは何も送信する必要がないことに注意してください。WhatsAppギャラリーを開いた後に追加の操作は必要ありません。 0:30 WhatsAppはすべてのメディア(受信したGIFファイルを含む)のプレビューを表示するため、ダブルフリーのバグとRCEエクスプロイトが発動します。 libpl_droidsonroids_gif の decoding.c における DDGifSlurp のダブルフリー脆弱性 WhatsAppユーザーがメディアファイルを送信するためにWhatsAppでギャラリービューを開くと、WhatsAppはlibpl_droidsonroids_gif.soというネイティブライブラリでGIFファイルを解析し、プレビューを生成します。libpl_droidsonroids_gif.soはオープンソースライブラリで、ソースコードは https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c で入手できます。

GIFファイルには複数のエンコードされたフレームが含まれます。デコードされたフレームを保存するために、rasterBitsという名前のバッファが使用されます。すべてのフレームのサイズが同じ場合、rasterBitsは再割り当てなしで再利用されます。ただし、以下の3つの条件のいずれかが満たされると、rasterBitsは再割り当てされます。

width * height > originalWidth * originalHeight width - originalWidth > 0 height - originalHeight > 0 再割り当てはfreeとmallocの組み合わせです。再割り当てのサイズが0の場合、それは単なるfreeです。サイズが100、0、0の3つのフレームを含むGIFファイルがあるとしましょう。

最初の再割り当て後、サイズ100のinfo->rasterBitsバッファが得られます。 2回目のサイズ0の再割り当てで、info->rasterBitsバッファは解放されます。 3回目のサイズ0の再割り当てで、info->rasterBitsは再び解放されます。 これによりダブルフリーの脆弱性が発生します。トリガーとなる箇所はdecoding.cにあります。

int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth; int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight; const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height; if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) { void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, <<-- double-free here sizeof(GifPixelType)); if (tmpRasterBits == NULL) { gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM; break; } info->rasterBits = tmpRasterBits; info->rasterSize = newRasterSize; } Androidでは、サイズNのメモリのダブルフリーにより、直後のサイズNの2つのメモリ割り当てが同じアドレスを返すことになります。

(lldb) expr int $foo = (int) malloc(112) (lldb) p/x $foo (int) $14 = 0xd379b250

(lldb) p (int)free($foo) (int) $15 = 0

(lldb) p (int)free($foo) (int) $16 = 0

(lldb) p/x (int)malloc(12) (int) $17 = 0xd200c350

(lldb) p/x (int)malloc(96) (int) $18 = 0xe272afc0

(lldb) p/x (int)malloc(180) (int) $19 = 0xd37c30c0

(lldb) p/x (int)malloc(112) (int) $20 = 0xd379b250

(lldb) p/x (int)malloc(112) (int) $21 = 0xd379b250

上記のスニペットでは、変数$fooが2回解放されています。その結果、次の2回の割り当て($20と$21)は同じアドレスを返します。次に、gif.hのstruct GifInfoを見てみましょう。 struct GifInfo { void (*destructor)(GifInfo *, JNIEnv *); <<-- there's a function pointer here GifFileType *gifFilePtr; GifWord originalWidth, originalHeight; uint_fast16_t sampleSize; long long lastFrameRemainder; long long nextStartTime; uint_fast32_t currentIndex; GraphicsControlBlock *controlBlock; argb *backupPtr; long long startPos; unsigned char *rasterBits; uint_fast32_t rasterSize; char *comment; uint_fast16_t loopCount; uint_fast16_t currentLoop; RewindFunc rewindFunction; <<-- there's another function pointer here jfloat speedFactor; uint32_t stride; jlong sourceLength; bool isOpaque; void *frameBufferDescriptor; };

次に、以下のサイズの3つのフレームを持つGIFファイルを作成します。 sizeof(GifInfo) 0 0

WhatsAppギャラリーを開くと、そのGIFファイルは、サイズがsizeof(GifInfo)のrasterBitsバッファでダブルフリーのバグを引き起こします。興味深いことに、WhatsAppギャラリーではGIFファイルは2回解析されます。そのGIFファイルが再び解析されると、別のGifInfoオブジェクトが作成されます。Androidのダブルフリーの挙動により、GifInfoのinfoオブジェクトとinfo->rasterBitsは同じアドレスを指すことになります。その後、DDGifSlurp()は最初のフレームをinfo->rasterBitsバッファにデコードするため、infoとそのrewindFunction()(DDGifSlurp()関数の最後で呼び出されます)を上書きします。

ツールをダウンロード