1. Anasayfa
  2. 100 Günde Solidity

🧵 100GündeSolidity 079 – Hacks : Signature Replay (İmza Tekrarı)

🧵 100GündeSolidity 079 – Hacks : Signature Replay (İmza Tekrarı)
İmza Tekrarı
0

İmza Tekrarı

Merhaba,

Bu e-bülten serisinin 79. gönderiminde “Signature Replay” (İmza Tekrarı) konusunu ele alacağız. Blockchain dünyasında imzaların güvenliği son derece önemlidir ve imza tekrarı gibi bir sorun, güvenlik açıklarına neden olabilir. Bu nedenle, imza tekrarının ne olduğu, neden önemli olduğu ve nasıl önlenebileceği hakkında bilgi sahibi olmak, blockchain ve smart contract geliştiricileri için son derece önemlidir.

Şimdi, imza tekrarının ne olduğuna bir göz atalım.

İmza tekrarı, bir kişinin daha önce gerçekleştirdiği bir işlemde kullanılan imzayı tekrar kullanarak, benzer bir işlemi başka bir yerde gerçekleştirmesidir. Bu, aynı imza verilerinin farklı bir işlemde yeniden kullanılması anlamına gelir. Bu işlem, imzayı oluşturan özel anahtarın kötüye kullanılması veya çalınması yoluyla gerçekleştirilebilir.

Örneğin, bir kullanıcının bir transfer işlemi yaparken imza oluşturduğunu ve bir saldırganın bu imzayı alarak başka bir transfer işlemi yapabileceğini varsayalım. Bu durumda, saldırgan transfer işlemini gerçekleştirmek için önceden kullanılan imzayı kullanarak transfer işlemini doğrulayabilir. Böylece, orijinal işlemdeki para miktarı saldırganın cüzdanına aktarılır.

Bu nedenle, imza tekrarı, güvenlik açıklarına neden olabilir ve kullanıcıların hesaplarında önemli miktarda kayıp yaşamasına neden olabilir.

İmza Tekrarı Neden Önemlidir?

İmza tekrarı, smart contract ve blockchain sistemlerinde güvenlik açıklarına neden olabilecek önemli bir sorundur. İmza tekrarı, bir kişinin kötü niyetli bir şekilde bir işlemi kopyalamasına ve aynı imzayı yeniden kullanarak benzer bir işlemi gerçekleştirmesine olanak tanır. Bu, blockchain sistemlerinde kaynakların kötüye kullanılması, para transferlerinin çalınması ve hatta sahte işlemlerin gerçekleştirilmesi gibi ciddi sonuçlara yol açabilir.

Özellikle, smart contract sistemlerinde imza tekrarına izin vermek, smart contract’ların sözleşmelerin gerektirdiği şekilde çalışmamasına neden olabilir ve sonuç olarak, para kayıplarına ve hatta akıllı sözleşmelerin etkisiz hale gelmesine neden olabilir. Bu nedenle, imza tekrarının önlenmesi ve güvenliğin sağlanması, blockchain sistemleri ve smart contract geliştiricileri için son derece önemlidir.

İmza tekrarının önlenmesi, blockchain sistemlerinde güvenliği artırarak, kullanıcıların ve yatırımcıların daha fazla güven duymasını sağlar. Bu da blockchain teknolojisi ve smart contract’ların benimsenmesini artırır ve sektörün büyümesine katkıda bulunur.

İmza Tekrarı Nasıl Önlenir?

