黑客入侵 BeReal——关于“中间人”攻击的实践课程
GenAI LIVE! | 2025年6月4日
BeReal 是什么?
BeReal是一款全新的社交媒体应用,据称比传统社交媒体平台更注重“活在当下”。这款应用的理念是,每天一次,每个人都会在同一时间收到一条通知,说“是时候活在当下了!”然后,每个人都有两分钟的时间记录自己当时的所作所为。手机会同时用前置摄像头和后置摄像头拍摄照片,然后上传到动态消息中,供所有(好友)查看。应用无法选择上传现有照片或编辑照片。你必须以当下的姿态发布内容。
我想看看我能在 iPhone 和 Macbook 之间使用一款名为Mitmproxy的软件来操控 BeReal 到什么程度。这款软件可以让我查看手机和互联网之间所有未加密的 HTTPS 请求。有了它,我可以随意查看、暂停、编辑和取消任何请求。这款软件还提供了一个 Python API,可以用来编写自定义脚本,稍后我会详细介绍。
著名域名
我花了一些时间使用该应用,了解了哪些端点与哪些功能相关联。借助这些信息,我能够构建该应用的运行概况。我已经知道 BeReal 是基于 Firebase 构建的,但似乎还有一个额外的端点来处理某些请求。
- firebasestorage.googleapis.com - Firebase 云存储,用于上传文件(图像)。
- us-central1-alexisbarreyat-bereal.cloudfunctions.net - Firebase 云功能端点,用于创建帖子、删除帖子、设置帖子标题、发送反应等。
- mobile.bereal.com - 次要端点 - 用于获取帖子提要、查看好友、添加好友。
劫持身份验证令牌
手机发出的请求使用(JSON Web Token)JWT进行身份验证,该令牌在每个请求的“授权”标头中发送。此标头会在几分钟后过期,但在此之前,我可以使用此令牌以经过身份验证的用户身份做任何我想做的事情。
BeReal 最常获取的端点是mobile.bereal.com/api/feeds/friends,它可以获取用户动态中好友的帖子列表。如果我在 Postman 中调用此端点时没有使用授权标头,我会立即收到一个403 - Forbidden
预期的状态码,因为我没有任何凭证可以证明我的身份。
在 Mitmproxy 的 feed 上,我可以直接复制粘贴任何 BeReal API 请求中包含的“Authorization” JWT,并将其用于我自己。在 Postman 中添加此标头后,我就能通过安全检查,并收到一个包含我所有好友帖子的 JSON 格式的欢迎信息,其中包含他们所有图片的链接、位置数据、重拍次数等信息。
我可以用同样的方法随意设置 BeReal 帖子的标题。通常情况下,只能设置一次,之后就永久生效了;但是,通过POST
向/setCaptionPost端点发出请求,我可以绕过这条规则,随意反复设置标题。
自定义 RealMoji
在 BeReal 中表达感激之情,与其点赞,不如发送一张“RealMoji”,也就是一张包含你脸部的图片作为回应。这为通常容易被忽略的回应增添了一层个性化色彩。你可以无限次重复拍摄 RealMoji,这为插入自定义图片作为回应提供了绝佳的机会,因为我们不像 BeReal 那样每天只限发送一张。让我们先来看看发送 RealMoji 时会发生什么。
POST
向 Firebase 存储端点发出请求,启动文件上传请求。
使用上一个PUT
请求返回的上传 ID 向 Firebase 发出请求,以上传图片。实际的图像数据将包含在该请求的正文中。
最终的 POST 请求会发送到云函数,其中包含待发送反应的详细信息(图像存储位置、反应类型等)。发送 RealMoji 反应总共需要三个请求。
操纵预期内容大小
在没有完全理解 Firebase 文件上传工作原理的情况下,我开始简单地修改请求的数据PUT
,因为那时图像内容被发送到服务器。
我在 Mitmproxy 中设置了一个过滤器,以便在请求通过时暂停它,然后修改请求的主体以包含我选择的 Jpeg 数据
然后我遇到了 400 状态错误,提示内容大小与预期不符。嗯……
我搜索了45243这个数字,发现它在之前的请求中已经定义过了。第二次尝试时,我又修改了这个POST
请求,使其与要上传文件的内容大小相匹配。
完成这些操作后,我两个请求都收到了 200 状态码。成功了!我修改的 Payload 已经上传了!然后我刷新了应用,就看到了我的“FakeMoji”的全部内容。
定制 BeReal 帖子
上传 BeReal 和发送 RealMoji 的流程基本相同。弄清楚如何操作 Firebase 上传后,创建自定义帖子也基本没什么区别。
自动化
Mitmproxy 还提供了一个 Python API,非常适合自动处理 HTTP 请求。基于上述流程,我编写了一个脚本,可以自动执行拦截请求和替换数据的操作。
import json
import os
import mitmproxy.http
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
FAKEMOJI = os.path.join(BASE_PATH, 'fakemoji.jpg')
def read_content(file_path):
with open(file_path, 'rb') as f:
data = f.read()
f.close()
return data
class Interceptor:
def __init__(self):
self.upload_type = None
# http request trigger
def request(self, flow: mitmproxy.http.HTTPFlow):
method = flow.request.method
url = flow.request.url
# Firebase upload domain
if ("firebasestorage.googleapis.com" in url):
# handle upload request (POST)
if method == "POST":
# content body
json_body = json.loads(flow.request.content)
# record upload type (necessary for following PUT request)
self.upload_type = json_body["metadata"]["type"]
# replace content length definition
flow.request.headers["x-goog-upload-content-length"] = os.stat(FAKEMOJI).st_size
# handle sending file content (PUT)
elif method == "PUT":
# only replace image if realmoji upload
if (self.upload_type == "realmoji"):
# replace file content
flow.request.content = read_content(FAKEMOJI)
addons = [
Interceptor()
]
该脚本监听元数据类型为“RealMoji”的 Firebase 请求,然后对其进行拦截和操作。上传的预期内容大小会被修改,请求内容PUT
会自动替换为本地文件fakemoji.jpg 的数据。
如何保护自己免受 MITM 攻击
如果您使用安装了自定义证书的公司管理电话,他们就有可能看到您发出此类请求。
事实上,恶意地对他人手机实施这种中间人攻击说起来容易做起来难。为了实现它,我需要配置iPhone的代理设置,并批准某些设备证书,这对于攻击者远程操作来说并不现实;然而,对于一台被入侵的设备来说,这样的事情就完全有可能了。
如果您使用安装了自定义证书的公司管理手机,他们可能会看到您发出此类请求。当然,并非所有公司都如此,但很难判断他们究竟有多“老大哥”,以及他们对您的数据和互联网使用情况掌握多少。
使用 VPN。
为了防止此类攻击,您可以尝试保护您的物理设备免遭恶意攻击,而为了进一步提升安全性,您可以使用 VPN!(这里有一个无耻的推荐链接。免费试用 30 天!)。诚然,VPN 并非完美无缺,而且 90% 的情况下,它们向公众的宣传都是错误的,但就此而言,它们可以有效地掩盖您的行为,避免网络窥探。
当我打开 VPN 并再次发送 RealMoji 时,Mitmproxy 什么也没检测到。我本来想附上一张截图来举例,但结果什么也没看到。之前显示的请求根本就没出现,就好像手机什么都没做一样。
总结
这个有趣的实验展示了如何操控你自己设备的 HTTP 流量,并查看应用在后台发出的请求。这再次证明了你永远不能信任前端,即使是原生应用。作为开发者,为了真正实现安全,你必须在后端安装有效的安全措施,以防止滥用;否则,你的生产环境应用也不过是沙盒环境而已!
鏂囩珷鏉ユ簮锛�https://dev.to/ozcap/hacking-bereal-a-practical-lesson-on-man-in-the-middle-attacks-10b6