Back to Blog

Poly Network Saldırısının Daha Ayrıntılı Analizi

Code Auditing
August 12, 2021
5 min read

Saldırı iki ana adımdan oluşmaktadır. Birinci adım, koruyucuyu (keeper) değiştirmektir; ikinci adım ise token'ları çekmektir (unlock fonksiyonunu çalıştırmak). İkinci adım tam olarak analiz edilmiştir. Birinci adım için Kevin, hash çarpışmasının saldırgan tarafından putCurEpochConPubKeyBytes fonksiyonunu çağırmak için kullanılan akıllıca bir numara olduğuna dikkat çekmiştir. Ancak saldırganın bu çağrıyı yapmak için başlangıçta nasıl geçerli bir işlem elde edebildiği hâlâ bilinmemektedir.

Bu blogda, tüm süreci açıklamak için Ontology'den gelen kötü amaçlı işlemi (0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c) kullanacağız.

Özetle şunları bulduk:

  • Ontology rölesinin (relayer), Ontology zincirinden gelen işlemler için yeterli doğrulama mekanizmaları yoktur.
  • Saldırgan, Poly zincirinde geçerli bir blok olduğu sürece, Ethereum rölesinden geçmeden doğrudan EthCrossChainData içindeki putCurEpochConPubKeyBytes fonksiyonunu çağırabilir.
  • Kevin tarafından belirtilen hash çarpışması

Sorumluluk Reddi: Bu blog, ekibimiz tarafından kamuya açık kaynak kodu ve zincir üstü işlemlere dayanılarak yapılan analiz sonuçlarını içermektedir. Poly Network'ten ek bilgi olmaksızın sonuçlarımızı doğrulayamayız.

0x.1 İşlemler ve Sözleşmeler

Saldırı Akışı

Ontology işlemi -> Ontology rölesi -> Poly zinciri -> Ethereum rölesi -> Ethereum

Ethereum

0x838bf9e95cb12dd76a54c9f9d2e3082eaf928270: EthCrossChainManager
0xcf2afe102057ba5c16f899271045a0a37fcb10f2: EthCrossChainData
0x250e76987d838a75310c34bf422ea9f1ac4cc906: LockProxy

İşlem: 0xb1f70464bd95b774c6ce60fc706eb5f9e35cb5f06e6cfe7c17dcda46ffd59581

Ontology

İşlem: 0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c

Poly

İşlem: 0x1a72a0cf65e4c08bb8aab2c20da0085d7aee3dc69369651e2e08eb798497cc80

0x2. Saldırı Akışı

Ethereum'da gerçekleşen saldırıyı örnek alalım. Bu, üç zinciri (ve bunlara karşılık gelen röleleri), yani Ontology Zinciri, Poly Zinciri ve Ethereum'u içeren bir zincirler arası saldırıdır.

Tüm saldırı akışı üç adımdan oluşmaktadır:

  1. saldırgan önce Ontology Zinciri'nde kötü amaçlı bir işlem (0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c) başlattı;
  2. saldırgan daha sonra Ethereum'daki EthCrossChainData sözleşmesinde saklanan koruyucunun (keeper) genel anahtarını değiştirdi;
  3. saldırgan son olarak kripto varlıkları ele geçirmek için kötü amaçlı bir işlem oluşturdu.

0x2.1 Birinci Adım

Saldırgan önce Ontology'den kötü amaçlı bir yük (payload) içeren zincirler arası bir işlem (0xf771ba610625d5a37b67d30bf2f8829703540c86ad76542802567caaffff280c) başlattı:

