Зависимость от временных меток в смарт-контрактах

Опубликовано: 22 Февраля, 2023

Во время разработки смарт-контракта программистам необходимо знать точное время, чтобы иметь возможность выполнять некоторые действия в смарт-контракте. Поэтому они используют метку времени, сгенерированную узлом, выполняющим смарт-контракт. В этой статье основное внимание уделяется обсуждению уязвимости, связанной с зависимостью от временных меток.

Здесь будут обсуждаться следующие темы зависимости от временных меток в смарт-контракте:

  1. Что такое уязвимость, связанная с зависимостью от временных меток?
  2. Как работает зависимость от отметок времени?
  3. Что такое правило 15 секунд?
  4. Всегда ли использование значения метки времени вызывает уязвимость?
  5. Воздействие уязвимости, связанной с зависимостью от временных меток.
  6. Что такое зависимость номера блока?
  7. Как предотвратить уязвимость, связанную с зависимостью от временных меток?

Давайте начнем подробно обсуждать каждую из этих тем.

Что такое уязвимость, связанная с зависимостью от временных меток?

Уязвимость зависимости от временной метки возникает, когда смарт-контракт полагается на значение временной метки блока, которое генерируется узлом, выполняющим смарт-контракт, для выполнения операции. Это делает его уязвимым для атак и подверженным манипуляциям. Из-за распределенного характера сети блокчейна установка точного времени между узлами, его синхронизация и получение точного времени сети неизбежны, поскольку большинство языков разработки смарт-контрактов являются завершенными по Тьюрингу. Чтобы решить эту проблему, большинство технологий блокчейна предлагают временную метку системы для получения фактического времени в сети.

  • Временная метка блока может быть изменена майнером, чтобы использовать уязвимость в распределенной системе, такой как сама цепочка блоков. Майнер может полностью изменить вывод контракта, изменив метку времени на несколько секунд, что максимизирует его прибыль.
  • Когда смарт-контракт использует метку времени блока в качестве одного из требований для выполнения важной деятельности (например, передачи эфира) или в качестве источника энтропии для создания случайных чисел, он уязвим.
  • Уязвимость, связанная с временной меткой, возникает, когда смарт-контракт использует значение временной метки, сгенерированное узлом, для сравнения ее со значением времени, которое произойдет менее чем через 900 секунд.

Как работает зависимость от отметок времени?

Ниже приведены 2 примера, показывающих, как работает уязвимость, связанная с зависимостью от временных меток:

Пример 1: Ниже приведена программа Solidity, показывающая уязвимость, связанную с зависимостью от временных меток.

Solidity




// Solidity program to show 
// timestamp dependence vulnerability
pragma solidity ^0.5.0;
  
contract helloGeeks {
  uint public yourAnswer;
  function oddOrEven(bool yourGuess) external payable returns (bool
  {
    if (yourAnswer == now % 2 > 0) 
    {
      uint fee = msg.value / 10;
      msg.sender.transfer(msg.value * 2 – fee);
    }
  }
}

Объяснение: В приведенном выше коде значение метки времени, полученное из инструкции now при отправке транзакции, не должно делиться на 2, только тогда оно будет удовлетворять условию >0. Следовательно, нода может использовать эту уязвимость, чтобы забрать все деньги с контракта.

Пример 2: Ниже представлена программа Solidity для реализации уязвимости зависимости от временных меток.

Solidity




// Solidity program to show
// timestamp dependency vulnerability
pragma solidity ^0.4.15;
  
contract GFG{
  uint256 constant private salt =  block.timestamp;
  
  function random(uint Max) constant private returns (uint256 result)
  {
    //get the best seed for randomness
    uint256 x = salt * 100 / Max;
    uint256 y = salt * block.number/(salt % 5) ;
    uint256 seed = block.number / 3 + (salt % 300) + Last_Payout + y;
    uint256 h = uint256(block.blockhash(seed));
  
    // Random number between 1 and Max
    return uint256((h / x)) % Max + 1; 
  }
}

Объяснение:

Эту функцию легко модифицировать, поскольку узел, создающий блок, содержащий транзакцию, выполняющую код смарт-контракта, генерирует значение реальной метки времени.

  • Чтобы получить фактическое время, смарт-контракт использует переменную block.timestamp.
  • Значение этой переменной задается узлом, поэтому узел может легко манипулировать значением, увеличивая его до тех пор, пока не будет выполнено условие в коде.
  • Узлы принимают любую временную метку блока, которая попадает в определенный период времени, поскольку они являются гибкими. Изменяя временные метки блоков напрямую, злоумышленники (майнеры) могут воспользоваться уязвимостью, когда смарт-контракт передает ETH с использованием block.timestamp, создавая идеальную среду для собственного успеха.
  • Майнер может предварительно вычислить более выгодное число для лотереи, используя метод block.timestamp для заполнения этого смарт-контракта, что позволяет опубликовать альтернативную временную метку в пределах срока проверки блока.

Что такое правило 15 секунд?

Ethereum изначально ограничивал временные метки до 15 минут, однако более свежая версия Ethereum «Yellow Paper» сняла это ограничение и просто требует, чтобы временная метка блока была выше, чем временная метка ранее упомянутого блока.

  • Тем не менее, широко используемые реализации протокола Ethereum Geth и Parity в будущем будут отклонять блоки с отметками времени более 15 секунд (со средним временем приземления блока между 12-14 секундами).
  • Это указывает на то, что можно использовать block.timestamp для этой функции, если размер зависящего от времени события может измениться на 15 секунд при сохранении целостности.

Всегда ли использование значения метки времени вызывает уязвимость?

Значение Block.timestamp также проверяется для подтверждения того, что блок будет добавлен в сеть блокчейна. Это значение должно быть меньше или равно фактическому значению плюс 900 секунд.

  • Значение timestamp должно быть больше или равно значению parent.timestamp, иначе следующий блок будет автоматически отклонен.
  • Здесь у узлов есть возможность изменить timestamp таким образом, чтобы он был не ниже parent.timestamp и не выше фактического времени плюс 900.

Воздействие уязвимости, связанной с зависимостью от временных меток

Влияние уязвимости зависимости от временных меток зависит от содержимого и причины, по которой значение используется в смарт-контракте. Если есть финансовые решения, основанные на значении метки времени, то любое изменение или манипуляция влечет за собой финансовые потери.
Чем больше используется значение метки времени для контроля доступа для выполнения определенной задачи в смарт-контракте, тем более он уязвим для атак.

Что такое зависимость номера блока?

Уязвимость зависимости от номера блока сравнима с уязвимостью зависимости от временной метки.

  • Это происходит, когда программисты оценивают дельту времени, используя block.number и среднее время блока, а не block.time.
  • Поскольку блоки перемещаются по одному, это может показаться более безопасным, чем block.timestamp, но, к сожалению, у него тоже есть недостатки.
  • Тайминги блоков могут измениться в результате реорганизации форка и других обстоятельств.

Как предотвратить уязвимость, связанную с зависимостью от временных меток?

Есть 2 способа предотвратить уязвимость зависимости от временных меток:

  1. Неиспользование значения временной метки в качестве проверки контроля доступа: эта ситуация очевидна из приведенного выше примера, где обсуждается, что использование значения временной метки в качестве контроля доступа в смарт-контракте также может привести к финансовым потерям. Таким образом, целесообразно меньше использовать его в качестве контроля доступа.
  2. Допустимый диапазон +900 секунд ошибки: это означает, что если значение метки времени, возвращаемое узлом, увеличивается на значение от 1 до 900 секунд, то это не окажет огромного влияния на смарт-контракт.