İmza tekrarı, blockchain sistemlerinde önemli bir güvenlik açığı olduğundan, bu açığı önlemek için bazı yöntemler bulunmaktadır. İmza tekrarının önlenmesi için aşağıdaki yöntemler kullanılabilir:

  1. Tek Kullanımlık İmzalar: Tek kullanımlık imzalar, bir işlem için yalnızca bir kez kullanılabilen özel anahtarlarla oluşturulur. Bu yöntem, imza tekrarını önlemek için etkili bir yöntemdir.
  2. Zaman Damgası: İşlemlere zaman damgası eklemek, imza tekrarını önlemek için etkili bir yöntemdir. Bu yöntemde, her bir işlem için farklı bir zaman damgası oluşturulur ve herhangi bir işlemde tekrar kullanılamaz.
  3. Özel Anahtar Kontrolü: Özel anahtarların güvenliği, imza tekrarının önlenmesinde önemli bir rol oynar. Özel anahtarların güvenliği için çeşitli yöntemler kullanılabilir, örneğin donanım cüzdanları gibi.
  4. Adres Nonce’ları: Adres Nonce’ları, bir adresin yalnızca bir kez kullanılmasını sağlayarak imza tekrarını önlemek için kullanılır. Bu yöntem, özellikle ERC-20 tokenlerinde kullanılır.
  5. IPFS: IPFS (InterPlanetary File System), imza tekrarını önlemek için verilerin depolanması için kullanılabilir. IPFS, verilerin yeniden kullanılmasını önleyerek imza tekrarını önler.

Bu yöntemler, imza tekrarının önlenmesinde etkili bir şekilde kullanılabilir. Ancak, her blockchain sistemi veya smart contract projesi için en uygun yöntemin belirlenmesi, projenin özelliklerine bağlıdır.

İmza Tekrarı Örneği

İmza tekrarının bir örneği, 2016 yılında yaşanan “The DAO” hack olayıdır. The DAO, Ethereum blockchain’inde bir smart contract’tı ve dünyanın ilk merkezi olmayan özerk organizasyonuydu.

The DAO hack olayında, bir saldırgan, bir işlemi gerçekleştirerek, Ethereum ağındaki birçok adrese para çekti. Saldırgan, işlemi kopyalayarak ve aynı imzayı yeniden kullanarak benzer bir işlemi gerçekleştirdi. Bu şekilde saldırgan, The DAO’dan yaklaşık 50 milyon dolar çaldı.

Bu olay, imza tekrarının nasıl kötüye kullanılabileceğini ve smart contract’ların güvenliği için önemli bir sorun olduğunu göstermektedir. Ethereum, bu olaydan sonra imza tekrarını önlemek için çeşitli güvenlik önlemleri aldı ve bunların arasında “Tek Kullanımlık İmzalar” gibi yöntemler yer almaktadır.

Akıllı Sözleşme Analizi

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";

contract MultiSigWallet {
    using ECDSA for bytes32;

    address[2] public owners;

    constructor(address[2] memory _owners) payable {
        owners = _owners;
    }

    function deposit() external payable {}

    function transfer(address _to, uint _amount, bytes[2] memory _sigs) external {
        bytes32 txHash = getTxHash(_to, _amount);
        require(_checkSigs(_sigs, txHash), "invalid sig");

        (bool sent, ) = _to.call{value: _amount}("");
        require(sent, "Failed to send Ether");
    }

    function getTxHash(address _to, uint _amount) public view returns (bytes32) {
        return keccak256(abi.encodePacked(_to, _amount));
    }

    function _checkSigs(
        bytes[2] memory _sigs,
        bytes32 _txHash
    ) private view returns (bool) {
        bytes32 ethSignedHash = _txHash.toEthSignedMessageHash();

        for (uint i = 0; i < _sigs.length; i++) {
            address signer = ethSignedHash.recover(_sigs[i]);
            bool valid = signer == owners[i];

            if (!valid) {
                return false;
            }
        }

        return true;
    }
}

Bu akıllı sözleşme, çoklu imza cüzdanı işlevi görmektedir. İki adet sahibi olan bu cüzdan, para transferi işlemlerinde her iki sahibin imzasının gerektiği bir yapıya sahiptir.

Sözleşme, “OpenZeppelin” kütüphanesinden “ECDSA” modülünü kullanmaktadır. Bu modül, Ethereum blockchain’inde kullanılan bir imza doğrulama algoritması olan ECDSA’yı uygulamaktadır.

