【车联网】逆向工程一个电动汽车充电器

介绍

电动汽车在过去几年已经变得非常普遍。在挪威,它们占所有新车销售的一半以上。支持电动汽车的充电器已经有效地成为我们日常生活所依赖的关键基础设施。与此同时,关于它们工作原理的公开信息有限。

出于好奇,我们决定购买 Zaptec Pro。这款型号旨在用于更大规模、联网安装,如停车场和公寓楼。在本文撰写时,Zaptec Pro 是挪威道路上最常见的充电器之一。

设备概述

充电器是一种令人惊讶的强大设备。它运行基于 Debian 的完整操作系统,具有 Wi-Fi、4G LTE、蓝牙和电力线(PLC)网络连接功能。把它想象成一种强化版的树莓派也不为过,带有一些 230V 继电器。

作为最终用户,Zaptec 可能只是您插入汽车的黑盒子上看到的标志。然而,在幕后,Zaptec 拥有一个完整的云生态系统,旨在打开和关闭这些继电器,并为您的电力消耗计费。

要使用公共充电器,客户通常需要下载一个应用程序。这些应用程序通常由停车场公司和充电网络运营商发布。客户将在应用程序中输入付款信息,并选择要使用的充电器。此时,应用程序将向云端发出请求,并使用应用程序后端与 Zaptec 之间的集成来启动新的充电会话。

Zaptec 使用 Azure IoT Hub 与他们的设备进行通信和控制。有关其工作原理的更多信息将在下文中讨论。

拆解

充电器有两块 PCB 板,叠放在一起,并通过一个 40 针连接器连接。底部 PCB 板包含大部分与电源相关的元件,而上部 PCB 板则容纳了“智能”元件。

【车联网】逆向工程一个电动汽车充电器

深入研究上层 PCB,有一些不同的感兴趣的组件:

  • 在绿色部分有压电蜂鸣器和 RGB 指示灯

  • 在蓝色部分有 RFID 组件

  • 黄色是 4G 调制解调器和天线

  • 橙色是一款 QCA7005 高通芯片组,用于通过电力线(PLC)进行网络通信

  • 紫色是一款 PIC24E 微控制器

  • 从左到右,我们有一个 512 MB NAND 闪存芯片,一个基于 ARM Cortex-A7 的微控制器,以及 512 MB 的 RAM

【车联网】逆向工程一个电动汽车充电器

调试接口

我们之前通过将设备连接到 Wi-Fi 网络并运行端口扫描来了解设备正在运行 Linux。它在端口 22 上有一个 SSH 监听器。

基本的暴力密码攻击没有奏效,所以是时候开始寻找 PCB 上的调试接口了。该板的布局相当清晰,组件被分成了几个不同的部分。在该板上最有可能运行 Linux 的芯片是 ARM 处理器。它也靠近闪存和 RAM 芯片,这似乎是合乎逻辑的。

由于它是一款 ARM 处理器,我们希望看到 JTAG/SWD 接口和/或 UART 串行端口。如果保留 JTAG/SWD 端口,理论上应该允许我们转储固件并修改运行代码。处理器在物理上具有所有这些引脚,并且可以通过查看数据表找到。但是,对于在电路 BGA 上焊接来说是不可能的。因此,我们或多或少取决于设计师在 PCB 上暴露的内容。虽然很容易注意到 NAND 闪存左侧未连接的 3 引脚标头。

【车联网】逆向工程一个电动汽车充电器

标题栏有三个引脚,其中一个是地线,所以很可能是:

  • 无(在生产固件中禁用)

  • ARM 的串行线调试(SWD)

  • UART

我们焊接了一个排针,并将逻辑分析仪连接到引脚上,发现了一个 UART 串行接口。

【车联网】逆向工程一个电动汽车充电器

控制台日志提供了关于设备的有用信息,但不幸的是没有给我们一个 shell。引导加载程序也被锁定,不允许中断引导过程,这阻止了我们在 U-Boot 环境中进行操作。

就在这时,我们意识到 ARM 处理器下面的那个小银色长方形几乎是一个合适大小的 microSD 卡槽。

【车联网】逆向工程一个电动汽车充电器

我们把一个 SD 卡放入插槽,然后重新启动充电器。它没有启动。要么我们制造了一个砖头,要么充电器试图使用 SD 卡作为启动设备,而我们没有任何东西可以启动。取出 SD 卡并再次启动验证了我们的怀疑。

调查启动过程

我们尝试使用各种图像刷写 SD 卡,这些图像是基于相同处理器的开发板,取得了不同程度的成功。有几个图像成功启动,但不可避免地在加载 Linux 内核之前在 U-Boot 中挂起。

