Странности смарт-контрактов: как не надо работать с деньгами

27 апреля

Вы наверняка не раз слышали новости про то, как некий взломщик проэксплуатировал какой-то смарт-контракт и украл миллионы долларов. Не техническим специалистам может показаться, что там всё очень сложно – только самого умного хакера ждёт солидный куш. Так ли это? Объясняет антивирусный эксперт Лаборатории Касперского Алексей Маланов.

Так и есть – найти и проэксплуатировать уязвимость – это, действительно, сложно. Но вот когда она уже найдена (а деньги украдены), всё становится гораздо проще. Сейчас я расскажу, как же именно осуществляются взломы. Простыми словами.

Сегодня начнём с самой знаменитой атаки – The DAO.

Общие сведения о смарт-контрактах

В 2015 году появилась криптовалюта Ethereum ("эфир") – ныне вторая по капитализации. Её ключевым нововведением стала поддержка полноценных смарт-контрактов. Если вы плохо понимаете, что это, не пугайтесь, это всего лишь мини-программа по управлению деньгами или другими цифровыми активами.

Все кошельки в Ethereum делятся на два типа: людские (управляются хозяевами) и контракты (управляются программным кодом).

Что это позволило. Ну, например, можно запрограммировать "пирамиду": если на кошелёк-контракт приходит 1 "эфир", он запоминает отправителя, а впоследствии отправит обратно 2 эфира. Разумеется, за счёт вновь поступивших средств.

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

Ещё можно реализовать деривативы (сделки с условиями): фьючерсы, свопы, опционы...

Главное преимущество смарт-контрактов: все видят текст программы, все понимают условия её работы (по крайней мере, имеют возможность). Ему можно доверять, его исполнение строго, как запрограммировано, гарантируется блокчейн. В отличие от традиционной лотереи, где организатор может приворовать часть сборов или попросту сбежать.

Такие мощные смарт-контракты появились впервые, поэтому, как водится, не обошлось без неожиданностей и «косяков».

Пишем типичный смарт-контракт

Запрограммируем «игрушечные деньги». Если у вас есть хоть какой-нибудь опыт программирования, то вам наверняка многое будет интуитивно понятно. В противном случае, пожалуйста, внимательно прочитайте комментарии к коду.

Рассмотрим поподробнее строчку 13. Когда какой-то пользователь хочет купить игрушечных денег, он вызывает функцию BuyToyMoney(), а в нагрузку прикладывает к этому немного "эфира". Адрес этого пользователя будет содержаться в переменной msg.sender, а количество отправленных денег – в msg.value.

Теперь взглянем на строчку 23. Отправка кому-то "эфира" записана в виде «вызвать у кошелька-получателя msg.sender функцию по умолчанию call(), приложив немного денег value(amount)».

Как видите, игрушечные деньги можно купить и можно продать. Сам контракт ведет учет владельцев игрушечных денег и их балансов. Если у вас есть какие-то токены на базе Ethereum (обычно реализовываются по стандарту ERC20), то эти токены – лишь баланс в каком-то смарт-контракте. Их передача другому пользователю – это вызов соответствующей функции в этом смарт-контракте.

По сути, проведение ICO – это написание вот такого вот контракта и продажа новых игрушечных денег. Некоторые фантики/вкладыши впоследствии превращаются в относительно твердую валюту. Какие-то другие не стоят ничего.

Эксплуатируем типичный контракт

Как это ни печально, но такой простой контракт, который мы только что написали, фатально уязвим: можно украсть с него весь "эфир" и получить квинтиллион игрушечных денег.

Для этого мы разберём технику «повторный вход».

Дело в том, что в Ethereum отправка денег к кому-то – это вызов функции «прими деньги» в кошельке-получателе. А если получателем денег тоже будет смарт-контракт, то он получит управление и сможет, например, продать те же игрушечные монеты второй раз.

Поясним на конкретном примере.

Злоумышленник пишет контракт справа. В нём две функции. Первая, LaunchAttack(), она покупает и продаёт одну игрушечную монетку. Вторая – функция приёма денег, она продаёт монетку.

Что происходит (по стрелкам сверху вниз):

  1. Злоумышленник вызывает LaunchAttack()
  2. Происходит покупка, управление передаётся в BuyToyMoney()
  3. Управление возвращается обратно
  4. Происходит продажа

Пока все идёт по плану, никаких аномалий.

Далее:

  1. Во время продажи сначала происходит проверка достаточности баланса
  2. Потом отправка денег – вызов function () payable
  3. И наконец, красная стрелка – повторный вход в функцию SellToyMoney()
  4. Баланс всё ещё позволяет снова отправить "эфир" злоумышленнику

И только в самом конце происходит уменьшение баланса дважды:

Как видите, в итоге злоумышленник получил в два раза больше "эфира", чем вложил. Мечта всех любителей "пирамид" по принципу «отправь один – получи два».

Взлом The DAO

Вот именно так у The DAO в 2016 году и украли 3.5 млн ETH ($60 млн по курсу на тот день). Но обо всём по порядку.

Преисполненные энтузиазма, любители смарт-контрактов в какой-то момент заявили: «А зачем нам традиционные компании, которые управляются людьми? Ведь люди некомпетентны, ошибаются, воруют, ленятся. Почему бы нам всю их работу не запрограммировать, чтобы работало само.» Так появилась концепция DAO (Decentralized Autonomous Organization) - организация, реализованная на смарт-контрактах. Все её функции запрограммированы, все права и свободы регламентированы.

