ПОСЛЕДНИЕ НОВОСТИ
$
10
За просмотр новости вы заработаете
10 баллов

Участвуй в работе сайта и зарабатывай!
Узнать подробности и свой рейтинг

Взлом и как обмануть криптоказино

 Ethereum завоевал огромную популярность как платформа для ICO.

 Взлом Как обмануть криптоказино
Взлом Как обмануть криптоказино

Но она применима не только для создания токенов стандарта ERC-20. Блокчейн Ethereum можно использовать в онлайн-рулетке, лотереях и карточных играх. Подтвержденные транзакции блокчейна нельзя подделать — технология децентрализована и прозрачна, — но код умных контрактов может быть уязвим. Одна из проблем — уязвимые генераторы псевдослучайных чисел, ГПСЧ. Давай разберем типовые ошибки реализации ГПСЧ в азартных играх на базе Ethereum.

Ethereum позволяет исполнять тьюринг-полные программы, обычно написанные на языке Solidity, поэтому основатели платформы называют ее «мировым суперкомпьютером». Благодаря прозрачности Ethereum весьма удобно использовать в сфере азартных онлайн-игр, где очень важно доверие пользователя.

Однако процессы блокчейна Ethereum предсказуемы, что создает сложности для тех, кто решил написать собственный генератор псевдослучайных чисел — неотъемлемую часть любой азартной игры. Мы решили исследовать умные контракты, чтобы оценить надежность ГПСЧ на Solidity и выявить распространенные ошибки проектирования, которые приводят к уязвимостям и дают тем самым возможность предсказать случайные числа.

В 2017 году специалисты Positive Technologies реализовали проекты по анализу безопасности и защите от киберпреступников как процедуры ICO, так и внедрения блокчейн-технологий. Результаты исследования оказались безрадостными: уязвимости в смарт-контрактах были выявлены в 71% проектов, в 23% проектов были выявлены недостатки, позволяющие атаковать инвесторов. В каждом проекте ICO в среднем содержалось пять уязвимостей. Однако злоумышленникам достаточно всего одной, чтобы присвоить деньги инвесторов.

Наше исследование включает следующие стадии:

    Собрали 3649 умных контрактов с etherscan.io и GitHub.
    Импортировали контракты в Elasticsearch, поисковик с открытым кодом.
    С помощью веб-интерфейса Kibana с богатыми возможностями по поиску и фильтрации данных обнаружили 72 уникальные реализации ГПСЧ.
    Проанализировав вручную каждый контракт, мы обнаружили, что 43 контракта были уязвимы.

 Уязвимые генераторы

Анализ выявил четыре категории уязвимых ГПСЧ:

    генераторы, использующие переменные блока как источник энтропии;
    генераторы, использующие хеш предыдущего блока;
    генераторы, использующие хеш предыдущего блока в сочетании с якобы секретным начальным значением;
    генераторы, подверженные уязвимости с опережением транзакции (front-running).

Рассмотрим каждую категорию с примерами уязвимого кода.
 
Генератор, использующий переменные блока

Существует ряд переменных блока, которые могут быть по ошибке использованы как источники энтропии:

    block.coinbase представляет собой адрес майнера, который майнит данный блок;
    block.difficulty — относительный показатель того, насколько сложно создать блок;
    block.gaslimit — максимальный расход «газа» на все транзакции в блоке;
    block.number — высота данного блока;
    Block.timestamp — дата майнинга блока.

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

Пример 1 (0x80ddae5251047d6ceb29765f38fed1c0013004b7):

// Won if block number is even
// (note: this is a terrible source of randomness, please don’t use this with real money)
bool won = (block.number % 2) == 0;

Пример 2 (0xa11e4ed59dc94e69612f3111942626ed513cb172):

// Compute some *almost random* value for selecting winner from current transaction.
var random = uint(sha3(block.timestamp)) % 2;

Пример 3 (0xcC88937F325d1C6B97da0AFDbb4cA542EFA70870):