这个问题最终归结于开发板和 Zaptec PCB 之间存在硬件差异。这导致图像不兼容。Zaptec 可能使用了不同的内存,或将各种组件连接到不同的引脚。

U-Boot 和 Linux 了解设备硬件配置的方式是通过设备树。这本质上是一个描述硬件如 RAM 和闪存存储的文件,以便操作系统知道如何与它们交互。通常,设计师会根据电路板原理图创建设备树。由于我们无法访问 Zaptec 的原理图,我们只能寻找另一个解决方案。

倾倒 NAND 闪存

访问设备固件始终是一件好事。这不仅可以提供有关设备工作原理的更多信息,而且如果我们能够访问 Zaptec 设备树,就可以允许我们编译自己的兼容引导程序或操作系统。

这并不是世界上最干净的工作,但我们成功地将 TSOP48 NAND 芯片去焊并使用 TL866II Plus 编程器倒出了其内容。

【车联网】逆向工程一个电动汽车充电器

【车联网】逆向工程一个电动汽车充电器

【车联网】逆向工程一个电动汽车充电器

固件分析

程序员生成的二进制文件是 NAND 闪存的精确逐字节副本。这带来了一些挑战,因为我们想要分析的分区与其他数据混合在一起,例如纠错位和为磨损均衡保留的空间。这被称为带外(OOB)数据,由集成到 ARM 处理器中的 NAND 控制器引入。

【车联网】逆向工程一个电动汽车充电器

Damien Cauquil 在 2019 年在 HITB Amsterdam 举行了一场演示,详细介绍了这个过程在基于 I.MX 的处理器上是如何工作的。幸运的是,他发布了一个移除 OOB 数据的工具。它生成一个类似于 U-Boot 或 Linux 与 NAND 闪存交互时看到的二进制文件。

【车联网】逆向工程一个电动汽车充电器

在固件中研究了一段时间后,我们成功地从引导分区中提取出了 Zaptec 的设备树二进制文件。

编译自定义引导程序

我们考虑过构建 Linux 以从 SD 卡引导,但最终决定只编译 U-Boot。如果我们重新焊接 NAND 闪存,并且有能力进入 U-Boot 环境,我们可以控制传递给 Linux 内核的引导参数。这将允许我们进入单用户模式,基本上只是将您放入一个根 shell 而不提示输入密码。

我们将设备树二进制文件包含在 U-Boot 构建过程中,并将引导加载程序刷入 SD 卡。一旦进入我们的自定义 U-Boot 环境,我们设置了一些环境变量,告诉 U-Boot 从 NAND 闪存启动并进入单用户模式。

【车联网】逆向工程一个电动汽车充电器

一旦进入单用户模式,我们设置了一个新的根密码,并在没有 SD 卡的情况下重新启动。现在我们可以使用新的根密码通过 WiFi 连接 SSH!

【车联网】逆向工程一个电动汽车充电器

事物如何运作

现在拥有对运行设备的根访问权限,我们想要调查充电器工作的几个不同方面。

蓝牙 PIN 码

该设备出厂时设置了一个四位数的 PIN 码。它印在盒子上,无法更改。它用于管理一些设置,比如充电器如何连接到互联网。

【车联网】逆向工程一个电动汽车充电器

我们想要回答的两个问题是:

  • PIN 码是如何生成的?许多物联网设备从易于猜测的标识符(如序列号或 MAC 地址)生成安全代码。如果在这种情况下是真的,也许我们可以管理任意设备。

  • 拥有设备 PIN 码的访问权限可以做什么?您可以免费充电或启动比特币矿工的僵尸网络吗?

从我们可以看到的情况来看,PIN 码似乎是在设备最初编程时从工厂的服务器设置的。浏览设备上出现的第一批日志似乎暗示了这一点。

【车联网】逆向工程一个电动汽车充电器

由于 PIN 码(和 Azure 访问令牌)是从工厂的服务器进行配置的,我们不会很快获得生成这些密钥的代码。理想情况下,PIN 码应该是一个真正随机的数字,而不是基于标识符或一些奇怪的密码学。

这仍然引出了一个问题,即如果您知道 PIN 码,您实际上可以做些什么。在购买充电器之前,我们对 Android 应用程序进行了反编译,并在蓝牙低功耗(BLE)功能中进行了探索。在 Android 应用程序的 BLE 特征列表中,“RunCommand”确实很有趣。

【车联网】逆向工程一个电动汽车充电器