Sözleşme, iki adet sahibi olan bir cüzdan olarak tasarlanmıştır. Oluşturulurken, sahiplerin adresleri constructors aracılığıyla sözleşmeye tanıtılmaktadır. “deposit()” fonksiyonu, sözleşmeye ETH yatırılmasını sağlar.

“transfer()” fonksiyonu, sözleşmeden ETH transfer etmek için kullanılır. Bu fonksiyon, “_to” parametresinde belirtilen adrese, “_amount” parametresinde belirtilen miktarda ETH transferi yapar. Bu işlem için, “_sigs” parametresinde belirtilen iki adet imzanın geçerli olması gerekmektedir.

“getTxHash()” fonksiyonu, “_to” ve “_amount” parametreleri kullanılarak, bir işlem özeti olan “txHash” değerini hesaplar.

“_checkSigs()” fonksiyonu, “_sigs” parametresinde belirtilen iki adet imzanın geçerli olup olmadığını kontrol eder. Bu fonksiyon, “recover()” fonksiyonunu kullanarak imzalardan adresleri geri çeker ve bu adreslerin sahibi olup olmadığını doğrular. Bu işlem için, “toEthSignedMessageHash()” fonksiyonu kullanılarak “ethSignedHash” değeri hesaplanır.

Sonuç olarak, bu akıllı sözleşme, iki adet sahibi olan bir çoklu imza cüzdanıdır ve her işlem için iki adet geçerli imza gerektirir. Böylece, imza tekrarı ve dolandırıcılık riskleri minimize edilmeye çalışılmaktadır.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.5/contracts/utils/cryptography/ECDSA.sol";

contract MultiSigWallet {
    using ECDSA for bytes32;

    address[2] public owners;
    mapping(bytes32 => bool) public executed;

    constructor(address[2] memory _owners) payable {
        owners = _owners;
    }

    function deposit() external payable {}

    function transfer(
        address _to,
        uint _amount,
        uint _nonce,
        bytes[2] memory _sigs
    ) external {
        bytes32 txHash = getTxHash(_to, _amount, _nonce);
        require(!executed[txHash], "tx executed");
        require(_checkSigs(_sigs, txHash), "invalid sig");

        executed[txHash] = true;

        (bool sent, ) = _to.call{value: _amount}("");
        require(sent, "Failed to send Ether");
    }

    function getTxHash(
        address _to,
        uint _amount,
        uint _nonce
    ) public view returns (bytes32) {
        return keccak256(abi.encodePacked(address(this), _to, _amount, _nonce));
    }

    function _checkSigs(
        bytes[2] memory _sigs,
        bytes32 _txHash
    ) private view returns (bool) {
        bytes32 ethSignedHash = _txHash.toEthSignedMessageHash();

        for (uint i = 0; i < _sigs.length; i++) {
            address signer = ethSignedHash.recover(_sigs[i]);
            bool valid = signer == owners[i];

            if (!valid) {
                return false;
            }
        }

        return true;
    }
}

/*
// owners
0xe19aea93F6C1dBef6A3776848bE099A7c3253ac8
0xfa854FE5339843b3e9Bfd8554B38BD042A42e340

// to
0xe10422cc61030C8B3dBCD36c7e7e8EC3B527E0Ac
// amount
100
// nonce
0
// tx hash
0x12a095462ebfca27dc4d99feef885bfe58344fb6bb42c3c52a7c0d6836d11448

// signatures
0x120f8ed8f2fa55498f2ef0a22f26e39b9b51ed29cc93fe0ef3ed1756f58fad0c6eb5a1d6f3671f8d5163639fdc40bb8720de6d8f2523077ad6d1138a60923b801c
0xa240a487de1eb5bb971e920cb0677a47ddc6421e38f7b048f8aa88266b2c884a10455a52dc76a203a1a9a953418469f9eec2c59e87201bbc8db0e4d9796935cb1b
*/

Bu akıllı sözleşme, birden fazla imza sahibinin onayı gerektiren çoklu imza cüzdanı için tasarlanmıştır. Sözleşme iki imza sahibi tarafından kontrol edilir ve herhangi bir işlem yapabilmek için iki imzanın da verilmesi gerekir.