Bu yükün, özel olarak hazırlanmış bir fonksiyon adı içerdiğini fark edebilirsiniz (6631 ile başlıyor, yani dönüşümden sonra f1121318093). Bu ad kesinlikle titizlikle seçilmiştir; çünkü saldırgan, fonksiyon imzalarının hash çarpışmasından yararlanarak putCurEpochConPubKeyBytes fonksiyonunu (Ethereum'daki EthCrossChainData sözleşmesine bakınız) çağırmak için bunu kullanacaktır. Hash çarpışması konusunun ayrıntılarını burada açıklamayacağız, zira bu konu çokça tartışılmıştır.

Bunun ardından bu işlem, Ontology Zinciri Rölesi tarafından başarıyla kabul edildi. Herhangi bir katı doğrulama YOKTUR. Sonuç olarak, Poly Zinciri'nde geçerli yeni bir işlem (0x1a72a0cf65e4c08bb8aab2c20da0085d7aee3dc69369651e2e08eb798497cc80) hâline geldi.

Yeni işlem daha sonra Ethereum Rölesi tarafından algılandı ve REDDEDİLDİ. Çünkü Ethereum Rölesi, hedef sözleşme adresini (bu durumda EthCrossChainData) doğruladı; ancak yalnızca LockProxy'ye izin verilmektedir.

Bu nedenle işlem sonlandırıldı. Ancak kötü amaçlı yükü içeren işlem Poly Zinciri'nde depolandı ve bu durum saldırı başlatmak için kullanılabilir.

0x2.2 İkinci Adım

Saldırgan, EthCrossChainManager sözleşmesinin verifyHeaderAndExecuteTx fonksiyonunu çağırarak Ethereum'a manuel olarak işlem gönderdi. Poly Zinciri'nde saklanan kötü amaçlı işlem verisi girdi olarak kullanıldı. Geçerli bir Poly Zinciri işlemi olarak, verifyHeaderAndExecuteTx fonksiyonundaki doğrulamayı (imzalar ve merkle kanıtı dahil) atlayabildi. Bunun ardından, orijinal dört koruyucuyu saldırgan tarafından kontrol edilen yeni bir koruyucuyla (yani 0xA87fB85A93Ca072Cd4e5F0D4f178Bc831Df8a00B) değiştirmek için EthCrossChainData sözleşmesinin putCurEpochConPubKeyBytes fonksiyonu çağrıldı.

0x2.3 Üçüncü Adım

Koruyucunun değiştirilmesinin ardından saldırgan, Poly Zinciri'ni kullanmadan doğrudan verifyHeaderAndExecuteTx fonksiyonunu çağırabildi. Son olarak, Ethereum'dan büyük miktarda dijital varlık çalmak için LockProxy sözleşmesinin unlock fonksiyonu çağrıldı. Ayrıntılı analiz önceki raporumuzda bulunabilir.

0x3. Röle (Relayer)

Hem Ontology hem de Ethereum röleleri Go dilinde yazılmıştır. Ancak yeterli doğrulama eksikliği nedeniyle

  • Saldırgan, Poly zincirine paketlenecek kötü amaçlı bir işlem oluşturabilir
  • Saldırgan, Ethereum'daki EthCrossChainData akıllı sözleşmesindeki fonksiyonları doğrudan çağırabilir

0x3.1 Ontology Rölesi, Ontology'den Gelen Zincirler Arası İşlemlere Körü Körüne Güveniyor

ont_relayer, Ontology zincirinden gelen zincirler arası işlemleri dinlemek ve bunları Poly zincirine göndermekten sorumludur.

  • Side, Ontology zinciri anlamına gelir; Alliance, Poly zinciri anlamına gelir
  • CrossChainContractAddress, Ontology zincirindeki yerel akıllı sözleşmedir (numara 09)

Yukarıdaki şekil, Ontology rölesinin Ontology zincirine gelen ve giden zincirler arası işlemleri dinlemek için iki rutin ve zincirler arası işlemin durumunu kontrol etmek için bir rutin başlattığını göstermektedir (satır 71).

Yukarıdaki şekilde, Ontology rölesi zincirdeki olayları elde etmek için Ontology zinciri tarafından sunulan RPC arayüzünü (satır 215 GetSmartContractEventByBlock) çağırmaktadır. Satır 228 ve 232'den, bu rutinin yalnızca CrossChainContractAddress tarafından tetiklenen makeFromOntProof olayını dinlediğini görebiliriz.

Yukarıdaki şekilde, zincirler arası işlemi işlerken beş kontrol bulunmaktadır. İlk ikisi Ontology zincirine yapılan RPC isteklerini kontrol eder (kontrol 1 ve 4) ve parametrelerin boş olup olmadığı için üç kontrol vardır (kontrol 2, 3 ve 5). Ancak zincirler arası işlemdeki anlambilim için herhangi bir kontrol mevcut değildir; yani sözleşme ve yöntem adının makul olup olmadığı denetlenmez. Son olarak işlemi Poly zincirine gönderir (satır 183).

Ontology rölesi, RPC arayüzünü kullanarak işlemi oluşturur ve Poly zincirine gönderir (satır 164 - SendTransaction).

ProcessToAliianceCheckAndRetry fonksiyonu yalnızca işlemin başarısız olup olmadığını kontrol eder. Başarısız olursa işlemi yeniden gönderir.

Özetle, ont-relayer Ontology zincirinden CrossChainContractAddress tarafından tetiklenen tüm makeFromOntProof olaylarını dinler. Ardından işlem Poly zincirine gönderilir. Ontology zincirindeki herhangi birinin zincirler arası işleminin makeFromOntProof olayını tetikleyeceğini ve bunun Poly zincirine gönderilmesiyle sonuçlanacağını unutmayın.

0x3.2 Ethereum Rölesini Atlama

Ethereum Rölesi, Poly zincirinden gelen işlemleri dinlemek ve ardından işlemi Ethereum'a göndermekten sorumludur.

Ethereum Rölesi, Poly Zincirini izlemek için bir Goroutine başlatır;

Hedefi Ethereum olan zincirler arası işlemi izler (satır 275 - 278). Ardından hedef sözleşmenin (ToContractAddress) config.TargetContracts içinde yapılandırılmış sözleşmelerden biri olup olmadığını kontrol eder. Değilse, zincirler arası işlem hedef zincire (Ethereum) gönderilmeyecektir.

Ancak saldırgan, hedef zincirle doğrudan etkileşime girebilir ve EthCrossChainManager içindeki fonksiyonu çağırabilir. Başka bir deyişle, Ethereum rölesindeki kontrol atlatılabilir. Kötü amaçlı işlem poly zincirine paketlendiği sürece (bu, önceki adımda Ontology rölesi aracılığıyla gerçekleştirilmiştir), saldırgan doğrudan EthCrossChainManager ile etkileşime girebilir. Bu süreçte, Poly zincirinde geçerli bir işlem bulunduğundan imza doğrulaması (ECCUtils.verifySig) ve merkle kanıtı (ECCUtils.merkleProve) geçebilir.

Önceki iki yöntemi kullanarak saldırgan, Ethereum üzerinde ToContractAddress.method'u başarıyla çağırabilir. Hash çarpışmasıyla birleştirince, koruyucuyu değiştirmek için sonunda putCurEpochConPubKeyBytes fonksiyonu çağrılır.

Katkıda Bulunanlar

Yufeng Hu, Siwei Wu, Lei Wu, Yajin Zhou @ BlockSec

Resmi web sitesi: https://blocksec.com/

Resmi Twitter hesabı: https://twitter.com/BlockSecTeam

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit