简介
随着全世界竞相实现互联互通,上市时间往往比安全性更重要。
今天的节目将介绍如何发现智能汽车应用中的漏洞!
如果您认出了上图中的某个徽标,那么您可能面临风险!授权不当可能会导致未经授权访问智能汽车应用(行车记录仪、汽车信息娱乐系统),允许访问位置历史记录、视频等。
受影响的供应商:
Szime
Proof.co.il(已修复)
我于 2023 年 11 月发现了此漏洞,在一年多的时间里多次尝试联系两家供应商(通过多种渠道)后,我发布了此漏洞的详细信息,以便用户可以保护自己免受车辆监控。Proof.co.il
已确认并修复了该问题,但 Szime 尚未做出回应。
漏洞 -系统简介
当客户购买新设备时,他们会下载相关应用程序,并使用名为 的唯一标识符将设备注册到该应用程序IMEI。此过程称为设备绑定。一旦用户将相机绑定到手机,他们就可以完全控制它并可以访问其所有功能,包括位置历史记录和视频。
问题 1 - IMEI 号码可预测
我发现 IMEI 号码由 14 位数字组成,其中前 13 位数字是标识符,最后一位数字是Luhn 算法计算出的校验和数字。
问题是 IMEI 号码是连续的。例如,如果您的车载摄像头有 IMEI 01234567891233,那么之前的 IMEI 很有可能01234567891225属于另一台摄像头。
还有一个 API 请求用于检查 IMEI 是否存在:
首先,登录以获取access_token
POST /oauth/token HTTP/1.1
...
grant_type=password&client_id=app&client_secret=api1234&scope=SCOPE_READ&username=xxxxxxxxxx&password=yyyyyyyyyy
(🤦♂️让我们花一点时间来欣赏客户端应用程序中嵌入的这个奇妙的秘密 API 密钥api1234:)
username是一个电话号码。
然后检查 IMEI 是否存在:
GET /api/v2/user/sendbindreq?access_token=xxxxxxxxx&did=yyyyyyyyyyyyyy HTTP/1.1
...
did是设备 ID - 又名 IMEI。
这使得攻击者能够通过暴力破解的方式检索所有现有的 IMEI。
由于 api 无法验证绑定到新相机的手机所有者是否也是该相机的所有者,因此:
任何用户都可以通过猜测 IMEI 为自己注册任何未注册的相机
此外,IMEI 号码在某些设备(如行车记录仪)上可见,行人可以透过车窗查看并获取 IMEI 号码。
由于所有的 IMEI 都已经刷入相机,遗憾的是这个问题无法修复!
问题 #2 - “窃取”已绑定的相机
我们已经确定,一旦将相机绑定到手机,只有他们才能访问其功能。
但如果攻击者能够通过将相机绑定到手机来“窃取”相机怎么办?不幸的是,这是可能的。
我发现解除绑定的过程没有得到适当的授权。看一看:
如果攻击者发送此“解除绑定”请求,并且其中imei含有受害者设备的 IMEI:
POST /api/v2/user/debinddev?access_token=xxxxxxxxx HTTP/1.1
...
{"imei":"yyyyyyyyyyyyyy" }
无需验证请求发起者是否是设备所有者,设备会立即解绑!
这意味着任何有帐户的用户都可以根据设备的 IMEI 号码解绑任何设备!
接下来,攻击者需要做的就是通过以下请求将设备绑定到他们的帐户:
POST /api/v2/user/binddev?access_token=xxxxxxxxx HTTP/1.1
...
{"name":"yyyyyyyyyy","imei":"zzzzzzzzzzzzzz", "nick":"notImportant"}
name是电话号码。
就这样!设备现在已绑定到他们的帐户,他们可以访问设备的所有直播和录制数据!
后端代码(猜测)
虽然我无法知道后端服务器上运行的是什么代码,但如果使用 flask 框架用 python 编写,我猜测代码是这样的:
@app.route('/api/v2/user/debinddev', methods=['POST'])
def debind_dev():
access_token = request.args.get('access_token')
imei = request.json.get('imei')
if not access_token or not imei:
return "Bad Args"
response = db.verify_access_token_valid(access_token)
if not response.is_ok:
return "Bad Token"
db.debind_camera(imei)
return "OK"
解决办法(猜测)
我认为修复方法如下:
@app.route('/api/v2/user/debinddev', methods=['POST'])
def debind_dev():
access_token = request.args.get('access_token')
imei = request.json.get('imei')
if not access_token or not imei:
return "Bad Args"
response = db.verify_access_token_valid(access_token)
if not response.is_ok:
return "Bad Token"
# --------- FIX -----------
user = db.get_user_for_access_token(access_token)
if not user.does_own_camera(imei):
return "Bad Permissions"
# -------------------------
db.debind_camera(imei)
return "OK"
额外问题 - 无需电话验证即可注册
没有验证注册的电话号码是否属于用户。没有短信,什么都没有。
这个问题使这些攻击变得更容易,因为这消除了对活跃电话号码的要求,并允许整个攻击从脚本执行!
POST /api/v2/user/register HTTP/1.0
...
{"pn":"xxxxxxxxxx", "pwd":"yyyyyyyyyy"}
pn代表电话号码,pwd代表密码
减轻
我已收到确认,Proof.co.il 已修复其服务器上的问题。另一方面,Szime 没有回应,因此在他们修复此问题之前,我建议 Szime 用户断开其设备与互联网的连接。Szime,如果您正在阅读此内容,请停止对安全研究人员进行攻击。
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里