1. Anasayfa
  2. 100 Günde Solidity

🧵 100GündeSolidity 077 – Hacks : Front Running

🧵 100GündeSolidity 077 – Hacks : Front Running
Front Running
0

Front Running Nedir ve Nasıl Önlenir?

Blockchain teknolojisi, güvenli ve şeffaf bir şekilde işlem yapılabilmesini sağlayan bir yapıya sahip. Ancak, bu yapıda da bazı saldırı ve kötüye kullanım yöntemleri mevcuttur. Bunlardan biri de “front running” olarak adlandırılan saldırı yöntemidir. Bu yöntemde, saldırganlar bir işlemi önceden gözlemleyerek, işlemi gerçekleştirmeden önce kendi işlemlerini yaparak avantaj sağlarlar. Bu durum, özellikle kripto para borsalarında ve merkeziyetsiz finans (DeFi) uygulamalarında sıkça karşılaşılan bir sorundur. Bu yazıda, front running’in ne olduğu, nasıl gerçekleştiği ve nasıl önlenmesi gerektiği hakkında bilgi verilecektir.

Front Running Nedir?

Front running, bir işlemi gerçekleştirmeden önce, o işlemi gözlemleyerek avantaj elde etme eylemidir. Bu durum, özellikle kripto para borsalarında ve DeFi uygulamalarında sıkça karşılaşılan bir sorundur. Örneğin, bir kullanıcı bir alım işlemi yapmak istediğinde, bir saldırgan bu işlemi önceden gözleyebilir ve aynı işlemi kendisi yaparak fiyatı yükseltir. Sonrasında ise, daha yüksek bir fiyattan satış işlemi gerçekleştirerek kar elde eder. Bu durumda, özgün işlem yapan kullanıcı zarar ederken, saldırgan kar elde etmiş olur.

Nasıl Gerçekleşir?

Front running, genellikle kripto para borsalarında veya DeFi uygulamalarında gerçekleşir. Saldırganlar, bu platformlarda işlem yapmak isteyen kullanıcıların işlemlerini izleyerek, önceden haberdar olurlar. Bu işlemleri gözlemleyen saldırganlar, işlem gerçekleştirmeden önce, aynı işlemi kendileri yaparak fiyatı yükseltirler. Daha sonra, daha yüksek bir fiyattan satış işlemi yaparak kar elde ederler.

Özellikle DeFi uygulamalarında, smart contract’lar (akıllı sözleşmeler) kullanıldığından, işlemler halka açık bir şekilde gerçekleştirilir. Bu nedenle, saldırganlar kolayca işlemleri gözleyebilirler. Saldırganlar, özellikle çoklu imzalı cüzdanlar gibi güvenlik özellikleri olan cüzdanları hedef alarak front running saldırıları gerçekleştirirler.

Front running’in gerçekleşmesi için, saldırganın işlemi önceden gözlemleyebilmesi gerekmektedir. Bu nedenle, saldırganlar genellikle çok hızlı ve güçlü bir internet bağlantısına sahip olurlar. Ayrıca, bazı borsalarda öncelikli işlem yapma imkanı sağlayan özellikler de saldırganların front running saldırılarını kolaylaştırır.

Front Running Neden Zararlıdır?

Front running, özellikle kripto para borsalarında ve DeFi uygulamalarında, kullanıcıların zararına olan bir saldırıdır. Bu saldırı, kullanıcıların özgün işlemlerinin fiyatını yapay şekilde yükseltir ve kullanıcıların daha yüksek fiyatlarla işlem yapmasına neden olur. Bu durumda, saldırganlar kar elde ederken, kullanıcılar zarar ederler.

Front running saldırıları, özellikle kripto para piyasalarında ve DeFi uygulamalarında yaygın olarak görülmektedir. Bu saldırılar, piyasa fiyatlarını manipüle ederek, kullanıcıların piyasada adil bir şekilde işlem yapmalarını engeller. Ayrıca, front running saldırıları, güvenliğin ve gizliliğin ihlal edilmesine neden olabilir. Bu nedenle, kullanıcıların önlem almaları ve front running saldırılarına karşı dikkatli olmaları gerekmektedir.

Front Running’den Nasıl Korunulur?

