【译】 Stealing the funds of all HTC EXODUS 1 users (HTC 区块链钱包安全漏洞分析)
HTC EXODUS 1手機(jī)帶有集成的硬件錢包。該錢包允許通過拆分并將其發(fā)送給“受信任的聯(lián)系人”?來備份其主種子。通常需要三個(gè)受信任的聯(lián)系人來重建整個(gè)種子。我們表明,任何受信任的聯(lián)系人或破壞了該受信任聯(lián)系人的電話的攻擊者都可以收回全部種子并竊取EXODUS 1所有者的所有資金。如果在2019年4月之前使用社交密鑰恢復(fù)功能,我們強(qiáng)烈建議HTC EXODUS 1用戶將其資金轉(zhuǎn)移到另一種子。
介紹
在2018年,HTC推出了其首款面向區(qū)塊鏈的智能手機(jī)EXODUS 1。與其他智能手機(jī)相比,它具有硬件錢包功能,可將主種子存儲(chǔ)在安全的區(qū)域中。這樣可以確保即使具有root特權(quán)的攻擊者也無法訪問主種子-它在安全區(qū)域內(nèi)被加密。
圖1:HTC EXODUS 1設(shè)備?
我們對此款(硬件)錢包特別感興趣,因?yàn)樗峁┝艘粋€(gè)不錯(cuò)的功能:Social Key Recovery。在此博客文章中,我們將重點(diǎn)介紹EXODUS 1的特定功能。
它包含一個(gè)原始機(jī)制,可以強(qiáng)制執(zhí)行種子的備份。種子被分成五份,每份被發(fā)送到受信任的聯(lián)系人。如果用戶丟失了手機(jī),他們將可以通過請求其五個(gè)受信任聯(lián)系人中的三個(gè)來傳播種子來重建種子。份額數(shù)(5)和閾值(3)是固定的。
我們將首先提供有關(guān)實(shí)施社交密鑰恢復(fù)的更多詳細(xì)信息。然后,我們將介紹兩種攻擊方法:
- 第一個(gè)演示了如何將閾值從三個(gè)可信聯(lián)系人降低到兩個(gè)。
- 第二個(gè)示例演示了如何將閾值從三個(gè)受信任的聯(lián)系人降低到一個(gè),這意味著您的任何一個(gè)受信任的聯(lián)系人都可以檢索主種子并訪問您的資金。
社交密鑰恢復(fù)
主種子備份是硬件錢包用戶的常見問題。僅從該種子生成每個(gè)用戶機(jī)密。必須備份該種子,以確保您的錢包丟失并不意味著您的秘密丟失:可以從備份的種子將其恢復(fù)到新的錢包中。
如何備份種子?大多數(shù)硬件錢包都會(huì)提出一份紙質(zhì)回收表(圖3),用戶必須在紙上寫下其BIP39助記符(助記符是將您的種子表示為人類可讀的單詞的一種方式)。但是,要保證此紙張的安全性并非易事,因此為此設(shè)計(jì)了一些專用設(shè)備(圖2)。例如,可以使用加密鋼來防止助記符種子惡化。
圖2:Cryptosteel-備份種子的設(shè)備?
另一種解決方案是擁有一個(gè)備份硬件錢包,并用相同的種子初始化。但是,沒有完美的解決方案可以解決所有問題。
圖3:總帳回收表?
圖4:實(shí)踐中的恢復(fù)表存儲(chǔ)?
HTC EXODUS 1帶有自己的備份機(jī)制:社交密鑰恢復(fù)。用戶的種子被分成共享,并發(fā)送給受信任的聯(lián)系人。1或2?股的知識(shí)不會(huì)帶來有關(guān)種子的任何信息。3?股的唯一知識(shí)可以重建完整的種子。在該方案中,主種子永遠(yuǎn)不會(huì)在單個(gè)位置完全備份。
HTC硬件錢包采用名為Zion的Android應(yīng)用程序的形式,以及存儲(chǔ)種子并執(zhí)行敏感操作的trustlet(在智能手機(jī)安全OS中執(zhí)行的安全應(yīng)用程序)的形式(圖5)。秘密共享也在trustlet中計(jì)算:在下面,研究的機(jī)制在安全OS中實(shí)現(xiàn)。
圖5:Zion-體系結(jié)構(gòu)概述
?
Shamir’s Secret Sharing
?
此問題可以通過以下方法解決:
- 安全地存儲(chǔ)多項(xiàng)式系數(shù),以便以后可以恢復(fù)它們以生成其他份額,
- 或僅在拆分前保持PRNG狀態(tài)。
HTC使用的SSS實(shí)現(xiàn)受一個(gè)開源項(xiàng)目的啟發(fā),可在此處獲得。此開源實(shí)現(xiàn)一次生成所有共享。一個(gè)人不能要求一個(gè)份額。為了允許隨意添加受信任的聯(lián)系人,HTC修改了實(shí)現(xiàn),但犧牲了安全性。
HTC選擇保留PRNG種子。但是該實(shí)現(xiàn)還使用了DRBG:這可確保輸出是可預(yù)測的,并且生成的系數(shù)將始終相同。DRBG使用的種子(即PRNG狀態(tài))存儲(chǔ)在加密分區(qū)內(nèi),僅可用于安全OS。
隨機(jī)數(shù)生成器:
原始實(shí)現(xiàn)的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僅返回隨機(jī)緩沖區(qū)的內(nèi)容。此128字節(jié)的緩沖區(qū)由函數(shù)手動(dòng)更新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;} }我們可以看到,作為輸入?yún)?shù)傳遞給此函數(shù)的熵完全確定了PRNG的內(nèi)部狀態(tài),因此也確定了PRNG的輸出。正如我們之前所解釋的,此行為是HTC想要的。該熵來自智能手機(jī)TRNG,其值由返回qsee_prng_getdata。使用128位熵并將其存儲(chǔ)在加密分區(qū)中。
知道PRNG的輸出足以完全確定整個(gè)隨機(jī)輸出序列。例如,如果我們知道返回的前32個(gè)字節(jié),那么我們知道接下來的字節(jié)將對應(yīng)于這些字節(jié)的SHA-256,然后對應(yīng)于該值的SHA-256,依此類推……此外,PRNG的周期非常短128個(gè)字節(jié)。
但是,PRNG缺乏魯棒性對我們的攻擊無濟(jì)于事:將使用PRNG的狀態(tài)在兩次調(diào)用之間固定的事實(shí)。如果兩次之間的未調(diào)用,sss_rand則兩次調(diào)用將始終返回相同的值sss_update_secure_random_buffer。
HTC Social Key Recovery Shares計(jì)算
共享秘密是錢包的種子,用于導(dǎo)出每種加密貨幣的所有密鑰。但是該實(shí)現(xiàn)增加了一個(gè)加密層來保護(hù)秘密。選擇的密碼是基于Salsa20和Poly1305(與TweetNaCl相同)的經(jīng)過身份驗(yàn)證的流密碼。
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重建機(jī)密所需的份額數(shù)(而不是33)。除了五分之三的閾值不再有效這一事實(shí)外,我們?nèi)匀徽J(rèn)為安全威脅是不可忽略的。理想情況下,用戶應(yīng)將種子分成5個(gè)5彼此不認(rèn)識(shí)的可信任聯(lián)系人。實(shí)際上,使用55?受信任的聯(lián)系人,即使其中一些彼此認(rèn)識(shí)。
借助這種攻擊,惡意聯(lián)系人只需說服(或折衷)其他信任的聯(lián)系人即可完全收回種子并訪問資金。
打破機(jī)制
受先前攻擊影響的固件如下(使用了歐洲ID):
- 固件1.47.2401.2,它似乎是初始固件;
- 固件1.53.2401.2,于2019-12-18。
2019年2月19日,發(fā)布了第三個(gè)固件。
通過研究這一點(diǎn),我們非常驚訝地注意到sss_update_secure_random_bufferPRNG初始化函數(shù)從未被調(diào)用過。PRNG始終返回相同的值:其熵緩沖區(qū),以固定值初始化(可能通過測試向量驗(yàn)證)。我們認(rèn)為,trustlet已使用測試選項(xiàng)進(jìn)行編譯,而該選項(xiàng)應(yīng)永遠(yuǎn)不會(huì)在生產(chǎn)中使用。結(jié)果,用于加密種子的密鑰是固定的。由于此密鑰已發(fā)送給每個(gè)聯(lián)系人,因此任何人都可以解密種子并訪問資金。
<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>結(jié)論
負(fù)責(zé)任的披露
我們于2019.02.15向HTC Exodus披露了所有上述缺陷。
兩個(gè)月后,還披露了其他漏洞(觸摸屏驅(qū)動(dòng)程序內(nèi)部,受信任的UI內(nèi)部以及ETH / BTC事務(wù)解析中的內(nèi)存損壞)。HTC安全團(tuán)隊(duì)已經(jīng)找到并修復(fù)了它們。
2019年3月5日,HTC Exodus團(tuán)隊(duì)在巴黎并借此機(jī)會(huì)訪問了我們。他們甚至有機(jī)會(huì)進(jìn)入Donjon。
HTC?在2019.03.25發(fā)行了新固件(1.62.2401.7)解決了所有這些問題。SSS修補(bǔ)程序包括使用可靠的PRNG,并將每個(gè)生成的共享保存在安全存儲(chǔ)中。每當(dāng)添加新的受信任聯(lián)系人時(shí),都會(huì)使用這些共享。
HTC Exodus于2019.04.05開始為Zion Hardware Wallet設(shè)立賞金計(jì)劃。
在這些討論之后,HTC向我們表明,此漏洞的披露觸發(fā)了他們自己賞金計(jì)劃的創(chuàng)建。當(dāng)我們在建立賞金計(jì)劃之前報(bào)告了這些錯(cuò)誤時(shí),我們沒有得到任何賞金,但是當(dāng)他們訪問我們時(shí),我們得到了出埃及記襯衫和貼紙。:) 非常感謝!
帶走
我們研究了HTC Exodus 1手機(jī)的硬件錢包,并發(fā)現(xiàn)了社交密鑰恢復(fù)機(jī)制上的兩個(gè)關(guān)鍵漏洞。在攻擊者能夠在任何Zion信任聯(lián)系人的Android手機(jī)上執(zhí)行代碼(Android漏洞,常規(guī)Android應(yīng)用)的情況下,他可能會(huì)竊取相應(yīng)EXODUS 1所有者的資金。或者,受信任的聯(lián)系人可以直接訪問種子。這些漏洞已得到正確修補(bǔ)。
不過,我們強(qiáng)烈鼓勵(lì)所有使用社交密鑰恢復(fù)來更改種子(并轉(zhuǎn)移其資金)的EXODUS 1用戶。確實(shí),他們的種子可能早些受到破壞,或者仍然可以通過不會(huì)更新Zion的受信任聯(lián)系人而受到破壞。
?
?
總結(jié)
以上是生活随笔為你收集整理的【译】 Stealing the funds of all HTC EXODUS 1 users (HTC 区块链钱包安全漏洞分析)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML常用标签、特殊字符、路径
- 下一篇: 深度优化LNMP之MySQL