address seed1 = contestants[uint(block.coinbase) % totalTickets].addr;
address seed2 = contestants[uint(msg.sender) % totalTickets].addr;
uint seed3 = block.difficulty;
bytes32 randHash = keccak256(seed1, seed2, seed3);
uint winningNumber = uint(randHash) % totalTickets;
address winningAddress = contestants[winningNumber].addr;

Генератор, использующий хеш блока

У каждого блока в блокчейне Ethereum есть хеш для верификации транзакций. Так называемая виртуальная машина Ethereum (EVM) позволяет получить хеш блока с помощью функции block.blockhash(). Функция ожидает числовой аргумент, который обозначает номер блока. Во время исследования мы обнаружили, что результат функции block.blockhash() часто некорректно используется при генерации случайных значений.

Существуют три основные уязвимые вариации генераторов, использующих хеш блока:

    block.blockhash(block.number) — хеш текущего блока;
    block.blockhash(block.number-1) — хеш последнего блока;
    block.blockhash() — хеш блока, который как минимум на 256 блоков старше.

Переменная состояния block.number позволяет узнать высоту данного блока. Когда майнер добавляет транзакцию в блок, которая выполняет код контракта, известен block.number будущего блока этой транзакции и контракту доступно его значение. Однако в момент выполнения транзакции в EVM хеш создаваемого блока еще неизвестен по очевидным причинам, и EVM всегда выдает ноль.

Некоторые контракты ошибочно интерпретируют значение выражения block.blockhash(block.number). В таких контрактах хеш блока считается известным во время выполнения транзакции и используется как источник энтропии.

Пример 1 (0xa65d59708838581520511d98fb8b5d1f76a96cad):

function deal(address player, uint8 cardNumber) internal returns (uint8) {
   uint b = block.number;
   uint timestamp = block.timestamp;
   return uint8(uint256(keccak256(block.blockhash(b), player, cardNumber, timestamp)) % 52);
}

Пример 2 (https://github.com/axiomzen/eth-random/issues/3):

function random(uint64 upper) public returns (uint64 randomNumber) {
   _seed = uint64(sha3(sha3(block.blockhash(block.number), _seed), now));
   return _seed % upper;
}

block.blockhash(block.number-1)

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

Пример 1 (0xF767fCA8e65d03fE16D4e38810f5E5376c3372A8):

//Generate random number between 0 & max
uint256 constant private FACTOR =  1157920892373161954235709850086879078532699846656405640394575840079131296399;
function rand(uint max) constant private returns (uint256 result){
   uint256 factor = FACTOR * 100 / max;
   uint256 lastBlockNumber = block.number - 1;
   uint256 hashVal = uint256(block.blockhash(lastBlockNumber));
   return uint256((uint256(hashVal) / factor)) % max;
}

block.blockhash() — хеш будущего блока

Более надежный способ — использовать хеш будущего блока, например следующим образом.
1. Игрок делает ставку, казино запоминает block.number транзакции.
2. При втором вызове контракта игрок запрашивает у казино выигрышный номер.
3. Казино извлекает сохраненный block.number, получает хеш блока по его номеру и затем использует хеш при генерации псевдослучайного числа.

Такой подход работает, только если выполняется одно важное требование. В документации Solidity есть предупреждение об ограниченном числе хешей блоков, которые может хранить EVM.

Поделитесь информацией с друзьями!

Просто нажми на кнопки соцсетей внизу!

Источник

 

Добавить комментарий

Filtered HTML

  • Разрешённые HTML-теги: <em> <strong> <cite> <blockquote> <ul> <ol> <li> <dl> <dt> <dd> <br> <br />
  • Строки и параграфы переносятся автоматически.
  • Search Engines will index and follow ONLY links to allowed domains.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки. Ссылки на сторонние не рекламные источники необходимо вставлять в виде http://orskportal.ru/outlink/адрес...
  • Строки и параграфы переносятся автоматически.
2 + 0 =
Введите ответ в пустое поле. Например для 1+3 введите 4.