【译】 Stealing the funds of all HTC EXODUS 1 users (HTC 区块链钱包安全漏洞分析)

news/2024/12/29 17:27:43/

HTC EXODUS 1手机带有集成的硬件钱包。该钱包允许通过拆分并将其发送给“受信任的联系人” 来备份其主种子。通常需要三个受信任的联系人来重建整个种子。我们表明,任何受信任的联系人或破坏了该受信任联系人的电话的攻击者都可以收回全部种子并窃取EXODUS 1所有者的所有资金。如果在2019年4月之前使用社交密钥恢复功能,我们强烈建议HTC EXODUS 1用户将其资金转移到另一种子。

介绍

在2018年,HTC推出了其首款面向区块链的智能手机EXODUS 1。与其他智能手机相比,它具有硬件钱包功能,可将主种子存储在安全的区域中。这样可以确保即使具有root特权的攻击者也无法访问主种子-它在安全区域内被加密。

图1:HTC EXODUS 1设备

 

我们对此款(硬件)钱包特别感兴趣,因为它提供了一个不错的功能:Social Key Recovery。在此博客文章中,我们将重点介绍EXODUS 1的特定功能。

它包含一个原始机制,可以强制执行种子的备份。种子被分成五份,每份被发送到受信任的联系人。如果用户丢失了手机,他们将可以通过请求其五个受信任联系人中的三个来传播种子来重建种子。份额数(5)和阈值(3)是固定的。

我们将首先提供有关实施社交密钥恢复的更多详细信息。然后,我们将介绍两种攻击方法:

  • 第一个演示了如何将阈值从三个可信联系人降低到两个。
  • 第二个示例演示了如何将阈值从三个受信任的联系人降低到一个,这意味着您的任何一个受信任的联系人都可以检索主种子并访问您的资金。

社交密钥恢复

主种子备份是硬件钱包用户的常见问题。仅从该种子生成每个用户机密。必须备份该种子,以确保您的钱包丢失并不意味着您的秘密丢失:可以从备份的种子将其恢复到新的钱包中。

如何备份种子?大多数硬件钱包都会提出一份纸质回收表(图3),用户必须在纸上写下其BIP39助记符(助记符是将您的种子表示为人类可读的单词的一种方式)。但是,要保证此纸张的安全性并非易事,因此为此设计了一些专用设备(图2)。例如,可以使用加密钢来防止助记符种子恶化。

图2:Cryptosteel-备份种子的设备

 

另一种解决方案是拥有一个备份硬件钱包,并用相同的种子初始化。但是,没有完美的解决方案可以解决所有问题。

图3:总帐回收表

 

图4:实践中的恢复表存储

 

HTC EXODUS 1带有自己的备份机制:社交密钥恢复。用户的种子被分成共享,并发送给受信任的联系人。1或2 的知识不会带来有关种子的任何信息。3 的唯一知识可以重建完整的种子。在该方案中,主种子永远不会在单个位置完全备份。

HTC硬件钱包采用名为Zion的Android应用程序的形式,以及存储种子并执行敏感操作的trustlet(在智能手机安全OS中执行的安全应用程序)的形式(图5)。秘密共享也在trustlet中计算:在下面,研究的机制在安全OS中实现

图5:Zion-体系结构概述

 

Shamir’s Secret Sharing

 

此问题可以通过以下方法解决:

  • 安全地存储多项式系数,以便以后可以恢复它们以生成其他份额,
  • 或仅在拆分前保持PRNG状态。

HTC使用的SSS实现受一个开源项目的启发,可在此处获得。此开源实现一次生成所有共享。一个人不能要求一个份额。为了允许随意添加受信任的联系人,HTC修改了实现,但牺牲了安全性。

HTC选择保留PRNG种子。但是该实现还使用了DRBG:这可确保输出是可预测的,并且生成的系数将始终相同。DRBG使用的种子(即PRNG状态)存储在加密分区内,仅可用于安全OS

随机数生成器:

原始实现的RNG(不确定的)已由以下功能代替:

#define RANDOM_POOL_SIZE 128static uint8_t random_pool[RANDOM_POOL_SIZE];size_t sss_rand(uint8_t *data, size_t len) {if (len == 0) {return 0;}while (len > RANDOM_POOL_SIZE) {memcpy(data, random_pool, RANDOM_POOL_SIZE);data += RANDOM_POOL_SIZE;len -= RANDOM_POOL_SIZE;}memcpy(data, random_pool, len);return len;
}

PRNG仅返回随机缓冲区的内容。此128字节的缓冲区由函数手动更新sss_update_secure_random_buffer

void sss_update_secure_random_buffer(const uint8_t *entropy, size_t size) {SHA256_CTX ctx;uint8_t digest[SHA256_DIGEST_LENGTH];uint8_t *p = random_pool;sha256_Init(&ctx);sha256_Update(&ctx, entropy, size);sha256_Final(digest, &ctx);for (int i = 0; i < 4; i++) {memcpy(p, digest, SHA256_DIGEST_LENGTH);sha256_Init(&ctx);sha256_Update(&ctx, p, SHA256_DIGEST_LENGTH);sha256_Final(digest, &ctx);p += SHA256_DIGEST_LENGTH;}
}

我们可以看到,作为输入参数传递给此函数的熵完全确定了PRNG的内部状态,因此也确定了PRNG的输出。正如我们之前所解释的,此行为是HTC想要的。该熵来自智能手机TRNG,其值由返回qsee_prng_getdata。使用128位熵并将其存储在加密分区中。

知道PRNG的输出足以完全确定整个随机输出序列。例如,如果我们知道返回的前32个字节,那么我们知道接下来的字节将对应于这些字节的SHA-256,然后对应于该值的SHA-256,依此类推……此外,PRNG的周期非常短128个字节。

但是,PRNG缺乏鲁棒性对我们的攻击无济于事:将使用PRNG的状态在两次调用之间固定的事实。如果两次之间的未调用,sss_rand则两次调用将始终返回相同的值sss_update_secure_random_buffer

HTC Social Key Recovery Shares计算

共享秘密是钱包的种子,用于导出每种加密货币的所有密钥。但是该实现增加了一个加密层来保护秘密。选择的密码是基于Salsa20和Poly1305(与TweetNaCl相同)的经过身份验证的流密码。

Fig. 6: The bitslice function

 

