Selamat datang di seri artikel tentang “Penelitian Keamanan Jembatan Lintas Rantai” yang diproduksi oleh Chengdu Chain Security, di artikel sebelumnya (Penelitian Keamanan Jembatan Lintas Rantai (2) | Apa yang dibawa oleh perampokan jembatan Nomad terdesentralisasi pertama kepada kita?), Kami melakukan analisis teknis profesional terhadap protokol jembatan Nomad secara rinci.
Hari ini, Tim Riset Keamanan Rantai Chengdu akan melakukan dialisis yang aman dari Polygon, seorang prajurit poligon, jadi teruslah membaca.
Siapa 1_Polygon?
Polygon adalah solusi penskalaan layer2 Ethereum, dengan visi untuk membangun internet blockchain Ethereum. Polygon menyediakan kerangka kerja umum yang memungkinkan pengembang memanfaatkan keamanan Ethereum untuk membuat rantai yang disesuaikan dan berfokus pada aplikasi dan menyediakan jaringan yang dapat dioperasikan yang menggabungkan berbagai skema penskalaan yang berbeda seperti: zk-rollup, PoS, dll. Di antara mereka, Polygon PoS saat ini merupakan solusi penskalaan paling matang dan terkenal di Polygon. Ini menggunakan sidechain untuk pemrosesan transaksi untuk mencapai tujuan meningkatkan kecepatan transaksi dan menghemat konsumsi gas, dan struktur jaringan terutama mencakup tiga lapisan berikut:
Lapisan Ethereum:
Serangkaian kontrak di mainnet Ethereum, terutama termasuk: kontrak Staking, Checkpoint, dan Reward, bertanggung jawab atas fungsi manajemen staking yang terkait dengan taruhan PoS, termasuk: menyediakan fungsi staking token asli MATIC, sehingga siapa pun yang mempertaruhkan token dapat bergabung dengan sistem sebagai validator, memverifikasi konversi jaringan Polygon untuk mendapatkan hadiah staking, menghukum validator untuk tanda tangan ganda, waktu henti validator dan perilaku ilegal lainnya, dan menyimpan pos pemeriksaan.
Lapisan Heimdall:
Lapisan validator proof-of-stake, yang terdiri dari satu set node PoS Heimdall, bertanggung jawab untuk mengirimkan pos pemeriksaan jaringan Polygon ke mainnet Ethereum sambil mendengarkan serangkaian kontrak staking yang diterapkan di Ethereum. Proses utamanya adalah sebagai berikut: pertama, pilih subset validator aktif di kumpulan validator sebagai produsen blok, yang akan bertanggung jawab untuk membuat blok di lapisan Bor dan menyiarkannya, kemudian memvalidasi hash root Merkle dan menambahkan tanda tangan berdasarkan pos pemeriksaan yang dikirimkan oleh Bor, dan akhirnya, pengusul akan bertanggung jawab untuk mengumpulkan semua tanda tangan validator untuk pos pemeriksaan yang ditentukan, dan jika jumlah tanda tangan mencapai lebih dari 2/3, pos pemeriksaan akan diserahkan di Ethereum.
** Lapisan Bor: **
Lapisan produsen blok, yang terdiri dari sekelompok produsen blok yang dipilih secara teratur oleh komite validator pada lapisan Heimdall, adalah bagian dari validator yang bertanggung jawab untuk menggabungkan transaksi pada sidechain Polygon dan menghasilkan blok. Lapisan ini secara berkala menerbitkan pos pemeriksaan ke lapisan Heimdall, di mana pos pemeriksaan mewakili snapshot dari rantai Bor, seperti yang ditunjukkan pada gambar di bawah ini.
2_Polygon Interoperabilitas
2.1 Pos pemeriksaan
Mekanisme pos pemeriksaan adalah mekanisme untuk menyinkronkan data lapisan Bor ke Ethereum, di mana data yang disinkronkan adalah pos pemeriksaan, yaitu snapshot dari data blok lapisan Bor yang terkandung dalam interval pos pemeriksaan, kode sumbernya adalah sebagai berikut:
Pengusul: Pengusul, yang juga dipilih oleh validator, produsen blok dan pengusul adalah bagian dari validator, dan tanggung jawab mereka ditentukan oleh saham mereka di keseluruhan kumpulan
RootHash: adalah hash Merkle yang dihasilkan dari blok Bor antara StartBlock dan EndBlock
Berikut ini adalah pseudo-code untuk blok Bor bernomor 1 sampai n untuk menghasilkan nilai RootHash:
Singkatnya, nilai ini adalah nilai hash root dari pohon Merkel, yang terdiri dari nomor blok di header blok Bor, stempel waktu blok, nilai hash akar pohon transaksi tx hash, dan nilai hash keccak256 yang dihitung dari hash akar pohon penerimaan.
AccountRootHash: Hash Merkle dari informasi akun terkait validator yang perlu dikirim ke setiap pos pemeriksaan di Ethereum, dan nilai hash dari informasi akun individual dihitung sebagai berikut:
AccountRootHash dihasilkan dari hash root pohon Merkle akun dengan cara yang sama seperti nilai RootHash.
**2.2 StateSync **
StateSync mengacu pada sinkronisasi data Ethereum ke rantai Polygon Matic, yang terutama dibagi menjadi langkah-langkah berikut:
Pertama, kontrak pada Ethereum akan memicu fungsi syncState() di StateSender.sol untuk sinkronisasi status
Fungsi syncState() akan memancarkan event event sebagai berikut:
Semua validator di layer Heimdall akan menerima event, dan salah satu validator akan mengemas transaksi ke blok heimdall dan menambahkannya ke daftar sinkronisasi status tertunda;
Simpul lapisan bor akan mendapatkan daftar di atas untuk disinkronkan melalui API, dan menyerahkannya ke kontrak lapisan bor untuk pemrosesan logika bisnis lebih lanjut.
2.3 Jembatan Poligon
Polygon Bridge memungkinkan saluran lintas rantai dua arah antara Polygon dan Ethereum, sehingga memudahkan pengguna untuk mentransfer token antara dua platform rantai yang berbeda tanpa ancaman pihak ketiga dan kendala likuiditas pasar. Ada dua jenis Polygon Bridge, PoS dan Plasma, dan keduanya memiliki kesamaan berikut dalam transfer aset antara Polygon dan Ethereum:
Pertama, Anda perlu memetakan token di Ethereum ke Polygon, seperti yang ditunjukkan pada gambar di bawah ini:
Teknologi penahan dua arah (Two-way Peg) juga digunakan, yaitu
a: Semua aset token yang ditransfer dari Ethereum akan dikunci di Ethereum terlebih dahulu, dan jumlah token yang dipetakan akan sama akan dicetak di Polygon;
b: Untuk menarik aset token ke Ethereum, Anda harus terlebih dahulu membakar token yang dipetakan ini di Polygon, lalu membuka kunci aset yang dikunci di Ethereum;
Gambar berikut menunjukkan perbandingan antara Jembatan PoS dan Jembatan Plasma:
Seperti dapat dilihat dari gambar di atas, dalam hal keamanan, PoS Bridge bergantung pada keamanan set validator eksternal, sedangkan Plasma bergantung pada keamanan rantai utama Ethereum. Pada saat yang sama, ketika pengguna melakukan transfer aset lintas rantai (seperti mentransfer token dari Polygon ke Ethereum), PoS hanya memerlukan interval pos pemeriksaan, sekitar 20 menit hingga 3 jam, sedangkan Plasma membutuhkan periode tantangan sengketa 7 hari. Pada saat yang sama, PoS mendukung lebih banyak token standar, sementara Plasma hanya mendukung tiga jenis, termasuk: ETH, ERC20, ERC721.
3\Pesan rantai _Cross—Jembatan PoS
Jembatan PoS terutama terdiri dari dua fungsi: Deposit mengacu pada transfer aset pengguna di Ethereum ke Polygon, dan Penarikan mengacu pada penarikan aset dari Polygon ke Ethereum.
Setoran
Berikut ini adalah contoh pengguna Alice menggunakan PoS Bridge untuk mengirim aset token dari akun Ethereum-nya ke akun Polygon-nya:
Jika aset token yang ingin Anda transfer adalah ERC20, ERC721, atau ERC1155, Anda perlu mengotorisasi token yang ingin Anda transfer melalui fungsi approtect. Seperti yang ditunjukkan di bawah ini, jumlah token yang sesuai diotorisasi ke kontrak erc20Prefer dengan memanggil metode approtect dalam kontrak token di Ethereum.
Fungsi approtect memiliki dua parameter:
Pembelanja: Alamat tujuan tempat pengguna mengotorisasi pengeluaran token
amount: Jumlah token yang dapat dibelanjakan
Setelah transaksi otorisasi di atas dikonfirmasi, pengguna kemudian mengunci token ke dalam kontrak erc20Preliminary di Ethereum dengan memanggil metode depositFor() dari kontrak RootChainManager. Di sini, jika jenis aset yang akan ditransfer adalah ETH, depositEtherFor() dipanggil. Rinciannya adalah sebagai berikut:
Fungsi depositFor memiliki tiga parameter:
user: Alamat pengguna yang menerima token deposit di Polygon
rootToken: Alamat token pada rantai Ethereum utama
depositData: Jumlah token yang dikodekan oleh ABI
Berikut ini adalah kode spesifik fungsi depositFor dalam kontrak RootChainManager:
Menganalisis kode sumber, dapat dilihat bahwa fungsi tersebut pertama-tama memperoleh alamat kontrak predikat yang sesuai dengan token, dan kemudian memanggil fungsi lockTokens() untuk mengunci token dalam kontrak. Akhirnya, syncState() akan dipanggil untuk sinkronisasi status oleh _stateSender, yang hanya dapat dipanggil oleh pengirim status yang ditetapkan oleh admin.
Fungsi syncState() di StateSender.sol akan mengirimkan acara StateSynced, khususnya:
Parameter pertama adalah indeks nomor urut log, parameter kedua digunakan untuk memverifikasi apakah pemanggil adalah alamat kontrak sah terdaftar, dan parameter ketiga adalah data yang perlu disinkronkan dengan negara. Transaksi ditambahkan ke blok Heimdall dan ditambahkan ke daftar sinkronisasi status tertunda.
Kemudian, setelah node bor pada rantai Polygon Matic memperoleh peristiwa StateSynced dalam daftar sinkronisasi status melalui API, kontrak ChildChainManager pada rantai akan memanggil fungsi onStateReceive(), yang digunakan untuk menerima data sinkronisasi yang diunggah dari Ethereum, dan melanjutkan ke langkah berikutnya sesuai dengan jenis logika bisnis sinkronisasi status:
data: bytes32 syncType dan bytes syncData. Saat syncType dipetakan, syncData adalah alamat rootToken yang dikodekan, alamat childToken, dan tokenType bytes32, dan ketika syncType disimpan, syncData adalah alamat pengguna yang dikodekan. Alamat rootToken dan depositData dari jenis byte. depositData adalah kuantitas dalam REC20 dan tokenId dalam ERC721.
Karena ini adalah bisnis Deposito, fungsi _syncDeposit() akan dipanggil. Fungsi ini pertama-tama akan memecahkan kode syncData dalam format yang sesuai untuk mendapatkan rootToken, alamat pengguna, dan depositData yang sesuai. Kemudian periksa apakah rootToken memiliki token pemetaan yang sesuai pada poligon, dan panggil fungsi deposit() dari childToken jika ada.
Di sini kita mengambil kontrak token ERC20 sebagai contoh untuk memperkenalkan cara menyetor kontrak token pemetaan. Fungsi ini mentransfer jumlah token yang sesuai ke akun pengguna.
Fungsi ini memiliki dua parameter:
user: Alamat pengguna yang melakukan deposit
depositData: Jumlah yang dikodekan dalam ABI
Penarikan
Berikut ini adalah contoh pengguna Alice yang menggunakan PoS Bridge untuk menarik dana yang disimpan di akun Polygon-nya ke akun Ethereum-nya:
Saat pengguna menarik diri, pengguna perlu membakar jumlah token yang dipetakan yang sesuai dengan memanggil fungsi withdraw() dari kontrak token pemetaan pada rantai Polygon.
Penarikan hanya berisi satu parameter: jumlah token yang akan dibakar. Fungsi withdraw() dalam kontrak token yang sesuai adalah sebagai berikut:
Transaksi di atas akan dimasukkan ke dalam pos pemeriksaan setelah sekitar 20 menit hingga 3 jam, dan validator akan mengirimkannya ke Ethereum.
Setelah transaksi ditambahkan ke pos pemeriksaan dan dikirimkan ke Ethereum, fungsi exit() dari kontrak RootChainManager di Ethereum akan dipanggil, yang akan mengkonfirmasi validitas transaksi penarikan di Polygon dengan memverifikasi konten pos pemeriksaan yang dikirimkan, dan memicu kontrak Predikat yang sesuai untuk membuka kunci token yang disetorkan pengguna.
Input bukti buktiData yang diteruskan ke fungsi mencakup data berikut:
headerNumber: Berisi header blok pos pemeriksaan untuk transaksi penarikan
blockProof: Buktikan bahwa header blok dalam rantai anak adalah simpul daun dari akar merkle yang melakukan
blockNumber: Nomor blok pada rantai anak yang berisi transaksi penarikan
blockTime: Stempel waktu blok dari transaksi penarikan
txRoot: Nilai root dari pohon transaksi blok
receiptRoot: Nilai root dari pohon tanda terima blok
Kwitansi: Tanda terima untuk transaksi penarikan
receiptProof: Bukti Merck dari tanda terima transaksi penarikan
branchMask: Jalur ke tanda terima yang diwakili oleh 32 bit di pohon tanda terima
receiptLogIndex: Indeks log yang dibaca dari pohon tanda terima
Berikut ini adalah logika inti dari fungsi, yang terutama mencakup tiga bagian: bagian pertama adalah untuk memverifikasi validitas tanda terima transaksi penarikan, bagian kedua adalah untuk memverifikasi apakah pos pemeriksaan berisi blok transaksi, dan bagian ketiga adalah memanggil fungsi exitTokens() dalam kontrak predikat untuk mengirim token yang terkunci kepada pengguna.
Ambil kontrak ERC20Predicate sebagai contoh, yaitu, setelah mendekode penerima, pengirim, dan jumlah token yang dikirim dari log, sejumlah token tertentu akan dikirim ke pengguna.
Menurut analisis kode sumber dari proses pesan lintas rantai PoS Bridge, panggilan fungsi dari seluruh proses hanya dapat dipanggil oleh peran yang ditentukan oleh validator, sehingga keamanan lintas rantai hanya dijamin oleh PoS (notaris).
4\Pesan rantai _Cross—Jembatan Plasma
Plasma Bridge juga mencakup dua fungsi: Deposit dan Penarikan, seperti yang ditunjukkan pada gambar berikut:
Polygon Plasma sedikit berbeda dari implementasi Bitcoin Plasma MVP yang diperkenalkan dalam artikel pertama seri jembatan lintas rantai kami, yang terutama menggunakan model Plasma MoreVP berbasis akun. Dibandingkan dengan Plasma, algoritma telah ditingkatkan sebagian di bagian penarikan.
Karena transfer token ERC20 dan ERC721 diwujudkan melalui log peristiwa yang mirip dengan Bitcoin UTXO, pertama-tama mari kita perkenalkan acara tersebut:
input1: Saldo akun pengirim sebelum transfer
input2: Saldo rekening penerima sebelum transfer
output1: Saldo akun pengirim setelah transfer
output2: Saldo rekening penerima setelah transfer
Kedua, karena MVP Plasma asli dihasilkan oleh satu operator atau sejumlah kecil produsen blok, ada dua skenario serangan di Polygon:
Operator Jahat:
Artikel sebelumnya (Penelitian tentang Keamanan Jembatan Lintas Rantai (2) | Nomad cross-chain bridge) menyebutkan bahwa ketika transaksi pengguna dikemas ke dalam blok Plasma oleh Operator, ada tidak tersedianya data off-chain. Oleh karena itu, ketika pengguna melakukan transaksi keluar, jika mereka mulai menarik diri dari transaksi yang lebih lama, Operator dapat menantangnya dengan salah satu transaksi terbaru mereka, dan tantangannya akan berhasil. Pada saat yang sama, karena mekanisme pos pemeriksaan PoS yang digunakan dalam Plasma, jika Operator berkolusi dengan validator untuk melakukan kejahatan, mereka bahkan dapat menempa beberapa transisi status dan mengirimkannya ke Ethereum.
Pengguna Jahat:
Pengguna terus membelanjakan token di Polygon setelah memulai transaksi keluar, mirip dengan pengeluaran ganda lintas rantai.
Singkatnya, algoritma Plasma MoreVp Polygon menggunakan algoritma lain untuk menghitung prioritas keluar, yaitu keluar dari transaksi terbaru. Karena metode ini menggunakan peristiwa LogTransfer yang mirip dengan UTXO, selama transaksi sah pengguna menggunakan input1 dan input2 yang benar, bahkan jika beberapa transaksi berbahaya dikemas sebelum transaksi pengguna, transaksi pengguna dapat ditangani dengan benar karena transaksi pengguna hanya berasal dari input yang valid. Pseudocode yang relevan adalah sebagai berikut:
Setoran
Mari kita ambil contoh pengguna Alice menggunakan Plasma Bridge untuk mengirim aset token dari akun Ethereum-nya ke akun Polygon-nya:
Pertama-tama, pengguna juga perlu mengotorisasi aset token yang perlu mereka transfer ke depositManager kontrak Polygon di rantai utama (Ethereum) melalui fungsi approtect.
Setelah transaksi resmi dikonfirmasi, pengguna memanggil fungsi erc20token.deposit() untuk memicu fungsi depositERC20ForUser() dari kontrak depositManager dan menyetor aset token ERC20 pengguna.
Ketika mainnet Ethereum mengonfirmasi transaksi deposit, itu akan membuat blok yang hanya berisi transaksi ini, dan mengirimkannya ke kontrak childChain di jaringan Polygon menggunakan mekanisme sinkronisasi negara, mencetak jumlah koin yang dipetakan yang sama dan menyimpannya ke akun pengguna di Polygon.
Catatan: Menurut analisis kode sumber kontrak childChain, Plasma hanya mendukung tiga jenis, termasuk: ETH, ERC20, dan ERC721.
Tarik
Ketika pengguna ingin menggunakan jembatan Plasma untuk menarik aset dari Polygon ke Ethereum, mereka akan melalui langkah-langkah berikut:
Pengguna membakar aset token yang dipetakan pada rantai Polygon dengan memanggil fungsi withdraw() dari koin yang dipetakan di Polygon:
Anda juga dapat memanggil implementasi antarmuka withdrawStart() Klien Plasma di Polygon.
Pengguna dapat memanggil fungsi startExitWithBurntTokens() dalam kontrak ERC20Predicate, yang pertama-tama akan memanggil WithdrawManager.verifyInclusion() untuk memverifikasi apakah pos pemeriksaan berisi transaksi penarikan dan tanda terima yang sesuai, kodenya adalah sebagai berikut:
Setelah verifikasi berlalu, WithdrawManager.addExitToQueue() akan dipanggil untuk memasukkannya ke dalam antrian pesan sesuai urutan prioritas:
Terakhir, addExitToQueue() memanggil _addExitToQueue() untuk mencetak NFT sebagai voucher pengembalian dana:
Pengguna menunggu periode tantangan 7 hari
Setelah periode tantangan selesai, Anda dapat memanggil fungsi WithdrawManager.processExits() untuk mengirim token ke pengguna.
Fungsi ini dibagi menjadi dua langkah: pertama, konfirmasikan apakah transaksi penarikan dalam antrian pesan telah melewati periode tantangan 7 hari, dan jika periode tantangan telah berlalu, hapus transaksi dari antrian:
Kemudian, tentukan apakah NFT voucher pengembalian dana telah dihapus selama periode tantangan, dan jika tidak, NFT akan dihancurkan dan aset terkait akan dikembalikan kepada pengguna:
Pada tanggal 5 Oktober 2021, White Hat Gerhard Wagner mengajukan kerentanan Polygon yang dapat menyebabkan serangan pengeluaran ganda yang melibatkan $850 juta, di mana White Hat menerima hadiah bug resmi $2,000,000 dari Polygon.
Dalam pengenalan Plasma Bridge di atas, kita tahu bahwa proses transaksi Withdraw lengkap adalah sebagai berikut:
- Pengguna memulai transaksi Penarikan di Polygon, yang membakar token pengguna di Polygon;
- Setelah interval pos pemeriksaan (sekitar 30 menit), tunggu transaksi penarikan dimasukkan ke dalam pos pemeriksaan;
- Lebih dari 2/3 validator menandatangani dan mengirimkannya ke Ethereum, di mana pengguna memanggil startExitWithBurntTokens() dalam kontrak ERC20PredicateBurnOnly untuk memverifikasi apakah pos pemeriksaan berisi transaksi pembakaran;
- Jika verifikasi lulus, voucher pengembalian dana NFT akan dicetak dan dikirim ke pengguna
- Pengguna menunggu periode tantangan 7 hari
- Hubungi WithdrawManager.processExits() untuk menghancurkan NFT dan mengembalikan dana pengguna
Catatan: Untuk mencegah pemutaran ulang transaksi (serangan pengeluaran ganda), Polygon menggunakan NFT sebagai bukti pengembalian dana untuk mengidentifikasi transaksi Penarikan secara unik. Namun, karena cacat pembuatan ID NFT, penyerang dapat membuat parameter untuk menghasilkan beberapa NFT dengan ID berbeda menggunakan transaksi Penarikan valid yang sama, dan kemudian menggunakan NFT ini untuk transaksi pengembalian dana, sehingga mencapai “serangan pengeluaran ganda”.
Berikut adalah tampilan lebih dekat tentang cara menghasilkan NFT:
Dari analisis kode sumber di atas, dapat dilihat bahwa addExitToQueue() akan memanggil _addExitToQueue() untuk mencetak NFT:
Menurut analisis parameter, exitid = priority, maka ID NFT dihasilkan oleh pergeseran kiri prioritas usia di Plasma Bridge.
Seperti yang dapat dilihat dari analisis kode sumber di atas, usia adalah nilai pengembalian fungsi WithdrawManager.verifyInclusion(), yang pertama-tama akan memverifikasi validitas transaksi penarikan, dan kemudian menghasilkan usia yang sesuai jika verifikasi lulus. Dalam logika validasi, nilai yang diterjemahkan oleh data parameter yang dapat dikontrol adalah branchMaskBytes:
Nilai ini juga digunakan saat menghasilkan usia:
Lacak fungsi MerklePatriciaProof.verify() yang dipanggil dalam logika verifikasi transaksi, dan temukan bahwa fungsi tersebut memanggil _getNibbleArray() untuk mentranskode branchMaskBytes:
Terus lacak fungsi decoding, yang membuang sebagian nilai saat mentranscoding branchMaskBytes, dan cara kehilangan nilai ini akan menyebabkan nilai yang berbeda ditranskode untuk mendapatkan nilai dekode yang sama. Secara khusus, jika bit heksadesimal pertama (setengah byte) dari nilai b yang dikodekan hp yang masuk adalah 1 atau 3, bit heksadesimal kedua diurai. Jika tidak, byte pertama diabaikan begitu saja.
Jika penyerang membangun parameter branchMaskBytes sehingga bit heksadesimal pertama tidak sama dengan 1 dan 3, ada 14*16 = 224 cara untuk mendapatkan nilai transkode yang sama.
Proses serangan spesifik adalah sebagai berikut:
- Setor ETH / token dalam jumlah besar ke Polygon melalui Polygon Plasma
- Mulai perdagangan Tarik di Polygon dan tunggu periode tantangan 7 hari
- Ubah byte pertama dari parameter branchMaskBytes dalam transaksi penarikan (transaksi valid yang sama dapat dikirim ulang hingga 223 kali) dan memulai transaksi penarikan berulang kali
Singkatnya, kerentanan ini terutama disebabkan oleh masalah dalam desain algoritma ID NFT yang menghasilkan voucher pengembalian dana untuk mencegah pemutaran ulang, sehingga transaksi pengembalian dana yang sama dapat menghasilkan NFT yang berbeda, yang mengakibatkan serangan pengeluaran ganda. Ternyata byte pertama dari branch mask yang dikodekan harus selalu 0x00. Perbaikannya adalah memeriksa apakah byte pertama dari topeng cabang yang dikodekan 0x00 dan tidak memperlakukannya sebagai topeng yang salah.
Nah, berbagi hari ini selesai, di edisi berikutnya, Tim Riset Keamanan Keamanan Rantai Chengdu akan memperkenalkan penelitian keamanan proyek lintas rantai lainnya, harap nantikan.
Lihat Asli
Halaman ini mungkin berisi konten pihak ketiga, yang disediakan untuk tujuan informasi saja (bukan pernyataan/jaminan) dan tidak boleh dianggap sebagai dukungan terhadap pandangannya oleh Gate, atau sebagai nasihat keuangan atau profesional. Lihat Penafian untuk detailnya.
Dialisis Keamanan Polygon Warrior Polygon: Bagaimana Memastikan Keamanan dan Stabilitas Lintas Rantai?
Penulis: Chengdu Lian’an
Asli: “Penelitian tentang Keamanan Jembatan Lintas Rantai (3)” | Dialisis aman Polygon Warrior, bagaimana mencegah pembukaan “Kotak Pandora”?
Selamat datang di seri artikel tentang “Penelitian Keamanan Jembatan Lintas Rantai” yang diproduksi oleh Chengdu Chain Security, di artikel sebelumnya (Penelitian Keamanan Jembatan Lintas Rantai (2) | Apa yang dibawa oleh perampokan jembatan Nomad terdesentralisasi pertama kepada kita?), Kami melakukan analisis teknis profesional terhadap protokol jembatan Nomad secara rinci.
Hari ini, Tim Riset Keamanan Rantai Chengdu akan melakukan dialisis yang aman dari Polygon, seorang prajurit poligon, jadi teruslah membaca.
Siapa 1_Polygon?
Polygon adalah solusi penskalaan layer2 Ethereum, dengan visi untuk membangun internet blockchain Ethereum. Polygon menyediakan kerangka kerja umum yang memungkinkan pengembang memanfaatkan keamanan Ethereum untuk membuat rantai yang disesuaikan dan berfokus pada aplikasi dan menyediakan jaringan yang dapat dioperasikan yang menggabungkan berbagai skema penskalaan yang berbeda seperti: zk-rollup, PoS, dll. Di antara mereka, Polygon PoS saat ini merupakan solusi penskalaan paling matang dan terkenal di Polygon. Ini menggunakan sidechain untuk pemrosesan transaksi untuk mencapai tujuan meningkatkan kecepatan transaksi dan menghemat konsumsi gas, dan struktur jaringan terutama mencakup tiga lapisan berikut:
Lapisan Ethereum:
Serangkaian kontrak di mainnet Ethereum, terutama termasuk: kontrak Staking, Checkpoint, dan Reward, bertanggung jawab atas fungsi manajemen staking yang terkait dengan taruhan PoS, termasuk: menyediakan fungsi staking token asli MATIC, sehingga siapa pun yang mempertaruhkan token dapat bergabung dengan sistem sebagai validator, memverifikasi konversi jaringan Polygon untuk mendapatkan hadiah staking, menghukum validator untuk tanda tangan ganda, waktu henti validator dan perilaku ilegal lainnya, dan menyimpan pos pemeriksaan.
Lapisan Heimdall:
Lapisan validator proof-of-stake, yang terdiri dari satu set node PoS Heimdall, bertanggung jawab untuk mengirimkan pos pemeriksaan jaringan Polygon ke mainnet Ethereum sambil mendengarkan serangkaian kontrak staking yang diterapkan di Ethereum. Proses utamanya adalah sebagai berikut: pertama, pilih subset validator aktif di kumpulan validator sebagai produsen blok, yang akan bertanggung jawab untuk membuat blok di lapisan Bor dan menyiarkannya, kemudian memvalidasi hash root Merkle dan menambahkan tanda tangan berdasarkan pos pemeriksaan yang dikirimkan oleh Bor, dan akhirnya, pengusul akan bertanggung jawab untuk mengumpulkan semua tanda tangan validator untuk pos pemeriksaan yang ditentukan, dan jika jumlah tanda tangan mencapai lebih dari 2/3, pos pemeriksaan akan diserahkan di Ethereum.
** Lapisan Bor: **
Lapisan produsen blok, yang terdiri dari sekelompok produsen blok yang dipilih secara teratur oleh komite validator pada lapisan Heimdall, adalah bagian dari validator yang bertanggung jawab untuk menggabungkan transaksi pada sidechain Polygon dan menghasilkan blok. Lapisan ini secara berkala menerbitkan pos pemeriksaan ke lapisan Heimdall, di mana pos pemeriksaan mewakili snapshot dari rantai Bor, seperti yang ditunjukkan pada gambar di bawah ini.
2_Polygon Interoperabilitas
2.1 Pos pemeriksaan
Mekanisme pos pemeriksaan adalah mekanisme untuk menyinkronkan data lapisan Bor ke Ethereum, di mana data yang disinkronkan adalah pos pemeriksaan, yaitu snapshot dari data blok lapisan Bor yang terkandung dalam interval pos pemeriksaan, kode sumbernya adalah sebagai berikut:
Pengusul: Pengusul, yang juga dipilih oleh validator, produsen blok dan pengusul adalah bagian dari validator, dan tanggung jawab mereka ditentukan oleh saham mereka di keseluruhan kumpulan
RootHash: adalah hash Merkle yang dihasilkan dari blok Bor antara StartBlock dan EndBlock
Berikut ini adalah pseudo-code untuk blok Bor bernomor 1 sampai n untuk menghasilkan nilai RootHash:
Singkatnya, nilai ini adalah nilai hash root dari pohon Merkel, yang terdiri dari nomor blok di header blok Bor, stempel waktu blok, nilai hash akar pohon transaksi tx hash, dan nilai hash keccak256 yang dihitung dari hash akar pohon penerimaan.
AccountRootHash: Hash Merkle dari informasi akun terkait validator yang perlu dikirim ke setiap pos pemeriksaan di Ethereum, dan nilai hash dari informasi akun individual dihitung sebagai berikut:
AccountRootHash dihasilkan dari hash root pohon Merkle akun dengan cara yang sama seperti nilai RootHash.
**2.2 StateSync **
StateSync mengacu pada sinkronisasi data Ethereum ke rantai Polygon Matic, yang terutama dibagi menjadi langkah-langkah berikut:
Pertama, kontrak pada Ethereum akan memicu fungsi syncState() di StateSender.sol untuk sinkronisasi status
Fungsi syncState() akan memancarkan event event sebagai berikut:
Semua validator di layer Heimdall akan menerima event, dan salah satu validator akan mengemas transaksi ke blok heimdall dan menambahkannya ke daftar sinkronisasi status tertunda;
Simpul lapisan bor akan mendapatkan daftar di atas untuk disinkronkan melalui API, dan menyerahkannya ke kontrak lapisan bor untuk pemrosesan logika bisnis lebih lanjut.
2.3 Jembatan Poligon
Polygon Bridge memungkinkan saluran lintas rantai dua arah antara Polygon dan Ethereum, sehingga memudahkan pengguna untuk mentransfer token antara dua platform rantai yang berbeda tanpa ancaman pihak ketiga dan kendala likuiditas pasar. Ada dua jenis Polygon Bridge, PoS dan Plasma, dan keduanya memiliki kesamaan berikut dalam transfer aset antara Polygon dan Ethereum:
a: Semua aset token yang ditransfer dari Ethereum akan dikunci di Ethereum terlebih dahulu, dan jumlah token yang dipetakan akan sama akan dicetak di Polygon;
b: Untuk menarik aset token ke Ethereum, Anda harus terlebih dahulu membakar token yang dipetakan ini di Polygon, lalu membuka kunci aset yang dikunci di Ethereum;
Gambar berikut menunjukkan perbandingan antara Jembatan PoS dan Jembatan Plasma:
Seperti dapat dilihat dari gambar di atas, dalam hal keamanan, PoS Bridge bergantung pada keamanan set validator eksternal, sedangkan Plasma bergantung pada keamanan rantai utama Ethereum. Pada saat yang sama, ketika pengguna melakukan transfer aset lintas rantai (seperti mentransfer token dari Polygon ke Ethereum), PoS hanya memerlukan interval pos pemeriksaan, sekitar 20 menit hingga 3 jam, sedangkan Plasma membutuhkan periode tantangan sengketa 7 hari. Pada saat yang sama, PoS mendukung lebih banyak token standar, sementara Plasma hanya mendukung tiga jenis, termasuk: ETH, ERC20, ERC721.
3\Pesan rantai _Cross—Jembatan PoS
Jembatan PoS terutama terdiri dari dua fungsi: Deposit mengacu pada transfer aset pengguna di Ethereum ke Polygon, dan Penarikan mengacu pada penarikan aset dari Polygon ke Ethereum.
Setoran
Berikut ini adalah contoh pengguna Alice menggunakan PoS Bridge untuk mengirim aset token dari akun Ethereum-nya ke akun Polygon-nya:
Fungsi approtect memiliki dua parameter:
Pembelanja: Alamat tujuan tempat pengguna mengotorisasi pengeluaran token
amount: Jumlah token yang dapat dibelanjakan
Fungsi depositFor memiliki tiga parameter:
user: Alamat pengguna yang menerima token deposit di Polygon
rootToken: Alamat token pada rantai Ethereum utama
depositData: Jumlah token yang dikodekan oleh ABI
Berikut ini adalah kode spesifik fungsi depositFor dalam kontrak RootChainManager:
Menganalisis kode sumber, dapat dilihat bahwa fungsi tersebut pertama-tama memperoleh alamat kontrak predikat yang sesuai dengan token, dan kemudian memanggil fungsi lockTokens() untuk mengunci token dalam kontrak. Akhirnya, syncState() akan dipanggil untuk sinkronisasi status oleh _stateSender, yang hanya dapat dipanggil oleh pengirim status yang ditetapkan oleh admin.
Parameter pertama adalah indeks nomor urut log, parameter kedua digunakan untuk memverifikasi apakah pemanggil adalah alamat kontrak sah terdaftar, dan parameter ketiga adalah data yang perlu disinkronkan dengan negara. Transaksi ditambahkan ke blok Heimdall dan ditambahkan ke daftar sinkronisasi status tertunda.
data: bytes32 syncType dan bytes syncData. Saat syncType dipetakan, syncData adalah alamat rootToken yang dikodekan, alamat childToken, dan tokenType bytes32, dan ketika syncType disimpan, syncData adalah alamat pengguna yang dikodekan. Alamat rootToken dan depositData dari jenis byte. depositData adalah kuantitas dalam REC20 dan tokenId dalam ERC721.
Fungsi ini memiliki dua parameter:
user: Alamat pengguna yang melakukan deposit
depositData: Jumlah yang dikodekan dalam ABI
Penarikan
Berikut ini adalah contoh pengguna Alice yang menggunakan PoS Bridge untuk menarik dana yang disimpan di akun Polygon-nya ke akun Ethereum-nya:
Penarikan hanya berisi satu parameter: jumlah token yang akan dibakar. Fungsi withdraw() dalam kontrak token yang sesuai adalah sebagai berikut:
Transaksi di atas akan dimasukkan ke dalam pos pemeriksaan setelah sekitar 20 menit hingga 3 jam, dan validator akan mengirimkannya ke Ethereum.
Setelah transaksi ditambahkan ke pos pemeriksaan dan dikirimkan ke Ethereum, fungsi exit() dari kontrak RootChainManager di Ethereum akan dipanggil, yang akan mengkonfirmasi validitas transaksi penarikan di Polygon dengan memverifikasi konten pos pemeriksaan yang dikirimkan, dan memicu kontrak Predikat yang sesuai untuk membuka kunci token yang disetorkan pengguna.
Input bukti buktiData yang diteruskan ke fungsi mencakup data berikut:
headerNumber: Berisi header blok pos pemeriksaan untuk transaksi penarikan
blockProof: Buktikan bahwa header blok dalam rantai anak adalah simpul daun dari akar merkle yang melakukan
blockNumber: Nomor blok pada rantai anak yang berisi transaksi penarikan
blockTime: Stempel waktu blok dari transaksi penarikan
txRoot: Nilai root dari pohon transaksi blok
receiptRoot: Nilai root dari pohon tanda terima blok
Kwitansi: Tanda terima untuk transaksi penarikan
receiptProof: Bukti Merck dari tanda terima transaksi penarikan
branchMask: Jalur ke tanda terima yang diwakili oleh 32 bit di pohon tanda terima
Berikut ini adalah logika inti dari fungsi, yang terutama mencakup tiga bagian: bagian pertama adalah untuk memverifikasi validitas tanda terima transaksi penarikan, bagian kedua adalah untuk memverifikasi apakah pos pemeriksaan berisi blok transaksi, dan bagian ketiga adalah memanggil fungsi exitTokens() dalam kontrak predikat untuk mengirim token yang terkunci kepada pengguna.
Menurut analisis kode sumber dari proses pesan lintas rantai PoS Bridge, panggilan fungsi dari seluruh proses hanya dapat dipanggil oleh peran yang ditentukan oleh validator, sehingga keamanan lintas rantai hanya dijamin oleh PoS (notaris).
4\Pesan rantai _Cross—Jembatan Plasma
Plasma Bridge juga mencakup dua fungsi: Deposit dan Penarikan, seperti yang ditunjukkan pada gambar berikut:
Polygon Plasma sedikit berbeda dari implementasi Bitcoin Plasma MVP yang diperkenalkan dalam artikel pertama seri jembatan lintas rantai kami, yang terutama menggunakan model Plasma MoreVP berbasis akun. Dibandingkan dengan Plasma, algoritma telah ditingkatkan sebagian di bagian penarikan.
Karena transfer token ERC20 dan ERC721 diwujudkan melalui log peristiwa yang mirip dengan Bitcoin UTXO, pertama-tama mari kita perkenalkan acara tersebut:
input1: Saldo akun pengirim sebelum transfer
input2: Saldo rekening penerima sebelum transfer
output1: Saldo akun pengirim setelah transfer
output2: Saldo rekening penerima setelah transfer
Kedua, karena MVP Plasma asli dihasilkan oleh satu operator atau sejumlah kecil produsen blok, ada dua skenario serangan di Polygon:
Operator Jahat:
Artikel sebelumnya (Penelitian tentang Keamanan Jembatan Lintas Rantai (2) | Nomad cross-chain bridge) menyebutkan bahwa ketika transaksi pengguna dikemas ke dalam blok Plasma oleh Operator, ada tidak tersedianya data off-chain. Oleh karena itu, ketika pengguna melakukan transaksi keluar, jika mereka mulai menarik diri dari transaksi yang lebih lama, Operator dapat menantangnya dengan salah satu transaksi terbaru mereka, dan tantangannya akan berhasil. Pada saat yang sama, karena mekanisme pos pemeriksaan PoS yang digunakan dalam Plasma, jika Operator berkolusi dengan validator untuk melakukan kejahatan, mereka bahkan dapat menempa beberapa transisi status dan mengirimkannya ke Ethereum.
Pengguna Jahat:
Pengguna terus membelanjakan token di Polygon setelah memulai transaksi keluar, mirip dengan pengeluaran ganda lintas rantai.
Singkatnya, algoritma Plasma MoreVp Polygon menggunakan algoritma lain untuk menghitung prioritas keluar, yaitu keluar dari transaksi terbaru. Karena metode ini menggunakan peristiwa LogTransfer yang mirip dengan UTXO, selama transaksi sah pengguna menggunakan input1 dan input2 yang benar, bahkan jika beberapa transaksi berbahaya dikemas sebelum transaksi pengguna, transaksi pengguna dapat ditangani dengan benar karena transaksi pengguna hanya berasal dari input yang valid. Pseudocode yang relevan adalah sebagai berikut:
Setoran
Mari kita ambil contoh pengguna Alice menggunakan Plasma Bridge untuk mengirim aset token dari akun Ethereum-nya ke akun Polygon-nya:
Pertama-tama, pengguna juga perlu mengotorisasi aset token yang perlu mereka transfer ke depositManager kontrak Polygon di rantai utama (Ethereum) melalui fungsi approtect.
Setelah transaksi resmi dikonfirmasi, pengguna memanggil fungsi erc20token.deposit() untuk memicu fungsi depositERC20ForUser() dari kontrak depositManager dan menyetor aset token ERC20 pengguna.
Catatan: Menurut analisis kode sumber kontrak childChain, Plasma hanya mendukung tiga jenis, termasuk: ETH, ERC20, dan ERC721.
Tarik
Ketika pengguna ingin menggunakan jembatan Plasma untuk menarik aset dari Polygon ke Ethereum, mereka akan melalui langkah-langkah berikut:
Anda juga dapat memanggil implementasi antarmuka withdrawStart() Klien Plasma di Polygon.
Setelah verifikasi berlalu, WithdrawManager.addExitToQueue() akan dipanggil untuk memasukkannya ke dalam antrian pesan sesuai urutan prioritas:
Terakhir, addExitToQueue() memanggil _addExitToQueue() untuk mencetak NFT sebagai voucher pengembalian dana:
Pengguna menunggu periode tantangan 7 hari
Setelah periode tantangan selesai, Anda dapat memanggil fungsi WithdrawManager.processExits() untuk mengirim token ke pengguna.
Fungsi ini dibagi menjadi dua langkah: pertama, konfirmasikan apakah transaksi penarikan dalam antrian pesan telah melewati periode tantangan 7 hari, dan jika periode tantangan telah berlalu, hapus transaksi dari antrian:
Kemudian, tentukan apakah NFT voucher pengembalian dana telah dihapus selama periode tantangan, dan jika tidak, NFT akan dihancurkan dan aset terkait akan dikembalikan kepada pengguna:
5_Polygon Kerentanan pengeluaran ganda Jembatan Plasma
Pada tanggal 5 Oktober 2021, White Hat Gerhard Wagner mengajukan kerentanan Polygon yang dapat menyebabkan serangan pengeluaran ganda yang melibatkan $850 juta, di mana White Hat menerima hadiah bug resmi $2,000,000 dari Polygon.
Dalam pengenalan Plasma Bridge di atas, kita tahu bahwa proses transaksi Withdraw lengkap adalah sebagai berikut:
- Pengguna memulai transaksi Penarikan di Polygon, yang membakar token pengguna di Polygon;
- Setelah interval pos pemeriksaan (sekitar 30 menit), tunggu transaksi penarikan dimasukkan ke dalam pos pemeriksaan;
- Lebih dari 2/3 validator menandatangani dan mengirimkannya ke Ethereum, di mana pengguna memanggil startExitWithBurntTokens() dalam kontrak ERC20PredicateBurnOnly untuk memverifikasi apakah pos pemeriksaan berisi transaksi pembakaran;
- Jika verifikasi lulus, voucher pengembalian dana NFT akan dicetak dan dikirim ke pengguna
- Pengguna menunggu periode tantangan 7 hari
- Hubungi WithdrawManager.processExits() untuk menghancurkan NFT dan mengembalikan dana pengguna
Catatan: Untuk mencegah pemutaran ulang transaksi (serangan pengeluaran ganda), Polygon menggunakan NFT sebagai bukti pengembalian dana untuk mengidentifikasi transaksi Penarikan secara unik. Namun, karena cacat pembuatan ID NFT, penyerang dapat membuat parameter untuk menghasilkan beberapa NFT dengan ID berbeda menggunakan transaksi Penarikan valid yang sama, dan kemudian menggunakan NFT ini untuk transaksi pengembalian dana, sehingga mencapai “serangan pengeluaran ganda”.
Berikut adalah tampilan lebih dekat tentang cara menghasilkan NFT:
Menurut analisis parameter, exitid = priority, maka ID NFT dihasilkan oleh pergeseran kiri prioritas usia di Plasma Bridge.
Nilai ini juga digunakan saat menghasilkan usia:
Jika penyerang membangun parameter branchMaskBytes sehingga bit heksadesimal pertama tidak sama dengan 1 dan 3, ada 14*16 = 224 cara untuk mendapatkan nilai transkode yang sama.
Proses serangan spesifik adalah sebagai berikut:
- Setor ETH / token dalam jumlah besar ke Polygon melalui Polygon Plasma
- Mulai perdagangan Tarik di Polygon dan tunggu periode tantangan 7 hari
- Ubah byte pertama dari parameter branchMaskBytes dalam transaksi penarikan (transaksi valid yang sama dapat dikirim ulang hingga 223 kali) dan memulai transaksi penarikan berulang kali
Singkatnya, kerentanan ini terutama disebabkan oleh masalah dalam desain algoritma ID NFT yang menghasilkan voucher pengembalian dana untuk mencegah pemutaran ulang, sehingga transaksi pengembalian dana yang sama dapat menghasilkan NFT yang berbeda, yang mengakibatkan serangan pengeluaran ganda. Ternyata byte pertama dari branch mask yang dikodekan harus selalu 0x00. Perbaikannya adalah memeriksa apakah byte pertama dari topeng cabang yang dikodekan 0x00 dan tidak memperlakukannya sebagai topeng yang salah.
Nah, berbagi hari ini selesai, di edisi berikutnya, Tim Riset Keamanan Keamanan Rantai Chengdu akan memperkenalkan penelitian keamanan proyek lintas rantai lainnya, harap nantikan.