Analisis Kerentanan Kompiler Solidity dan Strategi Penanganannya
Kompiler adalah salah satu komponen dasar dari sistem komputer modern, fungsinya adalah untuk mengubah kode sumber bahasa pemrograman tingkat tinggi menjadi kode instruksi yang dapat dieksekusi oleh komputer. Kebanyakan pengembang dan petugas keamanan biasanya memperhatikan keamanan kode aplikasi, tetapi sering kali mengabaikan keamanan kompilernya sendiri. Sebenarnya, sebagai program komputer, kompiler juga dapat memiliki celah keamanan, yang dalam situasi tertentu dapat menimbulkan risiko keamanan yang serius.
Misalnya, saat browser mengompilasi dan mengeksekusi kode JavaScript, mungkin karena kerentanan pada mesin JavaScript, pengguna yang mengunjungi situs web berbahaya dapat diserang oleh penyerang yang memanfaatkan celah tersebut untuk melakukan eksekusi kode jarak jauh, akhirnya mengontrol browser korban bahkan sistem operasi. Penelitian lain juga menunjukkan bahwa bug pada compiler C++ dapat menyebabkan eksekusi kode jarak jauh dan akibat serius lainnya.
Compiler Solidity juga memiliki kerentanan keamanan. Menurut peringatan keamanan dari tim pengembang Solidity, terdapat kerentanan keamanan di beberapa versi compiler Solidity. Fungsi dari compiler Solidity adalah untuk mengubah kode kontrak pintar menjadi kode instruksi (EVM) yang akan diunggah ke Ethereum dan dieksekusi oleh EVM.
Perlu membedakan antara kerentanan compiler Solidity dan kerentanan EVM itu sendiri. Kerentanan EVM adalah masalah keamanan yang muncul saat mesin virtual mengeksekusi instruksi, yang dapat mempengaruhi seluruh jaringan Ethereum. Sedangkan kerentanan compiler Solidity adalah masalah yang terjadi saat mengubah Solidity menjadi kode EVM, yang tidak akan langsung mempengaruhi jaringan Ethereum, tetapi dapat menyebabkan kode EVM yang dihasilkan tidak sesuai dengan harapan pengembang.
Salah satu bahaya dari kerentanan compiler Solidity adalah, dapat menyebabkan kode EVM yang dihasilkan tidak sesuai dengan harapan pengembang kontrak pintar. Karena kontrak pintar biasanya melibatkan aset cryptocurrency pengguna, setiap bug yang disebabkan oleh compiler dapat mengakibatkan kehilangan aset pengguna dan menghasilkan konsekuensi yang serius.
Pengembang dan auditor sering kali fokus pada logika kontrak dan masalah keamanan yang umum, sementara kerentanan compiler sulit ditemukan melalui audit kode. Diperlukan analisis bersama antara versi compiler tertentu dan pola kode untuk menentukan apakah kontrak pintar terpengaruh oleh kerentanan compiler.
Berikut adalah beberapa contoh kerentanan compiler Solidity yang nyata:
SOL-2016-9 HighOrderByteCleanStorage
Kerentanan ini ada di versi awal dari compiler Solidity (>=0.1.6 <0.4.4). Pertimbangkan kode berikut:
soliditas
kontrak C {
uint32 a = 0x12345678;
uint32 b = 0;
fungsi f() publik {
a = a + 1;
}
function run() public view returns (uint32) {
return b;
}
}
Secara teoritis, variabel b tidak dimodifikasi, fungsi run() seharusnya mengembalikan 0. Namun, dalam kode yang dihasilkan oleh compiler versi yang rentan, run() akan mengembalikan 1. Ini karena EVM menggunakan elemen tumpukan berukuran 32 byte, sementara Solidity mendukung tipe data lebih kecil seperti uint32. Compiler harus membersihkan bit tinggi ( clean up ) saat memproses, tetapi tidak menangani dengan benar saat terjadi overflow penjumlahan, menyebabkan bit tinggi 1 ditulis ke variabel b.
SOL-2022-4 Efek Samping Memori InlineAssembly
Kerentanan ini ada di dalam compiler versi 0.8.13 hingga 0.8.15. Pertimbangkan kode berikut:
solidity
kontrak C {
function f() public pure returns (uint) {
assembly {
mstore(0, 0x42)
}
uint x;
assembly {
x := mload(0)
}
return x;
}
}
Kompiler menghapus operasi penulisan memori yang tampak tidak berguna untuk optimasi, tetapi secara keliru juga mengoptimalkan akses memori yang melintasi blok assembly. Hal ini menyebabkan fungsi f() mengembalikan 0 alih-alih 0x42 yang benar.
Kerentanan ini mempengaruhi kompiler versi 0.5.8 hingga 0.8.16. Pertimbangkan kode berikut:
solidity
kontrak C {
function f(string[1] calldata a) external pure returns (string memory) {
return abi.decode(abi.encode(a), (string[1]))[0];
}
}
Dalam kondisi normal, fungsi ini seharusnya mengembalikan string yang dimasukkan. Namun, dalam versi yang memiliki celah, ia akan mengembalikan string kosong. Ini karena kompiler secara keliru membersihkan beberapa data saat melakukan encoding abi pada array calldata, yang menyebabkan data yang di-encode dan di-decode tidak konsisten.
Gunakan versi terbaru dari compiler Solidity, masalah keamanan yang diketahui biasanya lebih sedikit.
Memperbaiki kasus uji unit. Sebagian besar bug di tingkat compiler akan menyebabkan hasil eksekusi kode tidak sesuai dengan yang diharapkan, dengan meningkatkan cakupan pengujian dapat menghindari masalah seperti ini.
Hindari penggunaan assembly inline, operasi ABI decoding yang kompleks, dan jangan menggunakan fitur baru serta fungsi eksperimental secara buta. Sebagian besar kerentanan compiler terkait dengan operasi kompleks ini.
Untuk petugas keamanan:
Jangan abaikan risiko keamanan yang mungkin diperkenalkan oleh compiler saat audit. Item pemeriksaan terkait adalah SWC-102: Versi Compiler Usang.
Dalam proses pengembangan, dorong tim pengembang untuk memperbarui versi compiler, dapat memperkenalkan pemeriksaan versi otomatis dalam CI/CD.
Tidak perlu terlalu khawatir tentang kerentanan compiler. Sebagian besar kerentanan hanya terpicu dalam pola kode tertentu, perlu dievaluasi dampak keamanannya berdasarkan proyek spesifik.
Beberapa sumber yang berguna:
Peringatan Keamanan Resmi Solidity:
Daftar bug resmi Solidity:
Daftar bug compiler versi yang berbeda:
Tanda peringatan di sudut kanan atas halaman Kontrak Etherscan dapat memberi tahu tentang kerentanan keamanan yang ada pada versi kompiler saat ini.
Singkatnya, pengembang dan personel keamanan harus memperhatikan risiko keamanan yang mungkin ditimbulkan oleh kerentanan compiler Solidity, mengambil langkah-langkah yang tepat untuk mengurangi risiko, dan memastikan keamanan kontrak pintar.
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.
Analisis Kerentanan Compiler Solidity dan Strategi Praktis untuk Melindungi Keamanan smart contract
Analisis Kerentanan Kompiler Solidity dan Strategi Penanganannya
Kompiler adalah salah satu komponen dasar dari sistem komputer modern, fungsinya adalah untuk mengubah kode sumber bahasa pemrograman tingkat tinggi menjadi kode instruksi yang dapat dieksekusi oleh komputer. Kebanyakan pengembang dan petugas keamanan biasanya memperhatikan keamanan kode aplikasi, tetapi sering kali mengabaikan keamanan kompilernya sendiri. Sebenarnya, sebagai program komputer, kompiler juga dapat memiliki celah keamanan, yang dalam situasi tertentu dapat menimbulkan risiko keamanan yang serius.
Misalnya, saat browser mengompilasi dan mengeksekusi kode JavaScript, mungkin karena kerentanan pada mesin JavaScript, pengguna yang mengunjungi situs web berbahaya dapat diserang oleh penyerang yang memanfaatkan celah tersebut untuk melakukan eksekusi kode jarak jauh, akhirnya mengontrol browser korban bahkan sistem operasi. Penelitian lain juga menunjukkan bahwa bug pada compiler C++ dapat menyebabkan eksekusi kode jarak jauh dan akibat serius lainnya.
Compiler Solidity juga memiliki kerentanan keamanan. Menurut peringatan keamanan dari tim pengembang Solidity, terdapat kerentanan keamanan di beberapa versi compiler Solidity. Fungsi dari compiler Solidity adalah untuk mengubah kode kontrak pintar menjadi kode instruksi (EVM) yang akan diunggah ke Ethereum dan dieksekusi oleh EVM.
Perlu membedakan antara kerentanan compiler Solidity dan kerentanan EVM itu sendiri. Kerentanan EVM adalah masalah keamanan yang muncul saat mesin virtual mengeksekusi instruksi, yang dapat mempengaruhi seluruh jaringan Ethereum. Sedangkan kerentanan compiler Solidity adalah masalah yang terjadi saat mengubah Solidity menjadi kode EVM, yang tidak akan langsung mempengaruhi jaringan Ethereum, tetapi dapat menyebabkan kode EVM yang dihasilkan tidak sesuai dengan harapan pengembang.
Salah satu bahaya dari kerentanan compiler Solidity adalah, dapat menyebabkan kode EVM yang dihasilkan tidak sesuai dengan harapan pengembang kontrak pintar. Karena kontrak pintar biasanya melibatkan aset cryptocurrency pengguna, setiap bug yang disebabkan oleh compiler dapat mengakibatkan kehilangan aset pengguna dan menghasilkan konsekuensi yang serius.
Pengembang dan auditor sering kali fokus pada logika kontrak dan masalah keamanan yang umum, sementara kerentanan compiler sulit ditemukan melalui audit kode. Diperlukan analisis bersama antara versi compiler tertentu dan pola kode untuk menentukan apakah kontrak pintar terpengaruh oleh kerentanan compiler.
Berikut adalah beberapa contoh kerentanan compiler Solidity yang nyata:
Kerentanan ini ada di versi awal dari compiler Solidity (>=0.1.6 <0.4.4). Pertimbangkan kode berikut:
soliditas kontrak C { uint32 a = 0x12345678; uint32 b = 0; fungsi f() publik { a = a + 1; } function run() public view returns (uint32) { return b; } }
Secara teoritis, variabel b tidak dimodifikasi, fungsi run() seharusnya mengembalikan 0. Namun, dalam kode yang dihasilkan oleh compiler versi yang rentan, run() akan mengembalikan 1. Ini karena EVM menggunakan elemen tumpukan berukuran 32 byte, sementara Solidity mendukung tipe data lebih kecil seperti uint32. Compiler harus membersihkan bit tinggi ( clean up ) saat memproses, tetapi tidak menangani dengan benar saat terjadi overflow penjumlahan, menyebabkan bit tinggi 1 ditulis ke variabel b.
Kerentanan ini ada di dalam compiler versi 0.8.13 hingga 0.8.15. Pertimbangkan kode berikut:
solidity kontrak C { function f() public pure returns (uint) { assembly { mstore(0, 0x42) } uint x; assembly { x := mload(0) } return x; } }
Kompiler menghapus operasi penulisan memori yang tampak tidak berguna untuk optimasi, tetapi secara keliru juga mengoptimalkan akses memori yang melintasi blok assembly. Hal ini menyebabkan fungsi f() mengembalikan 0 alih-alih 0x42 yang benar.
Kerentanan ini mempengaruhi kompiler versi 0.5.8 hingga 0.8.16. Pertimbangkan kode berikut:
solidity kontrak C { function f(string[1] calldata a) external pure returns (string memory) { return abi.decode(abi.encode(a), (string[1]))[0]; } }
Dalam kondisi normal, fungsi ini seharusnya mengembalikan string yang dimasukkan. Namun, dalam versi yang memiliki celah, ia akan mengembalikan string kosong. Ini karena kompiler secara keliru membersihkan beberapa data saat melakukan encoding abi pada array calldata, yang menyebabkan data yang di-encode dan di-decode tidak konsisten.
Terkait kerentanan compiler Solidity, tim keamanan blockchain Cobo mengajukan saran berikut:
Kepada pengembang:
Gunakan versi terbaru dari compiler Solidity, masalah keamanan yang diketahui biasanya lebih sedikit.
Memperbaiki kasus uji unit. Sebagian besar bug di tingkat compiler akan menyebabkan hasil eksekusi kode tidak sesuai dengan yang diharapkan, dengan meningkatkan cakupan pengujian dapat menghindari masalah seperti ini.
Hindari penggunaan assembly inline, operasi ABI decoding yang kompleks, dan jangan menggunakan fitur baru serta fungsi eksperimental secara buta. Sebagian besar kerentanan compiler terkait dengan operasi kompleks ini.
Untuk petugas keamanan:
Jangan abaikan risiko keamanan yang mungkin diperkenalkan oleh compiler saat audit. Item pemeriksaan terkait adalah SWC-102: Versi Compiler Usang.
Dalam proses pengembangan, dorong tim pengembang untuk memperbarui versi compiler, dapat memperkenalkan pemeriksaan versi otomatis dalam CI/CD.
Tidak perlu terlalu khawatir tentang kerentanan compiler. Sebagian besar kerentanan hanya terpicu dalam pola kode tertentu, perlu dievaluasi dampak keamanannya berdasarkan proyek spesifik.
Beberapa sumber yang berguna:
Singkatnya, pengembang dan personel keamanan harus memperhatikan risiko keamanan yang mungkin ditimbulkan oleh kerentanan compiler Solidity, mengambil langkah-langkah yang tepat untuk mengurangi risiko, dan memastikan keamanan kontrak pintar.