Pada 8 Desember 2023, OpenZeppelin mengeluarkan peringatan penting tentang keamanan. Ternyata, saat menggunakan standar ERC-2771 dan fungsi tipe Multicall, ada risiko penggantian alamat! Saya telah mempelajari kerentanan ini secara mendalam dan ingin membagikan temuan saya.
Penyerang menukarkan 5 WETH dengan sekitar 3,455,399,346 TIME
Kemudian saya menyusun parameter calldata yang cerdik dan memanggil [Forwarder].execute
Fitur ini menjalankan multicall di kontrak TIME, dan sisa calldata digunakan untuk burn() - penghancuran token di pool!
Bagaimana ini bekerja?
Dalam serangan ini, bintang-bintang bertemu: ERC-2771, Multicall, dan data yang disusun dengan cermat. Kontrak TOKEN mewarisi ERC2771Context, dan di sinilah yang paling menarik dimulai!
ERC-2771 memberikan virtual msg.sender, memungkinkan delegasi transaksi kepada pihak ketiga. Alamat asli ditambahkan dalam calldata. Ketika [Forwarder] memanggil kontrak, _msgSender() memeriksa data ini dan memotong 20 byte terakhir sebagai "msg.sender" yang "asli".
Multicall mengubah satu panggilan menjadi beberapa, menghemat gas. Itu menerima array panggilan dan melaksanakannya melalui deleGatecall().
Dan di sinilah jebakannya! Penyerang memindahkan calldata sehingga 4 byte pertama dari data baru sesuai dengan fungsi burn(), dan parameternya - jumlah token yang sangat besar. Di baris 0x20, alamat pool likuiditas TIME-ETH ditambahkan, yang menjadi "diharapkan" msg.sender!
Akar masalah
Di ERC-2771 [Forwarder] tidak pernah direncanakan untuk bekerja dengan multicall! Penyerang menambahkan parameter _msgSender() ke panggilan eksternal multicall. Di dalam fungsi multicall, beberapa fungsi juga menambahkan parameter ini, yang memungkinkan mereka untuk mensimulasikan panggilan dari ALAMAT MANA PUN!
Langkah-langkah perlindungan
Versi baru OpenZeppelin Multicall kini menyimpan panjang konteks ERC-2771 dan mempertimbangkannya pada setiap panggilan anak.
ThirdWeb melangkah lebih jauh dan melarang kontrak mana pun untuk memanggil multicall, mencegah penggunaan [Forwarder].
Kerentanan ini adalah contoh jelas tentang bagaimana kombinasi komponen yang aman secara terpisah dapat menciptakan celah yang bencana! Semua pengembang harus ingat: selalu periksa interaksi antara berbagai standar.
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.
Analisis prinsip kerentanan penggantian alamat acak dalam ERC2771 Multicall dari SharkTeam
Pada 8 Desember 2023, OpenZeppelin mengeluarkan peringatan penting tentang keamanan. Ternyata, saat menggunakan standar ERC-2771 dan fungsi tipe Multicall, ada risiko penggantian alamat! Saya telah mempelajari kerentanan ini secara mendalam dan ingin membagikan temuan saya.
Analisis serangan
Mari kita pertimbangkan salah satu serangan:
Skema serangan sangat sederhana:
Bagaimana ini bekerja?
Dalam serangan ini, bintang-bintang bertemu: ERC-2771, Multicall, dan data yang disusun dengan cermat. Kontrak TOKEN mewarisi ERC2771Context, dan di sinilah yang paling menarik dimulai!
ERC-2771 memberikan virtual msg.sender, memungkinkan delegasi transaksi kepada pihak ketiga. Alamat asli ditambahkan dalam calldata. Ketika [Forwarder] memanggil kontrak, _msgSender() memeriksa data ini dan memotong 20 byte terakhir sebagai "msg.sender" yang "asli".
Multicall mengubah satu panggilan menjadi beberapa, menghemat gas. Itu menerima array panggilan dan melaksanakannya melalui deleGatecall().
Dan di sinilah jebakannya! Penyerang memindahkan calldata sehingga 4 byte pertama dari data baru sesuai dengan fungsi burn(), dan parameternya - jumlah token yang sangat besar. Di baris 0x20, alamat pool likuiditas TIME-ETH ditambahkan, yang menjadi "diharapkan" msg.sender!
Akar masalah
Di ERC-2771 [Forwarder] tidak pernah direncanakan untuk bekerja dengan multicall! Penyerang menambahkan parameter _msgSender() ke panggilan eksternal multicall. Di dalam fungsi multicall, beberapa fungsi juga menambahkan parameter ini, yang memungkinkan mereka untuk mensimulasikan panggilan dari ALAMAT MANA PUN!
Langkah-langkah perlindungan
Versi baru OpenZeppelin Multicall kini menyimpan panjang konteks ERC-2771 dan mempertimbangkannya pada setiap panggilan anak.
ThirdWeb melangkah lebih jauh dan melarang kontrak mana pun untuk memanggil multicall, mencegah penggunaan [Forwarder].
Kerentanan ini adalah contoh jelas tentang bagaimana kombinasi komponen yang aman secara terpisah dapat menciptakan celah yang bencana! Semua pengembang harus ingat: selalu periksa interaksi antara berbagai standar.