The DAO – это конкретная DAO, коллективный инвест-фонд. Реализован отчасти разработчиками Ethereum. Там по задумке прямая демократия: инвесторы голосованием решают, в какой проект вложить. Кто больше денег влил в The DAO, у того больше голосов при управлении. Всё, как в акционерном обществе.

Можно проголосовать «ногами», то есть вывести свои средства, если вы не согласны с политикой инвестирования большинства. Только способ вывода был уж очень оригинальный: ваши деньги при этом перетекают в дочерний инвест-фонд, в котором вы единственный голосующий, а дальше вы голосуете за то, чтобы вложить всё в свой кошелек... И на всё на это нужен месяц (созревание нового фонда и голосование требуют времени).

Как бы там ни было, а на 06.06.2016 в The DAO 20000 «криптоинвесторов» вложили $150 млн или 11 млн ETH, что составляло 13.6% от всего эфира, существовавшего на тот момент.

А уже 17.06.2016 злоумышленник воспользовался описанной выше техникой «повторного входа» и вывел на подконтрольную ему дочернюю DarkDAO 3.5 млн ETH ($60 млн по курсу на тот день, $2 млрд на сегодняшний день).

Реализация атаки была чуточку сложнее – она использовала выплату дивидендов и всякие голосования – но основной принцип именно такой.

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

Потом злоумышленник почему-то остановился. Видимо, решил, что $60 млн ему хватит. Но возникла новая угроза, кто-то другой мог продолжить его дело. И тогда авторы The DAO пошли на единственно возможный верный шаг: они атаковали собственный контракт точно таким же образом и вывели оставшиеся деньги. Эта техника защиты будет не раз применяться впоследствии.

Любопытно, что в описании The DAO было: «The terms of The DAO Creation are set forth in the smart contract,» - любые операции, дозволенные самим кодом программы, должны признаваться законными. И злоумышленник утверждал, что он вовсе и не злоумышленник – сделал всё по правилам, просто правила нечестные по отношению к инвесторам.

Ещё интересная деталь. О проблеме «повторного входа» не было известно в течение целого года после запуска Ethereum: никто просто не думал, что так можно. Но обнаружена она была всё же до атаки на The DAO.

За пять дней до события, 12.06.2016, один из авторов кода The DAO, эксперт по смарт-контрактам, бывший коммерческий директор Ethereum написал: «Наша команда благословлена отцом-основателем использованного языка программирования, под его чутким руководством мы всё перепроверили и смеем вас заверить - ваши деньги в безопасности!» Это мой вольный перевод.

Вообще, даже если бы средства не украли и The DAO бы не закрылся, то у него, вероятно, возникли бы другие сложности. В этой концепции были как социальные эксплоиты, так и банальная апатия участников. Но эта тема заслуживает отдельной статьи.

Блокчейн можно изменить, если что-то пошло не так Взлом The DAO интересен ещё и тем, что он имел значимое продолжение. Наверняка вы слышали об этой истории или даже являетесь владельцем криптовалюты Ethereum Classic (ETC), образовавшейся в результате «решения проблемы».

Напомню, что в The DAO вложили 13.6% всего эфира, в числе пострадавших вероятно были и создатели Ethereum. Самые влиятельные создатели заявили: «А давайте изменим правила блокчейна так, что будто взлома и не было, вернём все деньги, контракта с багой тоже как бы не было.» Это мой вольный пересказ.

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

Если правила записи блоков меняют так, что новые блоки не подходят под старые правила – это называется хардфорк, разделение цепи. Дальше блоки добавляются независимо по старым и новым правилам. Новые правила поддержало большинство (там взлом «отменили»), поэтому они сохранили старое название Ethereum (ETH). А старые правила поддержало достаточное количество участников, чтобы проект не умер. Они назвали себя Ethereum Classic (ETC), добавились на биржи и существуют параллельно.

ETH на 17.04.2018 стоит $500, а ETC - $16, в 30 раз меньше. Все те, у кого был "эфир" до разделения, автоматом получили «новые» ETH и «старые» ETC в равном количестве. Вот так вот образуются ценности в мире криптовалют. ETH вернули всем вкладчикам The DAO, ETC – нет. Все в плюсе.

Заключение

Что ж, мы рассмотрели лишь один кейс неординарного дизайна смарт-контрактов в криптовалюте Ethereum. Хотя он довольно простой по сути, он долгое время оставался незамеченным, потом он привёл к значительным денежным потерям, но в конце концов к «чудесному» обогащению всех причастных и непричастных.

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

Войдите на сайт, чтобы оставить комментарий
0 комментариев
Популярные
Новые

Рассылка

Подписывайтесь на обновления и анонсы

18+
Москва, Берсеневская набережная 6/2
+7 (495) 118-41-48
2018 © Blockchain.ru, Сделано в Charmer
  • Дисклеймер
  • Пользовательское соглашение
  • Политика конфиденциальности

К сожалению, браузер, которым вы пользуйтесь, устарел и не позволяет корректно отображать сайт. Пожалуйста, установите любой из современных браузеров, например:

Google Chrome Firefox Opera