我们旗下的专家安全研究团队 Kraken Security Labs发现了 Safepal S1 硬件钱包的漏洞。虽然我们未能从该钱包窃取加密货币,但我们确实发现了一些可能导致未来被盗用的弱点。
在 Kraken,我们致力于在攻击发生之前发现它们。发现漏洞后,我们于 2020 年 11 月 18 日向 Safepal 团队披露了这些漏洞的全部细节。
提升我们共同享有的技术安全性,是推动数字资产行业发展的重要途径。我们相信,提高公众意识和加强教育是实现这一目标的关键组成部分。

无效的防篡改检测
我们的测试发现,Safepal 的防篡改检测功能充其量只能说是无效。根据Safepal 的文档:“S1 内部嵌入了自毁和数据擦除机制。一旦多个传感器检测到任何软件或物理攻击,钱包将启动自卫机制,自毁机制将擦除私钥和所有钱包数据,防止黑客获取敏感数据,保护您的资产不落入不法分子之手。” 我们发现,拆开设备后,设备会停止启动,但只需重新连接一个引脚即可重新启动设备,并且设备内容并未被擦除。进一步的测试以及与 Safepal 的沟通表明,钱包仅在以下情况下才会擦除数据:(a) 设备通电;(b) 上述引脚断开超过 10 秒。在盗窃事件中,有动机的攻击者不太可能触发此警报。
开源软件许可违规
该钱包包含采用 GPLv2 许可的 U-Boot 和 Linux 内核。使用这些 GPL 许可的组件需要 Safepal 公开其产品的源代码,以便用户可以检查和修改运行在用户设备上的代码。我们已向 Safepal 索取源代码,但他们拒绝提供,这意味着 Safepal 违反了 GPL 许可协议。此类违规行为已导致诉讼,我们已敦促 Safepal 公开其源代码。
降级攻击
我们使用闪存编程器将之前的固件刷回设备,但设备并未检测到该固件。防止攻击者将固件降级到早期版本对于确保安全至关重要,因为这可以防止降级到例如存在漏洞的固件版本。
Safepal 已在https://www.safepal.io/upgrade发布了固件 V1.0.24以修复此问题。
进一步研究
此外,我们发现,U-Boot 的高度修改版本(通常只能通过“FIT 镜像”或 SoC 的专有安全启动流程支持安全启动)经过了加密和混淆处理。我们提出了一些关于 U-Boot 的研究结果,但由于混淆处理,我们的审查时间有限。根据我们的经验,与安全元件通信的应用处理器始终是加密货币硬件钱包的薄弱环节,SafePal S1 也不例外。SafePal 似乎在其产品中开发或重复使用了大量的混淆技术,这有效地延缓了我们的研究进度。但由于这种混淆以及其 GPL 源代码缺乏透明度,我们尚不清楚 SafePal S1 是否真正拥有经过验证的安全启动链。
我们感谢 Safepal 对这些问题的回应。我们鼓励您查看他们在https://blog.safepal.io/our-response-to-the-security-findings-from-kraken-security-labs的回应。
技术细节
SafePal S1 是一款加密货币硬件钱包,它采用嵌入式 Linux 系统,并搭载片上系统 (SoC)。因此,这款钱包的架构与目前最流行的基于微控制器的钱包(例如 Trezor 和 Ledger 钱包)有所不同。任何基于嵌入式 Linux 的系统在安全方面都面临着一个挑战,那就是如何确保启动过程的安全,因为大多数(但并非全部)支持 Linux 的微处理器都需要外部闪存和外部 RAM。此外,虽然 Linux 是使用最广泛的操作系统之一,但它本身并不安全,这意味着 SafePal 需要购买安全解决方案或自行进行安全加固。
高级硬件分析
SafePal 的硬件与其他常见钱包(例如 Ledger Nano S/X 或 Trezor One/T)有显著不同:后两者都基于微控制器,而 SafePal 则基于运行 Linux 的完整系统芯片 (SoC)。我们测试的是 S1P_Ver03 硬件版本。
该设备的主处理器标记为“SafePal S1”,但其底层处理器很可能是全志(Allwinner)的处理器。这一结论是通过将SafePal S1(引脚图)与全志i3处理器(https://dn.odroid.com/obsolete/Allwinner_i3_Datasheet_V1.0.pdf)的引脚排列进行比对得出的。值得注意的是,该处理器没有集成闪存,设备启动时使用的是外部闪存芯片,即Zbit Semiconductor的ZB25VQ64。此外,电路板上还有一个SOIC-8封装的芯片,推测它是安全元件。遗憾的是,我们无法从芯片标识中确定其供应商。

SafePal的处理器:SafePal S1 IDC80X1E——全志芯片。
发现1:篡改检测绕过
根据Safepal 的文档:“S1 内部嵌入了自毁和数据擦除机制。一旦多个传感器检测到任何软件或物理攻击,钱包将启动自卫机制,自毁机制将擦除私钥和所有钱包数据,防止黑客获取敏感数据,保护您的资产免遭窃取。”
防篡改检测系统分多个步骤进行分析:
案件开庭
首先,我们测试了使用破坏性和非破坏性方法打开 SafePal 钱包是否会导致篡改事件。结果表明,打开 S1 的外壳不会导致篡改事件,也不会阻止 S1 正常工作。
移除射频屏蔽层
SafePal 的处理器、闪存、安全元件和电源管理集成电路 (PMIC) 均由一个射频屏蔽罩保护。该射频屏蔽罩通过多个卡扣固定,并非完全焊接。因此,使用小型一字螺丝刀即可轻松进行无损拆卸。移除射频屏蔽罩可能会导致设备无法正常启动。经测量发现,右上角的射频屏蔽罩卡扣与其他卡扣不同,未接地。使用一根 0.4 毫米的导线将该卡扣连接到旁边裸露的接地焊盘上,重新接地后,防篡改事件得以消除,SafePal 钱包恢复正常工作。值得注意的是,设备并未重置,原有凭证(PIN 码等)仍然有效。
没有找到其他防篡改措施。

SafePal 配备射频屏蔽罩

SafePal 的射频屏蔽罩已被移除。负责检测射频屏蔽罩移除的触点通过一小段导线接地。

旁路射频屏蔽检测的特写镜头
盆栽
闪存芯片和安全元件均采用一种未知化合物进行灌封。然而,用热风枪加热后,灌封化合物变得易碎。此时,可以用一把小号一字螺丝刀刮掉灌封化合物,而不会损坏设备的任何组件。这样就可以直接接触到SPI引脚,进行进一步的探测。

SafePal 的射频屏蔽罩已被移除,闪存芯片上的封装层也被刮掉了。
闪存转储
通过读取芯片上的标记确定闪存芯片类型后,尝试使用 flashrom 工具在系统中转储闪存数据。由于撰写本文时 flashrom 工具尚不支持该芯片,因此需要在 flashrom 工具中实现自定义支持。最终成功获取了完整的闪存转储数据。
经过进一步分析,确定闪存的前 0x8000 字节左右使用闪存芯片的 OTP 安全功能设置为只读,而闪存芯片的其余部分既可读又可写。
Flash内容分析
从闪存的第 5 个字节开始,可以找到字符串“eGON.BT0”。进一步研究表明,这是基于全志芯片的设备上早期引导加载程序的常见头部信息:https ://linux-sunxi.org/EGON

SafePal 固件中发现 eGON.BT0 字符串
调查结果 2:违反 GPL 协议
从地址 0x40000 开始,发现了一个包含 Linux 内核的 Android 启动镜像,表明该设备运行的是 Linux 系统。由于未发现或收到任何 GPL 许可声明,这表明该设备违反了 GPL 许可协议。直接向 SafePal 提出的进一步请求未得到任何回复。
在地址 0x2A0000 处发现了 SquashFS 文件系统,提取后发现其中包含完整的 Linux 根文件系统,以及多个 GPL 许可的工具。
在地址 0x740000 处,发现了一个 JFFS2 文件系统,其中包含 sqlite3 数据库中的配置数据,包括事务地址。
此外,还找到了 JPEG 格式的启动徽标图像和 JPEG 格式的关机徽标图像。
Flash修改尝试
我们曾多次尝试修改闪存芯片的内容:
经确定,Linux 内核、SquashFS 文件系统和启动徽标均可修改。然而,修改后设备无法启动。
JFFS2 文件系统的内容和关机徽标可以修改,而不会使设备无法启动,但是对关机徽标的更改不会反映在实际关机中。
由于闪存芯片中设置了上述安全位,因此无法修改第一阶段引导加载程序。
闪电重制
更换主闪存芯片很可能就能在设备上执行代码。由于芯片内容保持不变,设备无法检测到这种更改。要执行代码,需要对多个检查进行逆向工程和反混淆。虽然可行,但这非常耗时,尤其考虑到 U-Boot 混淆链的复杂性,因此本次审计并未涉及此项工作。
固件升级
我们对 wallet_update 二进制文件中的固件升级过程进行了分析和逆向工程。用户可以在 SafePal 网站上输入序列号下载固件升级包,但我们发现,对于相同的硬件版本,固件升级包的内容完全相同,因此无法进行个性化设置。所有设备出厂时均预装了当时最新的固件版本 v.1.0.17。固件升级包的下载地址为:https://www.safepal.io/fw/S1F/v1.0.17/upgrade.bin
还发现固件升级是加密的,对固件二进制文件的修改会导致升级过程失败。
在分析 wallet_update 二进制文件时发现,该文件使用了大量异或运算数据进行混淆。通过对 wallet_update 进行二进制修补,使其能够在 qemu 用户模式下运行,从而允许在普通系统上解密固件升级。
研究还发现,固件升级在成功解密后,会对固件执行疑似 ECDSA 签名校验的操作。该实现方式与 trezor-crypto 非常相似,但由于未找到 trezor-crypto 许可协议要求的确认信息,因此无法对其进行全面验证。
发现 3:降级攻击
防止攻击者将固件降级到早期版本对于确保安全至关重要,因为它可以防止降级到例如存在漏洞的固件版本。
在本次审计期间,SafePal 固件版本 v1.0.18 发布了。一个钱包被升级到该固件版本,并启动和测试。在确认固件升级成功后,使用闪存编程器将固件刷回之前的 v1.0.17 版本。降级后设备功能完全正常,固件未检测到此次降级,钱包也继续正常运行,这表明该设备存在降级攻击漏洞。
启动过程
第一阶段引导加载程序
大多数全志设备使用 U-Boot 作为第二阶段引导加载程序,但是无法在闪存系统中找到 U-Boot。相反,在闪存中找到了对“XBOOT”和“XTAB”的引用,但这与任何已知的引导加载程序(例如https://github.com/xboot/xboot)都不匹配。
鉴于该设备运行Linux系统,且启动配置需要在某个地方进行,我们使用Ghidra对第一阶段引导加载程序进行了逆向工程。结果发现,该第一阶段引导加载程序使用了大量的混淆技术来混淆字符串和密钥材料,并最终发现它能够解密第二阶段引导加载程序。为了理解第二阶段引导加载程序的解密和验证过程,我们使用Unicorn Engine模拟器模拟了整个引导加载程序,从而实现了对第二阶段引导加载程序的完整解密。此外,我们还发现第一阶段引导加载程序能够验证第二阶段引导加载程序的ECDSA签名。

模拟第一阶段引导加载程序,包括检查固件检查,从而允许测试修改后的固件以确定其是否能通过检查。
第二状态引导加载程序
对第二阶段引导加载程序的快速分析立即显示,它是一个修改过的 U-Boot 引导加载程序。鉴于 U-Boot 采用 GNU 通用公共许可证 (GPL) 授权,且未找到任何 GPL 声明或源代码,这构成了违反 GPL 的行为。
经查明,U-Boot 已被修改,采用了某些混淆和解密方法。
应用分析
从提取的 squashfs 文件系统中恢复了两个二进制文件,分别为“ wallet ”和“wallet_update” 。wallet是主钱包应用程序,而wallet_update实现了固件升级过程。
在钱包二进制文件的固件升级检查中发现了一个检查时间到使用时间 (TOCTTOU) 的问题。然而,wallet_update 功能会执行第二次检查,该检查无法绕过。此外,每次启动时还会执行第三次检查,即使绕过软件锁定,该检查也会失败。
配置与数据库分析
JFFS2 文件系统中有两个配置文件:wallet.cfg 和 wallet.db。
Wallet.cfg 文件包含钱包是否已设置、钱包名称等配置项。经发现,该配置项可以被随意更改,攻击者可以随意修改钱包名称等配置项。
wallet.db 是一个基于 sqlite3 的数据库,其中包含钱包的交易信息、已配置的币种以及地址。修改该数据库会导致钱包应用程序无法正常工作(SafePal 只会显示黑屏)。目前尚不清楚这是由于 SQLite 版本不兼容(钱包使用的版本是 2012 年的 3.7.11),还是由于其他未知的安全机制。
数据库分析
由于数据库包含私人信息(地址和交易记录),我们尝试从设备中恢复地址。通过分析钱包二进制文件,我们发现数据库中存储的地址使用 AES 加密,密钥来源于各种静态来源以及疑似安全元件输入。
某些修改会导致设备提示用户重新设置钱包,但使用未修改的闪存镜像重新刷写设备后,钱包功能即可完全恢复。这可能表明设备存在防篡改检测和响应机制效率低下的问题。