在 Android 应用程序的代码中进一步挖掘发现了通过蓝牙启动和停止充电的命令。假设你有 PIN 码,也许你可以通过蓝牙发出这些命令来获得免费充电?

【车联网】逆向工程一个电动汽车充电器

现在有了对充电器代码的访问权限,我们可以看到它实际上是做什么的。BLE 接口是用 Python 编写的,这使得查看变得更容易。

【车联网】逆向工程一个电动汽车充电器

所以基本上在这里发生的是,您发送到 BLE 特征的任何值都会传递给 smart_service.RunCommand()函数。智能服务是在充电器上运行的另一个进程,使用.NET mono 编写。Python 通过 D-Bus 消息接口与智能服务通信。让我们看看 RunCommand 函数能做什么。

【车联网】逆向工程一个电动汽车充电器

.NET 代码似乎只实现了重新启动和更新固件命令。启动充电和停止充电最终命令似乎是在 Android 应用程序中部分实现的功能,但从未在充电器上实现。没有通过蓝牙免费充电。

除了重新配置设备,可能导致其断开网络并停止工作外,通过蓝牙接口可以做的似乎有限。

值得注意的是,由于 BLE 的性质,当设备由技术人员配置时,有可能窃取 PIN 码,但这需要有人在那个确切的时刻进行监听。Zaptec 还在 Python 代码中实现了 PIN 暴力保护。如果您多次输入错误的 PIN 码,蓝牙接口将关闭。蓝牙接口关闭的时间会随着每次错误的 PIN 尝试而增加。因此,您可以暴力破解 PIN 码,但这需要很长时间。从表面上看,对攻击者来说,访问 BLE 接口似乎并不是非常有趣的。

SSH 监听器

连接设备到网络后,我们想要做的第一件事之一是弄清楚是否有硬编码的根密码。没有。

Zaptec 在充电器上放置了两个公共 SSH 密钥,但在我们在单用户模式下配置密码之前,阴影文件是空的。 这种配置允许 Zaptec 使用正确的密钥对通过 SSH 登录,但有效地禁用了 SSH 侦听器和 UART 控制台的密码身份验证。

【车联网】逆向工程一个电动汽车充电器

云连接

我们想调查的最后一个领域是云连接。我们早期进行了一些数据包捕获,并知道充电器正在与 Azure IoT Hub 通信,但由于流量被加密,无法看到它发送了什么。

通过 root 访问权限,我们能够安装我们自己的根证书,并通过 mitmproxy 代理流量执行 TLS 解密。

【车联网】逆向工程一个电动汽车充电器

分析解密的 PCAP 文件使我们能够验证充电器正在使用共享访问签名与 Azure IoT Hub 进行通信,这是一种基于在工厂预配的秘密派生凭据的身份验证机制。

查看发布到 IoT Hub 的几条消息,揭示了它发送回 Zaptec 的数据类型。快速查看发现了一些内容,如 Linux 内核日志和电力消耗数据。

【车联网】逆向工程一个电动汽车充电器

我们还查看了.NET 代码,以查看通过 IoT Hub 它能够做什么。我们无法轻松测试此功能是否有效,但我们发现了似乎是 Zaptec 远程调试其设备的方法。

第一个是一个名为 RunRemoteCommand 的函数。这将云端接收到的消息内容直接传递给 Process.Start。

【车联网】逆向工程一个电动汽车充电器

一个名为 StartRemoteTunnel 的第二个有趣功能似乎允许 Zaptec 创建一个反向 shell 返回到互联网上的 SSH 监听器。

【车联网】逆向工程一个电动汽车充电器

结论

总的来说,在我们的调查过程中,我们并没有发现任何关键的安全问题。尽管在一些方面可能还有改进的空间。例如,如果他们使用了签名固件或加密了 NAND 闪存,我们要想获取设备的根访问权限就会困难得多。这两个功能已经由内置在充电器中的 ARM 处理器支持。

安全似乎在整个过程中考虑到了多个步骤,并且比我们进入项目时预期的要好。


声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与技术交流之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。

本人长期从事车联网攻防一线,公众号中的相关工具和内容在星球会有进一步的扩展解读,同步了解国内外车联网一线信息,内容每日都会更新,微信识别二维码付费即可加入,如不满意,72 小时内可在 App 内无条件自助退款。

5-20人 88元

20-50人 98元

50-100人 128元

【车联网】逆向工程一个电动汽车充电器


原文始发于微信公众号(车联网攻防日记):【车联网】逆向工程一个电动汽车充电器

版权声明:admin 发表于 2024年7月29日 下午3:41。
转载请注明:【车联网】逆向工程一个电动汽车充电器 | CTF导航

相关文章