Front running saldırılarından korunmak için birkaç adım atılabilir:

  1. Limit Emirleri Kullanmak: Limit emirleri, kullanıcılara işlem fiyatlarını belirlemelerine ve işlemin sadece belirli bir fiyat seviyesinde gerçekleşmesine izin verir. Bu nedenle, front running saldırılarından korunmak için limit emirleri kullanmak önemlidir.
  2. Gizlilik Özelliklerini Kullanmak: Kullanıcılar, gizlilik özelliklerini kullanarak işlemlerini gizli tutabilirler. Böylece, saldırganlar işlemleri gözlemleyemezler ve front running saldırılarından korunulabilir.
  3. Düşük Likidite Ortamlarında İşlem Yapmamak: Front running saldırıları, özellikle düşük likidite ortamlarında daha yaygındır. Bu nedenle, düşük likidite ortamlarında işlem yapmak yerine, daha yüksek likiditeye sahip borsalarda veya uygulamalarda işlem yapmak daha güvenlidir.
  4. Daha Güvenli Cüzdanlar Kullanmak: Saldırganlar, özellikle çoklu imzalı cüzdanlar gibi güvenlik özellikleri olan cüzdanları hedef alarak front running saldırıları gerçekleştirirler. Bu nedenle, daha güvenli cüzdanlar kullanmak front running saldırılarından korunmak için önemlidir.
  5. Dikkatli Olmak: Front running saldırılarından korunmak için en önemli adım, dikkatli olmaktır. Kullanıcılar, işlemlerini gerçekleştirmeden önce piyasa koşullarını ve fiyatları iyice incelemeli ve gerekli önlemleri almalıdır. Ayrıca, güvenilir borsaları ve uygulamaları kullanmak da önemlidir.

Örneklerle Front Running Olayları

İşte front running olaylarına dair bazı örnekler:

  1. Kripto Para Borsalarında Front Running: Kripto para borsalarında front running saldırıları oldukça yaygındır. Bir saldırgan, kullanıcının yaptığı işlemden önce aynı işlemi yaparak, fiyatı yapay şekilde yükseltir ve daha yüksek bir fiyatla işlem yapar. Bu durumda, kullanıcı zarar ederken, saldırgan kar elde eder. Örneğin, 2017 yılında, EtherDelta adlı bir kripto para borsasında, bir saldırgan, kullanıcıların işlemlerini gözlemleyerek front running saldırıları gerçekleştirdi.
  2. DeFi Uygulamalarında Front Running: DeFi uygulamalarında front running saldırıları da sıkça görülmektedir. Bir saldırgan, kullanıcının işlemini önceden tahmin ederek, önceden bir işlem gerçekleştirir ve kullanıcının işleminden önce işlemi tamamlar. Bu durumda, saldırgan kullanıcının işleminden daha iyi bir fiyatla işlem yapar ve kar elde eder. Örneğin, Uniswap adlı bir DeFi uygulamasında, bir saldırgan, kullanıcıların işlemlerini gözlemleyerek front running saldırıları gerçekleştirdi.
  3. HFT Firmalarında Front Running: High Frequency Trading (HFT) firmaları, front running saldırılarına sıkça başvurmaktadırlar. HFT firmaları, kullanıcıların işlemlerini önceden tahmin ederek, önceden bir işlem gerçekleştirirler ve kullanıcının işleminden önce işlemi tamamlarlar. Bu durumda, HFT firmaları kullanıcının işleminden daha iyi bir fiyatla işlem yapar ve kar elde eder. Örneğin, 2010 yılında, Goldman Sachs adlı bir HFT firması, müşterilerinin işlemlerini önceden tahmin ederek front running saldırıları gerçekleştirdiği gerekçesiyle 550 milyon dolarlık bir cezaya çarptırıldı.

Akıllı Sözleşme Analizi

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

/*
Alice creates a guessing game.
You win 10 ether if you can find the correct string that hashes to the target
hash. Let's see how this contract is vulnerable to front running.
*/

/*
1. Alice deploys FindThisHash with 10 Ether.
2. Bob finds the correct string that will hash to the target hash. ("Ethereum")
3. Bob calls solve("Ethereum") with gas price set to 15 gwei.
4. Eve is watching the transaction pool for the answer to be submitted.
5. Eve sees Bob's answer and calls solve("Ethereum") with a higher gas price
   than Bob (100 gwei).
6. Eve's transaction was mined before Bob's transaction.
   Eve won the reward of 10 ether.

What happened?
Transactions take some time before they are mined.
Transactions not yet mined are put in the transaction pool.
Transactions with higher gas price are typically mined first.
An attacker can get the answer from the transaction pool, send a transaction
with a higher gas price so that their transaction will be included in a block
before the original.
*/