Sözleşme, bir depozito işlemi yapmak için bir fonksiyon içerir. Ayrıca, transfer fonksiyonu aracılığıyla, _to adresine _amount ETH transferi gerçekleştirebilirsiniz. İşlemi gerçekleştirmeden önce, _nonce numarasını kullanarak işlem özeti hash’ini oluşturur ve daha önce yapılmamış bir işlem olduğunu kontrol eder.

getTxHash fonksiyonu, _to, _amount, _nonce parametrelerini kullanarak işlem özetinin hash’ini hesaplar. _checkSigs fonksiyonu, _sigs parametresi olarak verilen iki imzayı kullanarak imza doğrulama işlemini gerçekleştirir.

Sözleşme, ECDSA kütüphanesinin recover fonksiyonunu kullanarak her imza için doğrulama işlemi yapar. İmza sahibinin adresi, imza doğrulama işlemi sonucunda elde edilen adresle karşılaştırılır ve imzaların geçerli olup olmadığı kontrol edilir.

Ayrıca, her işlemi yalnızca bir kez gerçekleştirmek için executed adlı bir mapping kullanılır. Bu sayede, herhangi bir işlemin yalnızca bir kez gerçekleştirilebileceği ve çift harcamaların önüne geçildiği sağlanır.

Özetle, bu akıllı sözleşme iki imza sahibi tarafından kontrol edilen çoklu imza cüzdanı için tasarlanmıştır ve herhangi bir işlem yapabilmek için iki imzanın da verilmesi gerekir. Ayrıca, her işlemin yalnızca bir kez gerçekleştirilmesini sağlayan bir kontrol mekanizması bulunur.

Sonuç ve Özet : Signature Replay (İmza Tekrarı)

İmza tekrarı (signature replay), kötü niyetli kullanıcıların bir işlemi tekrar etmelerine veya tekrar göndermelerine izin veren bir zayıflıktır. Bu durum, Ethereum ve diğer blockchain ağlarında özellikle akıllı sözleşmelerde önemli bir güvenlik riski oluşturur.

İmza tekrarını önlemek için, akıllı sözleşmeler genellikle bir nonce (tek kullanımlık sayı) kullanarak her işlem için benzersiz bir kimlik belirleyicisi oluşturur. Böylece, aynı imzayı tekrar kullanarak işlemi yeniden göndermek mümkün olmaz.

Bu yazıda, önce imza tekrarının ne olduğunu ve neden önemli bir güvenlik riski oluşturduğunu açıkladık. Daha sonra, imza tekrarını önlemek için kullanılabilecek birkaç farklı yöntemi ele aldık. Son olarak, örnek bir akıllı sözleşme üzerinde analiz yaparak imza tekrarını önleme yöntemlerini uyguladık.

Solidity Programlama Dili Öğrenme yolculuğunuz hakkında daha iyi rehberlik almak için Solidity nedir? Ethereum Akıllı Sözleşmelerinin Dili Rehberi içeriğimize göz atın. Dilerseniz Yeni Başlayanlar için Solidity – Akıllı Sözleşme Geliştirme Hızlandırılmış Kursuna katılın.

Çalışmaya nereden başlayacağım diyenler için Blockchain ​​Developer Olmak İçin Yol Haritası içeriğine de muhakkak bakın.

Gelin aklınızdaki soruları SUPERPEER sohbetinde cevaplayalım.

Bu makaleyi okuduğunuz için teşekkürler! Bana destek olmak isterseniz;

Beni TwitterLinkedin ve YouTube‘da takip edin.

Kısa bir yorum bırakmayı UNUTMAYIN!

solidity101 - Solidity, 2015 yılında Christian Reitwiessner liderliğinde piyasaya sürülen, büyük harf kullanımına göre ikinci en büyük kripto para piyasası olan Ethereum tarafından oluşturulan yepyeni bir programlama dilidir.

Yazarın Profili

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir