以太坊鏈審計報告之Clef審計報告
近期,以太坊go-ethereum
公開了兩份審計報告,玄貓安全團隊第一時間對其進行了翻譯工作。此為第二篇《Ethereum Clef Review》即2018-09-14_Clef-audit_NCC
,此審計報告完成時間為2018年9月14日。
如果您正在使用的是較舊版本的go-ethereum
,強烈建議升級至最新版本,以免遭受不必要的損失。
1.1. 概述
在2018年9月初,以太坊基金會委託NCC Group
對Clef命令列介面進行程式碼審計。程式碼位於https://github.com/holiman/go-ethereum/tree/70cfedc9d7bd64f1f112eb2099a5c36266863f40/cmd/clef
。以下為審計詳情。
標題 | ID | 風險 |
---|---|---|
Clef備份加密不完全 | 002 | 中危 |
缺少密碼強度檢查 | 005 | 中危 |
交易資料欄位驗證失敗 | 007 | 中危 |
由不正確的方法Selector導致的拒絕服務 | 010 | 中危 |
secrets.dat許可權不當 | 001 | 低危 |
鍵值對加密儲存的加密值可交換 | 003 | 低危 |
暴露的Clef API 缺少指引 | 004 | 低危 |
ECRecover不會對恢復的公鑰進行身份驗證 | 009 | 低危 |
過時的依賴關係 | 011 | 低危 |
規則依賴於時間和狀態存在危險性 | 012 | 低危 |
通過格式錯誤的匯入金鑰拒絕服務 | 013 | 低危 |
加密金鑰庫完整性檢查不完整 | 014 | 低危 |
UI混合了無關和特定允許的資料 | 006 | 建議 |
1.2. Clef備份加密不完全
1.2.1. 風險: 中危
影響性:高,可利用性: 低
1.2.2. 標識
NCC-EF-Clef-002
1.2.3. 分類
認證
1.2.4. 位置
cmd/clef/main.go:initializeSecrets()
1.2.5. 影響
一個能夠入侵使用者裝置的攻擊者可以任意訪問Clef的加密備份
1.2.6. 描述
Clef
在硬碟中儲存了大量檔案,如包含賬戶密碼的credentials.json
,包含JavaScript
規則檔案雜湊的config.json
等檔案。通過這些檔案可以恢復私鑰。這些檔案均由一個隨機數種子派生的金鑰來加密,且這個隨機數種子是明文儲存在硬盤裡的secrets.dat
檔案中。
一個能夠訪問secrets.dat
和credentials.json
的攻擊者可以任意訪問賬戶及其資產。因此,一個沒有硬碟加密保護的裝置如果被物理入侵,將會洩露所有儲存在Clef
加密備份中的資訊。當執行中的裝置被遠端控制時,將會使威脅到休眠的Clef應用,無論此時是否進行了硬碟加密。此外,將這些檔案備份或拷貝到另一個位置也會使危及使用者的賬號安全。
1.2.7. 修復建議
強制使用密碼來啟動Clef命令列介面。並將此機制用在go-ethereum/accounts/keystore
來保護secret.dat
檔案。
1.3. 缺少密碼強度檢查
1.3.1. 風險: 中危
影響性:中,可利用性:低
1.3.2. 標識
NCC-EF-Clef-005
1.3.3. 分類
認證
1.3.4. 位置
signer/core/api.go:New()
1.3.5. 影響
一個攻擊者能夠猜解不安全的使用者密碼,或者對使用者弱密碼進行爆破。這會導致攻擊者獲取使用者以太坊賬戶的私鑰。
1.3.6. 描述
Clef CLI
能夠被用於建立和管理以太坊外部擁有的賬號。賬戶的建立過程可以通過傳送下面的RPC請求給Clef來實現。(如果執行時加上–rpc選項)
curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0", \ "method":"account_new","params":["test"],"id":67}' localhost:8550
執行Clef
的使用者將會被要求輸入用於保護賬戶私鑰的密碼。在這時,使用者能夠輸入一個任意長度的密碼(空密碼也將會被接受)。對於可以物理入侵或者遠端入侵的攻擊者來說,他們將更容易地恢復使用者私鑰。
1.3.7. 修復建議
強制規定最小密碼長度。NIST
組織已經出版了相關主題的文件
,推薦設定最小8個字元長度的密碼。除此之外,檢查已知的不符合規範的密碼。關於不符合規範的密碼參考NIST Bad passwords
1.3.8. 客戶反饋
Clef現在已經強制使用最小10位的密碼:github.com/holiman/go-ethere um/commit/193f7049719a2da9018027853d0c2237cdad602b
1.3.9. 參考資料
https://pages.nist.gov/800-63-3/
NIST Bad Passwords:https://cry.github.io/nbp/
1.4. 交易資料欄位驗證不當
1.4.1. 風險: 中危
影響性:中,可利用性:低
1.4.2. 標識
NCC-EF-Clef-007
1.4.3. 分類
資料驗證
1.4.4. 位置
signer/core/{abihelper,validation}.go
1.4.5. 影響
惡意構造的資料欄位能夠允許攻擊者欺騙簽名者的目的
1.4.6. 描述
當接收交易簽名的請求時,在將請求傳遞給使用者之前,Clef
會先進行一些驗證檢查。如果一個特殊的引數被傳遞給一個請求(方法的簽名),程式會試圖匹配資料欄位。資料欄位必須由4個位元組的標誌和32倍數的位元組組成,且該4個位元組的標誌用於函式呼叫(方法簽名的雜湊值會被截斷成4個位元組):
func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {if len(calldata) < 4 {return nil, fmt.Errorf("Invalid ABI-data, incomplete method signature of (%d bytes)", \len(calldata)) } sigdata, argdata := calldata[:4], calldata[4:] // 進行截斷if len(argdata)%32 != 0 { // 32的倍數return nil, fmt.Errorf("Not ABI-encoded data; length should be a multiple of 32 (was %d)", \len(argdata)) }
如果在請求中,沒有方法簽名作為引數被傳遞給Clef,這裡的檢查就不會進行。這是因為方法簽名不是以太坊虛擬機器的特性,它是Solidity-specfic
特性。如果檢查失敗,Clef
會中止傳遞請求,並且發出警告:
info, err = testSelector(*methodSelector, data)if err != nil { msgs.warn(fmt.Sprintf("Tx contains data, but provided ABI signature could not be matched: %v", err)) }
由於Clef CLI
的使用者不會總是傳遞一個方法簽名,或者不能理解關於ABI
簽名檢查相關的警告,Clef
的行為可能使使用者快速關閉警告(這被稱為警告疲勞),由於這個原因,惡意的DAPP可以通過短地址攻擊
或者構造畸形的calldata資料來實施攻擊。
1.4.7. 修復建議
當一個方法簽名被傳遞,資料欄位格式應該總是指定長度為4+k×32
,其中k≥0
。如果不是方法簽名被傳遞,Clef
不應該把請求傳遞給使用者。當一個方法簽名不被傳遞且資料欄位不為空時,它的格式也應該根據之前討論的編碼來進行檢查。如果驗證失敗,Clef
應該拒絕該交易(用於簡化驗證過程或列入白名單的合約地址不在此列)。如果非標準的交易需要預設支援,使用者應該收到警告,提示該交易不是標準格式。
1.4.8. 客戶反饋
現在驗證過程中,當拒絕交易時,預設返回警告資訊,且增加一個特殊的模式用來繞過這個行為:github.com/holiman/go-ethereum/commit/193f7049719a2da9018027853d0c2237cdad602b
1.4.9. 參考資料
1.5. 由不正確的方法Selector導致的拒絕服務
1.5.1. 風險: 中危
影響性:低,可利用性:低
1.5.2. 標識
NCC-EF-Clef-010
1.5.3. 分類
資料驗證
1.5.4. 位置
signer/core/abihelper.go:parseCallData()
accounts/abi/abi.go:JSON()
1.5.5. 影響
一個可以訪問Clef API
的攻擊者能夠使應用崩潰
1.5.6. 描述
在一些用例中,Clef持續地執行,並且根據使用者編寫的規則來接收請求。在一些場景中,應用崩潰會使得在應用重啟之前,合法的交易不被處理。
account_signTransaction
API處理簽名請求的交易。為了提供有用的資訊給使用者,發起請求的終端能夠提供被呼叫的函式方法的簽名(防止交易導致合約執行)。如果方法簽名是畸形的,Clef將會崩潰。下面這個正則匹配用於驗證使用者的輸入:
// MethodSelectorToAbi converts a method selector into// an ABI struct. The returned data is a valid json string// which can be consumed by the standard abi package.func MethodSelectorToAbi(selector string) ([]byte, error) { re := regexp.MustCompile(`^( [^\)] +) \( ([a-z0-9,\[\]] *)\)`) groups := re.FindStringSubmatch(selector)
該正則表示式期望方法簽名為如下格式:
functionName(uint256, string, address)
使用黑名單而不是白名單過於自由。這樣的過度接受策略將會使得使用者可以輸入如下內容:
函式名可以是除\
和)
的任意字元
引數可以是字母數字的或包含[
與]
的字串,但是不需要強制是語法上的正確方括號
引數列表能夠以,
結束和開始
函式簽名的結尾可以包含任何字元
這意味著根據當前的檢查規則,下面的函式簽名是有效的:
call(a,a],bbbb932[,) #@#((@$!(uint256) anything
1.5.7. 復現步驟
在終端執行下面的命令,呼叫本地RPC介面localhost:8550
,並且能夠觀察到Clef
程式崩潰。
curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0", \ "method":"account_signTransaction","params":[ \ {"from":"0x82A2A876D39022B3019932D30Cd9c97ad5616813", \ "gas":"0x333","gasPrice":"0x123","nonce":"0x0", \ "to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", \ "value":"0x10", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"}, "func(uint256,uint256,[]uint256)"],"id":67}' http://localhost:8550/
以下的方法簽名均會使應用崩潰:
func(uint256,uint256,[]uint256) func(uint256,uint256,uint256,) func(,uint256,uint256,uint256)
1.5.8. 修復建議
為了解決這個問題:
研究abi
的JSON
解碼器並且找到錯誤的根源。
在進行操作之前,進一步驗證接收到的方法簽名
1.5.9. 客戶反饋
引入一個PR來修復這個bug:github.com/ethereum/go-ethereum/pull/17653
1.6. secrets.dat許可權不當
1.6.1. 風險: 低危
影響性:高,可利用性:低
1.6.2. 標識
NCC-EF-Clef-001
1.6.3. 分類
配置不當
1.6.4. 位置
許可權設定initializeSecrets(),cmd/clef/main.go
第228行
許可權檢查checkFile()
,cmd/clef/main.go
第550行
1.6.5. 影響
master
種子可能被刪除或者覆蓋,導致不能訪問賬戶密碼和JavaScript
的規則檔案雜湊
1.6.6. 描述
secrets.dat
檔案包含了master
種子,在儲存和查詢賬戶密碼和JavaScript
規則檔案雜湊值的時候需要用到這個種子。在實際中,這個檔案只寫一次,包含了重要的根密碼,需要得到最大限度的保護。
Master
種子生成和儲存是initializeSecrets()
的主要目的,該函式位於cmd/clef/main.go
中。在程式碼228行,當權限設定為700時,可以進行寫入硬碟的操作。許可權700對應著擁有者的所有許可權——讀,寫,執行。這樣做的結果是,擁有者能夠輕易地刪除或者覆蓋這個檔案,從而導致不能訪問儲存的內容。原則上,這個擁有者還能夠進行執行操作。
位於cmd/clef/main.go
的checkFile()
函式的主要目的是檢查檔案secrets.dat
的許可權。在程式碼550行,檔案許可權是讀。將許可權模式與077進行與運算,並且檢查結果是否為0——任何非0結果將會報錯。這與上面描述的initializeSecrets()
確認儲存許可權設定是一致的。
對於secrets.dat
,寫許可權和執行許可權不應該被設定。對於secrets.dat
檔案的處理可以類比處理SSH keys
的方法
。
分開來看,賬戶密碼儲存在credentials.json
中,JavaScript
規則檔案雜湊儲存在config.json
中。通過位於signer/storageaes_gcm_storage.go
的writeEncryptedStorage
函式,將它們的檔案許可權設定為600。這被認為合適的,這是因為讀/寫的本質,鍵值對的儲存,實際上內容應該總是由root secret
來加密。
1.6.7. 修復建議
在initializeSecrets()
中,secrets.dat
的檔案許可權應該被設定為400(而不是700)。為了保持一致性,在checkFile()
中,secrets.dat
的檔案許可權應該是和377(而不是077)進行與運算。
1.6.8. 參考資料
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html#troublesho ot-unprotected-key
1.7. 鍵值對加密儲存的加密值可交換
1.7.1. 風險: 低危
影響性:低,可利用性:低
1.7.2. 標識
NCC-EF-Clef-003
1.7.3. 分類
加密
1.7.4. 位置
signer/storage/aes_gcm_storage.go
1.7.5. 影響
一個能夠加密備份檔案的攻擊者能夠交換使用者的keystore
的密文。這將會導致弱攻擊(比如確認不同的私鑰是否被同一個密碼保護),或者其他未知的依賴於Clef規則的複雜攻擊
1.7.6. 描述
Clef命令列介面以加密的形式儲存這下面的資料,目的是為了加快應用重啟後的恢復速度:
keystores
的密碼(用於規則引擎)
javascript
規則的儲存
規則檔案的雜湊
儲存和加密是通過一個鍵值對儲存的,只有值是通過AES-GCM
來進行加密:
// Put stores a value by key. 0-length keys results in no-opfunc (s *AESEncryptedStorage) Put(key, value string) {// ... ciphertext, iv, err := encrypt(s.key, []byte(value))// ... encrypted := storedCredential{Iv: iv, CipherText: ciphertext} data[key] = encrypted// ...}
鍵值對接下來被編碼成JSON
格式,並且儲存在硬碟中,示例如下:
{"key1": {"iv": "IQZYrnH0YjbcLmBD","c": "oP2S7Li+YYPt2vQcfDgUlc/QaIk=" },"key2": {"iv": "OVilp+zm+OvgH7Vm","c": "DP7kmTyJR89nTMb1mfRPokIYRpg=" } }
一個擁有恰當許可權訪問這些檔案的攻擊者能夠篡改內容,交換key1
和key2
的內容,這樣會使得讀取key1
值的時候,獲取到key2
的值
1.7.7. 修復建議
匯入在Seal()
和Open()
函式的additionalData
欄位,主要部分鍵值對。詳情檢視ciper package
1.7.8. 客戶反饋
程式碼中添加了鍵值對的主要部分作為AES-GCM
額外的資料:https://github.com/holiman/go-ethereum/commit/913f77ca8c5c08749b9d668adeb1ab02bbc30663
1.7.9. 參考資料
https://golang.org/pkg/crypto/cipher/
1.8. 暴露的 Clef API 缺乏指引
1.8.1. 風險:低危
影響性:低,可利用性:不確定
1.8.2. 標識
NCC-EF-Clef-004
1.8.3. 分類
拒絕服務
1.8.4. 位置
cmd/clef/main.go
1.8.5. 影響
有權訪問Clef API
的攻擊者不斷髮送大量垃圾請求到介面上使其失效,導致使用者強制重新啟動應用程式才能處理合法請求。
1.8.6. 描述
有權訪問 Clef 的公共 API 的攻擊者(例如通過暴露在網際網路的RPC介面)可以通過快速傳送垃圾請求,導致產生大量需要使用者按順序手動處理程序。
如果執行此類攻擊,終端使用者將無法繼續正常操作,除非重啟程式。
此外,通過以太坊的RPC協議完成的請求未加密。雖然大多數API請求和響應最終可能都會發布在以太坊網路上,但“account_sign”方法(旨在為不同目的簽署任意資料)還是應該被保密。
1.8.7. 復現步驟
使用 Clef 程式執行下面的bash
指令碼,將 RPC 介面暴露在 localhost:8550
,然後可以觀察到Clef 使用者需要一個一個地接收請求。
for i in {1..100}do curl --no-buffer -H "Content-Type: application/json" -X POST --data \'{"jsonrpc":"2.0","method":"account_new","params":["test"],"id":67}' localhost:8550 &donekill $(jobs -p)
1.8.8. 修復建議
對連線進行加密(通過TLS)並向Clef API驗證客戶端。或者,將這些任務委派給較低層協議或前端代理,或者新增文件用於警告使用者不要將Clef的API暴露。
1.9. ECRecover不會對恢復的公鑰進行身份驗證
1.9.1. 風險:低危
影響性:不確定,可利用性:不確定
1.9.2. 標識
NCC-EF-Clef-009
1.9.3. 分類
加密
1.9.4. 位置
signer/core/api.go
1.9.5. 影響
根據此請求的使用情況,簽名可能會被篡改從而恢復錯誤的公鑰。
1.9.6. 描述
Clef API
公開了一種EcRecover
方法,該方法允許從簽名訊息中恢復以太坊公鑰。該方法實現了橢圓曲線密碼學的高效密碼組標準文件中的演算法4.1.6(公鑰恢復操作)。
如演算法規範所述,可以從簽名中恢復幾個公鑰。
這是由於ECDSA
簽名演算法從簽名的r
值中刪除了一些資訊:只保留了x座標(對於y座標可以恢復2個解)並且它以橢圓曲線的順序進一步減小。 而以太坊使用了 secp256k1
,其曲線順序略低於場模量,因此確實丟失了資訊。曲線使用輔助因子1,則演算法的可能解決方案的數量是2×(1 + 1)= 4。
為了使恢復演算法恢復正確的結果,在每個以太坊簽名的末尾都新增一個v位元組。其最低有效位包含r值的y座標的符號,其餘位包含用於重新計算r值的x座標的資訊。
由於這些位可能被篡改,攻擊者在某些情況下可能會通過匯入錯誤的公鑰來欺騙演算法。
1.9.7. 修復建議
為了驗證恢復的金鑰,Clef需要:
驗證金鑰是否可用於驗證請求中傳遞的簽名。 這是SEC演算法的步驟1.6.2,Clef沒有實現。
將恢復的公鑰與以太坊地址或其他身份驗證機制進行匹配。
為了防止這些攻擊,需要更改Clef的API以接受額外的“身份驗證”引數。
1.9.8. 客戶反饋
ECRecover 方法已經從Clef API 移除:github.com/holiman/go-ethereum/commit/cf3bf1724e58cc85ec87cb39a0aee0cb246c472e
SEC 1: Elliptic Curve Cryptography version 2.0
1.10. 過時的依賴關係
1.10.1. 風險:低危
影響性:不確定,可利用性:不確定
1.10.2. 標識
NCC-EF-Clef-011
1.10.3. 分類
修補
1.10.4. 位置
signer/rules/deps/bignumber.js found at
https://github.com/holiman/go-ethereum/blob/clefchanges_2/signer/rules/deps
https://github.com/ethereum/go-ethereum/blob/master/signer/rules/deps
vendor/vendor.json found at
https://github.com/holiman/go-ethereum/blob/clefchanges_2/vendor
https://github.com/ethereum/go-ethereum/blob/master/vendor
Impact Outdated dependencies may expose the application to publicly discovered vu
1.10.5. 影響
過時的依賴項可能會將應用程式暴露給公開發現的漏洞。
1.10.6. 描述
迄今為止,許多最大的漏洞都依賴於利用過時元件中的已知漏洞。Clef
和Go-ethereum
程式碼庫從許多過時的元件中提取,儘管目前沒有眾所周知的漏洞。風險與元件功能和資料敏感性,開發活動和質量,流行度以及專案依賴性更新之間的時間長度成正比。由於此問題普遍存在,OWASP專案在《十大最關鍵Web應用程式安全風險》中列出了此風險。
signer/rules/rules.go
程式碼利用 signer/rules/deps/bindata.go
實質上載入bignumber.js
庫,用於任意精度的十進位制和非十進位制算術。 該庫的原始碼是signer/rules/deps/bignumber.js
,版本為2.0.3。 此專案的更改日誌表示此版本於2015年2月釋出,而最新版本為7.2.1。NCCGroup 不知道此庫中存在任何公開已知的漏洞。
vendor/vendor.json
檔案列出了大約154個Golang依賴項,其修訂時間戳從2015年初到2018年8月。其中大部分已過期且可以更新。 例如,來自https://github.com/huin/goupnp
的Go儲存庫的UPnP客戶端庫的七個元件,其提交雜湊值為679507af18f3c7ba2bcc7905392ce23e148661c3
,於2016年12月提交,即11個提交已過期。
1.10.7. 修復建議
將專案依賴項更新為建議用於生產部署的最新且穩定的版本。作為開發過程的一部分,包括定期審查依賴性更新情況。
1.10.8. 參考資料
https://www.owasp.org/images/7/72/OWASP_Top_10-2017_%28en%29.pdf.pdf
https://github.com/MikeMcl/bignumber.js/blob/master/CHANGELOG.md
1.11. 規則依賴於時間和狀態存在危險性
1.11.1. 風險:低危
影響性:中,可利用性:低
1.11.2. 標識
NCC-EF-Clef-012
1.11.3. 分類
配置
1.11.4. 位置
cmd/clef/rules.md
1.11.5. 影響
存在改變Clef
狀態和時間訪問的攻擊。如果成功安裝,它們將允許攻擊者恢復Clef
規則使用的狀態或改變Clef
所看到和使用的時間。這最終可能允許有權訪問Clef
介面的攻擊者移除規則上的某些限制。
var windowstart = new Date().getTime() - window;
攻擊者存在不同的方式來影響裝置執行時間而不是系統上的root使用者:
如果在日期程式中設定了CAP_SYS_TIME
功能,則任何使用者都可以更改時間。
如果攻擊者在網路中具有特權中間位置,她可以攻擊NTP協議以改變裝置的時間。
此外,為了在執行規則之間保持狀態,Clef保留加密的鍵值儲存(jsStorage)。特定攻擊可能允許攻擊者改變此狀態並刪除一些限制(例如,如果布林值設定為阻止進一步的交易事務,則恢復狀態將允許交易事務再次流動):
如果攻擊者具有對計算機的物理訪問許可權,則可以將其重新設定為以前的快照。
如果攻擊者擁有jsStorage
的檔案許可權,她可以記錄更改並將檔案還原到以前的某個時間點。
這些攻擊可能允許攻擊者阻止某些規則正常工作,或者更糟糕的是,攻擊者直接訪問Clef的API,讓錢包中的金錢流失。
1.11.6. 修復建議
這一發現強調了執行Clef的系統的安全性至關重要。應根據涉及的程度,為不同型別的使用者提供不同的建議。可以編寫不同的威脅模型,記錄Clef防範和不防範的內容。最終,很難防禦來自強大對手的這些型別的高度針對性的攻擊,它們應該超出Clef的威脅模型。
1.11.7. 參考資料
cmd/clef/rules.md
http://man7.org/linux/man-pages/man7/capabilities.7.html
https://www.cs.bu.edu/~goldbe/NTPattack.html
1.12. 通過格式錯誤的匯入金鑰拒絕服務
1.12.1. 風險:低危
影響性:中,可利用性:低
1.12.2. 標識
NCC-EF-Clef-013
1.12.3. 分類
資料驗證
1.12.4. 位置
accounts/keystore/keystore_passphrase.go
1.12.5. 影響
一個可以訪問API或擁有特權中間人位置的攻擊者,可能會製造惡意匯入請求或篡改它們,以便在不提醒使用者的情況下使應用程式崩潰或更改匯入的金鑰。
1.12.6. 描述
Clef
的API公開了一種“匯入”方法,允許請求匯入已有的帳戶。此匯入方法接受一個加密金鑰作為引數,必須以特定格式格式化。Clef
接受兩種不同的加密方法格式:版本1和版本3。處理金鑰匯入的大多數程式碼都假定請求傳遞的引數是可信的,這可能是因為在實踐中,無法編寫規則來處理此方法——使用者必須手動接受匯入請求。以下程式碼路徑都存在問題:
1)匯入私鑰。
匯入流程最終呼叫crypto.ToECDSAUnsafe()
方法,如所示,“如果盲目地將二進位制blob轉換為私鑰。它們幾乎不會被使用,除非您確定輸入的有效性並且避免由於錯誤的原編碼而導致錯誤(0字首會被截斷)”。
2)JSON解析。
JSON物件中的幾個欄位,在沒有事先檢查它們是否存在的情況下進行恢復操作。用於恢復KDF引數的getKDFKey()
函式不會將空內容對映視為cryptoJSON.KDFParams
,如果給定一個,則會崩潰。此外,一般以整數作為KDF物件的欄位,但即使給定字串,它也沒有進行判斷。
3)KDF引數。
可以通過向金鑰匯出函式提供極大的引數導致拒絕服務,這將迫使程式計算無法進行的加密操作。
4)經過身份驗證的加密。
在嘗試對匯入的金鑰進行解密之前,金鑰庫將驗證密文的完整性,以便檢測來自中間攻擊者的任何篡改。此完整性檢查不包括IV,並且不會在恆定時間內完成。這可能允許攻擊者篡改IV,使得使用者解密錯誤的私鑰,並且沒有Clef給出的任何警報(即使恢復的“地址”不同於在請求中作為引數傳遞的“地址”欄位)。
5)解密。
匯入器的版本1將使用AES-CBC
來解密接收到的金鑰,特別是低階CryptBlocks
函式,將多個blocksize
作為引數。否則,該功能將會出現panic
報錯。
1.12.7. 復現步驟
將 Clef 程式的 RPC 介面暴露在localhost:8550
,然後在命令列視窗執行下面的命令,可以觀察到 Clef 程式奔潰。
curl -i -H "Content-Type: application/json" -X POST \ --data '{"jsonrpc":"2.0","method":"account_import", \ "params":[{"version":"1","address":"string", \ "id":"string","crypto":{"cipher":"","ciphertext":"", \ "cipherparams":{"iv":""},"kdf":"", \ "kdfparams":{},"mac":""}}],"id":67}' http://localhost:8550/
下面的 payloads 也能夠導致程式奔潰。
{"version":"1","address":"string","id":"string","crypto": \ {"cipher":"","ciphertext":"","cipherparams":{"iv":""},"kdf":"", \"kdfparams":{"salt":"","dklen":"","n":"","r":"","p":"","c":"", \"prf":""},"mac":""}} {"version":"1","address":"string","id":"string","crypto": \ {"cipher":"","ciphertext":"01","cipherparams":{"iv":""}, \"kdf":"pbkdf2","kdfparams": \ {"salt":"","dklen":5,"n":5,"r":5,"p":5,"c":5, \"prf":"hmac-sha256"}, \"mac":"32f2f344a0bdf0434df8d3c3fd2afd043c1a26b969bb7c448abd67a4af27ae03"}}
1.12.8. 修復建議
在文件中詳細說明匯入API必須只接收可信任的和通過驗證的輸入。 此外,還要解決這一發現中強調的問題。
此外,請考慮從Clef的API中刪除Import方法。
1.13. 加密的金鑰庫完整性檢查不完整
1.13.1. 風險:低危
影響性:低,可利用性:低
1.13.2. 標識
NCC-EF-Clef-014
1.13.3. 分類
金鑰儲存
1.13.4. 位置
accounts/keystore/keystore_passphrase.go
1.13.5. 影響
攻擊者可以篡改錢包備份,而不會提醒使用者,在嘗試使用錢包金鑰之前,使用者不會意識到攻擊。
1.13.6. 描述
Go-Ethereum
的金鑰庫包具有匯出的EncryptKey()
方法,能夠以加密形式儲存錢包。此加密使用從使用者已知的密碼短語派生的金鑰。作為完整性檢查的一種方法,為了確保加密金鑰的備份沒有被篡改,金鑰庫通過密文計算訊息認證碼(MAC),如下所示:
// EncryptKey encrypts a key using the specified scrypt parameters into a json// blob that can be decrypted later on.func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {// ... derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptR, scryptP, scryptDKLen)// ... iv := make([]byte, aes.BlockSize) // 16if _, err := io.ReadFull(rand.Reader, iv); err != nil {panic("reading from crypto/rand failed: " + err.Error()) } cipherText, err := aesCTRXOR(encryptKey, keyBytes, iv)// ... mac := crypto.Keccak256(derivedKey[16:32], cipherText)
此完整性檢查不包括加密/解密過程的重要部分,允許攻擊者在不必修改密文的情況下篡改它。由於加密的內容具有高熵,因此不能執行強攻擊。
1.13.7. 修復建議
使用經過身份驗證的密碼,如AES-GCM
,它將加密與完整性檢查編譯為單個演算法。
1.14. UI混合了無關和特定允許的資料
1.14.1. 風險:建議
影響性:不確定,可利用性:不確定
1.14.2. 標識
NCC-EF-Clef-006
1.14.3. 分類
資料有效性
1.14.4. 位置
signer/core/cliui.go
1.14.5. 影響
攻擊者可以通過在 Clef UI 中顯示攻擊者控制的資訊來對使用者進行網路攻擊。
1.14.6. 描述
當Clef
通過其公開的API接收請求時,元資料將顯示給負責處理它的使用者。此元資料包括的各種欄位均與IP地址,使用者代理,來源等簽名內容無關。在signer/core/cliui.go
中有6個通過呼叫showMetadata()
來呼叫此功能。其中一些欄位可能會被輕微篡改,並可能提供錯誤的理解,因為使用者可能過分依賴它們而不是重要的欄位。
Clef將接受以下“惡意”請求(使用Go程式碼示例註釋編造的JSON)。
curl http://localhost:8550/ \ -i -H "Content-Type: application/json" \ -X POST --data '{...}' \ -A "indicates INVALID CHECKSUM IS EXPECTED" \ -H "Origin: NCC Group requires IMMEDIATE APPROVAL per direction of J Smith"
Clef 將向用戶顯示以下資訊
--------- Transaction request------------- to: 0x07a565b7ed7d7a678680a4c162885bedbb695fe0 WARNING: Invalid checksum on to-address! from: 0x82A2A876D39022B3019932D30Cd9c97ad5616813 [chksum ok] value: 16 wei gas: 0x333 (819) gasprice: 291 wei nonce: 0x0 (0) data: 0x4401a6e40000000000000000000000000000000000000000000000000000...012 Transaction validation: * WARNING : Invalid checksum on to-address * Info : safeSend(address: 0x0000000000000000000000000000000000000012) Request context: 127.0.0.1:40802 -> HTTP/1.1 -> localhost:8550 User-Agent: indicates INVALID CHECKSUM IS EXPECTED Origin: NCC Group requires IMMEDIATE APPROVAL per direction of J Smith ------------------------------------------- Approve? [y/N]: >
如目前所示,元資料對合法請求幾乎沒有好處,卻可能促進非法請求。天真的使用者可能會將無關的請求資料視為取代上述真實警告並錯誤地批准此交易。
1.14.7. 復現步驟
如果沒有明確的描述和警告,請不要在特定於審批的資料旁邊顯示請求元資料。 要麼明確標記所顯示的類別,並警告不能依賴請求資料,要麼只刪除所有請求資料。
1.14.8. 修復建議
如果沒有明確的描述和警告,請不要在特定允許的資料旁邊顯示請求元資料。要麼明確標記所顯示的類別,並警告不能依賴請求資料,要麼只刪除所有請求資料。
1.14.9. 客戶反饋
在顯示由API的外部呼叫者提供的元資料之前添加了另一條訊息:github.com/holiman/go-ethereum/commit/c6d7644e5a5bd0fe23c7f060a390112115515cab
1.4. 附錄
1.4.1. 宣告
我們努力提供準確的翻譯,可能有些部分不太準確,部分內容不太重要並沒有進行翻譯,如有需要請參見原文。
1.4.2. 原文地址
https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf
*參考來源:GitHub ,由Javierlev & Tri0nes編譯,轉載請註明來自FreeBuf.COM