contract FindThisHash {
    bytes32 public constant hash =
        0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2;

    constructor() payable {}

    function solve(string memory solution) public {
        require(hash == keccak256(abi.encodePacked(solution)), "Incorrect answer");

        (bool sent, ) = msg.sender.call{value: 10 ether}("");
        require(sent, "Failed to send Ether");
    }
}

Bu akıllı sözleşme örneği, bir tahmin oyununu simüle ediyor. Sözleşmenin amacı, belirli bir hedef değere eşit olan bir özet değeri (hash) bulmak olan bir yarışma sunmak ve doğru cevabı ilk bulan kişiye 10 ether ödül vermek. Ancak sözleşme, front-running saldırılarına karşı savunmasızdır.

İşlev açısından bakıldığında, sözleşmenin constructor fonksiyonu, sözleşmeyi oluşturan kişi tarafından 10 ether ile başlatılmasını sağlar. solve fonksiyonu ise, oyuncuların hedef hash değerine karşılık gelen doğru cevabı bulmasını kontrol eder. Doğru cevap bulunursa, sözleşme katılımcısına 10 ether ödül verilir.

Güvenlik açısından, sözleşmenin front-running saldırılarına açık olduğu görülebilir. Özellikle, saldırganlar, transaction pool’da bekleyen bir işlemi gözlemleyerek, daha sonra daha yüksek bir gaz fiyatı ile aynı işlemi gerçekleştirerek, orijinal işlemi gerçekleştiren kişiden önce ödülü alabilirler. Bu, yarışmanın adil olmayan bir şekilde sonuçlanmasına neden olabilir.

Süreç açısından, oyuncuların doğru cevabı bulmak için birçok tahmin yapabileceği ve cevabı girmek için solve fonksiyonunu çağırabileceği bir yarışma ortamı sunulur. Ancak front-running saldırıları, bu süreci bozabilir ve yarışmanın sonuçlarını etkileyebilir.

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

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

/*
   Now Let's see how to guard from front running using commit reveal scheme.
*/

/*
1. Alice deploys SecuredFindThisHash with 10 Ether.
2. Bob finds the correct string that will hash to the target hash. ("Ethereum").
3. Bob then finds the keccak256(Address in lowercase + Solution + Secret). 
   Address is his wallet address in lowercase, solution is "Ethereum", Secret is like an password ("mysecret") 
   that only Bob knows whic Bob uses to commit and reveal the solution.
   keccak2566("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266Ethereummysecret") = '0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36'
3. Bob then calls commitSolution("0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36"), 
   where he commits the calculated solution hash with gas price set to 15 gwei.
4. Eve is watching the transaction pool for the answer to be submitted.
5. Eve sees Bob's answer and he also calls commitSolution("0xf95b1dd61edc3bd962cdea3987c6f55bcb714a02a2c3eb73bd960d6b4387fc36")
   with a higher gas price than Bob (100 gwei).
6. Eve's transaction was mined before Bob's transaction, but Eve has not got the reward yet.
   He needs to call revealSolution() with exact secret and solution, so lets say he is watching the transaction pool
   to front run Bob as he did previously
7. Then Bob calls the revealSolution("Ethereum", "mysecret") with gas price set to 15 gwei;
8. Let's consider that Eve's who's watching the transaction pool, find's Bob's reveal solution transaction and he also calls 
   revealSolution("Ethereum", "mysecret") with higher gas price than Bob (100 gwei)
9. Let's consider that this time also Eve's reveal transaction was mined before Bob's transaction, but Eve will be
   reverted with "Hash doesn't match" error. Since the revealSolution() function checks the hash using 
   keccak256(msg.sender + solution + secret). So this time eve fails to win the reward.
10.But Bob's revealSolution("Ethereum", "mysecret") passes the hash check and gets the reward of 10 ether.
*/