/** Create `n` shares with theshold `k` and write them to `out`*/
void sss_create_shares(sss_Share *out, const unsigned char *data,uint8_t n, uint8_t k)
{unsigned char key[32];unsigned char m[crypto_secretbox_ZEROBYTES + sss_MLEN] = { 0 };unsigned long long mlen = sizeof(m); /* length includes zero-bytes */unsigned char c[mlen];int tmp;sss_Keyshare keyshares[n];size_t idx;/* Generate a random encryption key */sss_rand(key, sizeof(key));
.../* Generate KeyShares */sss_create_keyshares(keyshares, key, n, k);
...

Here is the sss_create_keyshares code :

/** Create `k` key shares of the key given in `key`. The caller has to ensure* that the array `out` has enough space to hold at least `n` sss_Keyshare* structs.*/
void
sss_create_keyshares(sss_Keyshare *out,const uint8_t key[32],uint8_t n,uint8_t k)
{
...uint8_t share_idx, coeff_idx, unbitsliced_x;uint32_t poly0[8], poly[k-1][8], x[8], y[8], xpow[8], tmp[8];/* Put the secret in the bottom part of the polynomial */bitslice(poly0, key);/* Generate the other terms of the polynomial */sss_rand((void *)poly, sizeof(poly));
...

sage: load("rebuild_secret.py")
0102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f100a2b7065ad61a3ca403d62f61b21fabbab4de9811b3d2ce55c847488f231bf4e
Recovered 1 secret in 0.111693s

我们刚刚展示了如何降低到22重建机密所需的份额数(而不是33)。除了五分之三的阈值不再有效这一事实外,我们仍然认为安全威胁是不可忽略的。理想情况下,用户应将种子分成5个5彼此不认识的可信任联系人。实际上,使用55 受信任的联系人,即使其中一些彼此认识。

借助这种攻击,恶意联系人只需说服(或折衷)其他信任的联系人即可完全收回种子并访问资金。

打破机制

受先前攻击影响的固件如下(使用了欧洲ID):

  • 固件1.47.2401.2,它似乎是初始固件;
  • 固件1.53.2401.2,于2019-12-18。

2019年2月19日,发布了第三个固件。

通过研究这一点,我们非常惊讶地注意到sss_update_secure_random_bufferPRNG初始化函数从未被调用过。PRNG始终返回相同的值:其熵缓冲区,以固定值初始化(可能通过测试向量验证)。我们认为,trustlet已使用测试选项进行编译,而该选项应永远不会在生产中使用。结果,用于加密种子的密钥是固定的。由于此密钥已发送给每个联系人,因此任何人都可以解密种子并访问资金。

<span style="color:#514134"><span style="color:#2e2925"><code>secret_key <span style="color:#000000"><strong>=</strong></span> b<span style="color:#dd1144">"</span><span style="color:#dd1144">\x0e\x74\xcd\x69</span><span style="color:#dd1144">..."</span>
box <span style="color:#000000"><strong>=</strong></span> nacl<span style="color:#000000"><strong>.</strong></span>secret<span style="color:#000000"><strong>.</strong></span>SecretBox(secret_key)
nonce <span style="color:#000000"><strong>=</strong></span> b<span style="color:#dd1144">"</span><span style="color:#dd1144">\x00</span><span style="color:#dd1144">"</span> <span style="color:#000000"><strong>*</strong></span> <span style="color:#009999">24</span>
encrypted_seed <span style="color:#000000"><strong>=</strong></span> share1[<span style="color:#009999">1</span> <span style="color:#000000"><strong>+</strong></span> <span style="color:#009999">32</span>:]
seed <span style="color:#000000"><strong>=</strong></span> box<span style="color:#000000"><strong>.</strong></span>decrypt(nonce <span style="color:#000000"><strong>+</strong></span> encrypted_seed)[:<span style="color:#009999">16</span>]
<span style="color:#000000"><strong>print</strong></span>(mnemonic<span style="color:#000000"><strong>.</strong></span>Mnemonic(<span style="color:#dd1144">'english'</span>)<span style="color:#000000"><strong>.</strong></span>to_mnemonic(seed))
</code></span></span>

结论

负责任的披露

我们于2019.02.15向HTC Exodus披露了所有上述缺陷。

两个月后,还披露了其他漏洞(触摸屏驱动程序内部,受信任的UI内部以及ETH / BTC事务解析中的内存损坏)。HTC安全团队已经找到并修复了它们。

2019年3月5日,HTC Exodus团队在巴黎并借此机会访问了我们。他们甚至有机会进入Donjon。

HTC 在2019.03.25发行了新固件(1.62.2401.7)解决了所有这些问题。SSS修补程序包括使用可靠的PRNG,并将每个生成的共享保存在安全存储中。每当添加新的受信任联系人时,都会使用这些共享。

HTC Exodus于2019.04.05开始为Zion Hardware Wallet设立赏金计划。

在这些讨论之后,HTC向我们表明,此漏洞的披露触发了他们自己赏金计划的创建。当我们在建立赏金计划之前报告了这些错误时,我们没有得到任何赏金,但是当他们访问我们时,我们得到了出埃及记衬衫和贴纸。:) 非常感谢!

带走

我们研究了HTC Exodus 1手机的硬件钱包,并发现了社交密钥恢复机制上的两个关键漏洞。在攻击者能够在任何Zion信任联系人的Android手机上执行代码(Android漏洞,常规Android应用)的情况下,他可能会窃取相应EXODUS 1所有者的资金。或者,受信任的联系人可以直接访问种子。这些漏洞已得到正确修补。

不过,我们强烈鼓励所有使用社交密钥恢复来更改种子(并转移其资金)的EXODUS 1用户。确实,他们的种子可能早些受到破坏,或者仍然可以通过不会更新Zion的受信任联系人而受到破坏。

 

 


http://www.ppmy.cn/news/370634.html

相关文章

htc one m7刷Linux,HTC one m7官方刷机详细操作教程

由于很多软件功能都需要手机进行刷机&#xff0c;所以入手HTC one m7新机的用户一定想着如何刷机。下面就来教你HTC one m7官方刷机的详细操作教程&#xff01; 准备事项&#xff1a; 1、手机必须能用usb数据线电脑&#xff0c;因为是线刷&#xff0c;所以必须要有数据线&#…

htc one m7刷Linux,HTC One M7刷机教程 HTC One M7线刷教程

HTC One M7怎样线刷呢&#xff1f;其实网上的教程挺多的&#xff0c;为了给大家带来方便&#xff0c;小编把教程详细的整理了一通&#xff0c;下面就是HTC One M7线刷的教程&#xff0c;希望本篇教程对大家有使用价值&#xff0c;具体的请看以下操作&#xff1a;一&#xff1a;…

htc one m7刷Linux,htc one m7刷coloros系统教程

一、准备工作 1、ColorOS目前仅支持HTC One单卡国际版&#xff0c;型号为HTC 801e 2、刷机前准备好&#xff1a;固件包、recovery包 (点击下载) 3、刷机前请双清&#xff0c;否则会刷机不成功 5、安装好驱动&#xff0c;下载好相关文件&#xff1a;点此下载 二、刷机步骤 第一步…

htc x920e刷android7.0,HTC X920E (Butterfly) 刷回官方RUU固件教程

其实htc手机的线刷刷机是最容易的了&#xff0c;因为htc的官方包就是exe格式的&#xff0c;直接可以下载下来运行刷入就可以了&#xff0c;下面来说说HTC X920E/Droid DNA/Butterfly的具体的刷ruu的教程吧&#xff0c;这个教程也可以用来救砖用&#xff0c;如果你的手机刷机失败…

htc d826 android 6,【精】自己动手一:HTC826D用提取的MirrorLink协议APP安装包投影成功...

火腿肠被我拆坏,已经光荣牺牲下岗,发个百度网盘分享给需要朋友们。http://pan.baidu.com/s/1nuLXAJn 四川全新英朗车友会欢迎大家加入。 HTC826D用提取MirrorLink协议APP安装包投影成功 有需要APP车友可以论坛回复并留下联系方式,我看见后一定第一时间给你们转发…

htc+one+m7+linux驱动,htc one m7刷入recovery的教程

在这里给大家来说一下htc one m7怎么刷第三方的recovery吧,为什么要刷第三方的recovery呢,因为只有刷入了第三方的recovery才可以刷入第三方的rom包,一般第三方的rom包都是zip格式的,都是支持卡刷的,所以需要用到recovery,下面就来看看详细的刷入recovery的教程吧: 第一…

htc+one+m7+linux驱动,HTC One M7简易刷Recovery教程

HTC One M7作为当下HTC旗下的旗舰热门机&#xff0c;用户们对于刷机的需求都比较强烈&#xff0c;对于刷ROM的前提就是要刷入Recovery&#xff0c;当然作为安卓智能手机HTC one而言也不例外&#xff0c;最近有些用户在刷机啦论坛发帖希望刷机啦小编能分享具体刷Recovery的推出教…

htc+one+m7+linux驱动,HTC One M7线刷官方ruu包的教程

上次给大家说过了卡刷的教程了&#xff0c;可是很多人怕刷机失败&#xff0c;这种情况下就只能刷回官方的ruu包了&#xff0c;下面就来说说HTC One/M7/801e怎么来刷回官方的的ruu固件包&#xff0c;由于多数的官方ruu包都是exe格式的&#xff0c;都是用数据线连接电脑&#xff…