contract SecuredFindThisHash {
    // Struct is used to store the commit details
    struct Commit {
        bytes32 solutionHash;
        uint commitTime;
        bool revealed;
    }

    // The hash that is needed to be solved
    bytes32 public hash =
        0x564ccaf7594d66b1eaaea24fe01f0585bf52ee70852af4eac0cc4b04711cd0e2;

    // Address of the winner
    address public winner;

    // Price to be rewarded
    uint public reward;

    // Status of game
    bool public ended;

    // Mapping to store the commit details with address
    mapping(address => Commit) commits;

    // Modifier to check if the game is active
    modifier gameActive() {
        require(!ended, "Already ended");
        _;
    }

    constructor() payable {
        reward = msg.value;
    }

    /* 
       Commit function to store the hash calculated using keccak256(address in lowercase + solution + secret). 
       Users can only commit once and if the game is active.
    */
    function commitSolution(bytes32 _solutionHash) public gameActive {
        Commit storage commit = commits[msg.sender];
        require(commit.commitTime == 0, "Already committed");
        commit.solutionHash = _solutionHash;
        commit.commitTime = block.timestamp;
        commit.revealed = false;
    }

    /* 
        Function to get the commit details. It returns a tuple of (solutionHash, commitTime, revealStatus);  
        Users can get solution only if the game is active and they have committed a solutionHash
    */
    function getMySolution() public view gameActive returns (bytes32, uint, bool) {
        Commit storage commit = commits[msg.sender];
        require(commit.commitTime != 0, "Not committed yet");
        return (commit.solutionHash, commit.commitTime, commit.revealed);
    }

    /* 
        Function to reveal the commit and get the reward. 
        Users can get reveal solution only if the game is active and they have committed a solutionHash before this block and not revealed yet.
        It generates an keccak256(msg.sender + solution + secret) and checks it with the previously commited hash.  
        Front runners will not be able to pass this check since the msg.sender is different.
        Then the actual solution is checked using keccak256(solution), if the solution matches, the winner is declared, 
        the game is ended and the reward amount is sent to the winner.
    */
    function revealSolution(
        string memory _solution,
        string memory _secret
    ) public gameActive {
        Commit storage commit = commits[msg.sender];
        require(commit.commitTime != 0, "Not committed yet");
        require(commit.commitTime < block.timestamp, "Cannot reveal in the same block");
        require(!commit.revealed, "Already commited and revealed");

        bytes32 solutionHash = keccak256(
            abi.encodePacked(Strings.toHexString(msg.sender), _solution, _secret)
        );
        require(solutionHash == commit.solutionHash, "Hash doesn't match");

        require(keccak256(abi.encodePacked(_solution)) == hash, "Incorrect answer");

        winner = msg.sender;
        ended = true;

        (bool sent, ) = payable(msg.sender).call{value: reward}("");
        if (!sent) {
            winner = address(0);
            ended = false;
            revert("Failed to send ether.");
        }
    }
}

Bu akıllı sözleşme, “find the hash” oyununu kullanarak, front-running (ön koşul) saldırılarını önlemek için commit-reveal şemasını kullanmaktadır. Ayrıca, submarine send teknolojisini kullanarak gas önleme saldırılarını da önlemektedir.

İşlevsel olarak, akıllı sözleşme, iki fonksiyondan oluşur. İlk olarak, kullanıcının çözümü önceden belirleyip saklamasına olanak tanıyan bir “commitSolution” işlevi bulunmaktadır. Bu işlev, kullanıcının adresi, çözümü ve bir “secret” (gizli parola) ile keccak256 hashini hesaplar ve saklar. İkinci işlev “revealSolution”, kullanıcının çözümünü açıklamasına ve hash kontrolü yapmasına olanak tanır. Eğer kontrol geçerli ise, kullanıcı ödül alır.

Akıllı sözleşme, bir “Commit” yapısı kullanarak kullanıcının çözümünü saklamaktadır. Ayrıca, oyunun aktif olup olmadığını kontrol etmek için bir “gameActive” modifiyeri kullanmaktadır. Bunun yanı sıra, kullanıcının sadece bir kez çözüm gönderebilmesi için “Already committed” hatası veren bir kontrol mekanizması vardır.

Güvenlik açısından, akıllı sözleşme, commit-reveal şeması kullanarak front-running saldırılarını önlemektedir. Bu şema, kullanıcının çözümünü sakladığı bir “commit” aşaması ve sonrasında çözümünü açıkladığı bir “reveal” aşaması içermektedir. Front-running saldırıları, başka bir kullanıcının çözümünü görmesi ve daha yüksek bir gas fiyatı ile işlem yaparak kullanıcının çözümünü gerçekleştirmesidir. Ancak, bu akıllı sözleşme, çözümü açıklamadan önce, çözümün önceden saklanmasını gerektirerek bu tür saldırıları engellemektedir.

Süreç açısından, akıllı sözleşme, bir kullanıcının ödülü kazanmak için önceden belirlenmiş bir hash’i çözmeye çalıştığı bir oyun sunmaktadır. Oyunun amacı, hash’i çözmek ve kullanıcının çözümü doğruysa ödül kazanmasıdır. Akıllı sözleşme, kullanıcının çözümünü önceden belirlemesini ve saklamasını gerektirdiği için, oyunun tamamlanması ve ödülün kazanılması birkaç adımda gerçekleşmektedir.

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
İlginizi Çekebilir

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