Мы только что видели, как небольшая лазейка приводит к финансовым потерям (различной величины), точно так же, как смарт-контракты, разработанные на Solidity, подвержены различным известным и неизвестным атакам. Злоумышленники используют ошибки и лазейки, чтобы заглядывать в смарт-контракты и манипулировать ими для проведения атак. Здесь мы представляем исчерпывающий список из 5 наиболее часто встречающихся ошибок в языке программирования Solidity.
В QuillAudits мы следуем адаптивной методологии, чтобы понять суть каждого взлома и применить полученные знания в будущих смарт-контрактах, чтобы избежать любой потенциальной угрозы.
Ошибки в языке программирования Solidity
1. Непроверенный внешний вызов
Мы решаем эту проблему в первую очередь потому, что это одна из наиболее часто наблюдаемых ловушек Solidity. Как правило, отправка эфира на любой внешний аккаунт осуществляется через перевод() функция. Помимо этого, две наиболее широко используемые функции для выполнения внешнего вызова: вызов()и Отправить(), здесь в основном вызов() Функция широко используется разработчиками для выполнения универсальных внешних вызовов.
Хотя вызов() и Отправить() функции возвращают логическое значение, определяющее, был ли вызов успешным или нет. Таким образом, в этом случае, если какая-либо из функций вызов() or Отправить() не выполняет задачу, они вернутся с ложный. Следовательно, если разработчик не проверит возвращаемое значение, это станет ловушкой.
Уязвимость
Рассмотрим пример ниже:
контракт Lotto {
boolpublic payedOut = false;
адрес публичного победителя;
uintpublic сумма_выигрыша;
//… дополнительная функциональность здесь
function sendToWinner () public {
требовать (! payedOut);
победитель.send (winAmount);
payedOut = true;
}
function removewLeftOver () public {
требовать (payedOut);
msg.sender.send (this.balance);
}
}
В приведенном выше контракте, похожем на Lotto, мы можем заметить, что победитель получает сумма выигрыша эфира, оставляя небольшой остаток, который может быть извлечен из любого внешнего агента.
Здесь подводный камень для контракта существует в строке [11], где a Отправить используется без перекрестной проверки ответа. В приведенном выше примере победитель чья транзакция не удалась (либо из-за нехватки газа, либо если это контракт, который намеренно включает функцию отката), разрешает оплачено быть установлен на правда независимо от того, была ли транзакция эфира успешной или нет. В этом случае любой эксплуататор может изъять победитель выигрыш через removeLeftOver функции.
Подход QuillAudit
Наша собственная команда разработчиков устраняет эту ошибку с помощью [перевод] функция вместо [Отправить] функция, так как [передача] будет отменена, если внешняя транзакция вернется. И если вы используете [send], всегда проверяйте возвращаемое значение.
Один из надежных подходов, которым мы следуем, - это использование [модели отказа]. Здесь мы логически изолируем функцию внешней отправки от остальной части кодовой базы и возлагаем нагрузку на потенциально неудачные транзакции на конечного пользователя, поскольку именно он вызывает функцию вывода.
2. Повторное участие
Смарт-контракты Ethereum вызывают и используют коды из других внешних контрактов, и для этого контракты должны отправлять внешние запросы. Эти внешние вызовы уязвимы и подвержены атакам, одна такая атака произошла недавно в случае взлома DAO.
Уязвимость
Злоумышленники проводят такие атаки, когда контракт отправляет эфир на неизвестный адрес. В этом случае злоумышленник может создать контракт на внешнем адресе, который содержит вредоносный код в резервной функции, и этот вредоносный код будет вызываться, когда контракт отправляет эфир на этот адрес.
Факт: Термин «повторная входимость» возник из-за того, что, когда внешний вредоносный контракт вызывает функцию через уязвимый контракт, а затем путь выполнения кода «повторно входит» в нее.
Рассмотрим пример ниже: это хранилище Ethereum, которое позволяет вкладчикам снимать только 1 эфир в неделю.
контракт EtherStore {
uint256 публичный вывод лимита = 1 эфир;
отображение (адрес => uint256) public lastWithdrawTime;
отображение (адрес => uint256) публичных балансов;
function depositFunds () external payable {
балансирует [msg.sender] + = msg.value;
}
функция removewFunds (uint256 _weiToWithdraw) public {
требуется (остатки [msg.sender]> = _weiToWithdraw);
// ограничить вывод
требуется (_weiToWithdraw <= ограничение вывода);
// ограничиваем время, разрешенное для вывода
требуется (сейчас> = lastWithdrawTime [msg.sender] + 1 неделя);
требуется (msg.sender.call.value (_weiToWithdraw) ());
остатки [msg.sender] - = _weiToWithdraw;
lastWithdrawTime [msg.sender] = сейчас;
}
}
В приведенном выше контракте у нас есть две публичные функции: [depositFunds] и [removeFunds]. [DepositFunds] используется для увеличения баланса отправителя, тогда как [removewFunds] указывает сумму, которую нужно снять. В этом случае будет удачным, если выводимая сумма будет меньше 1 эфира.
Ловушка здесь кроется в линии [17], где происходит перенос эфира. Злоумышленник может создать вредоносный контракт с адресом контракта [EtherStores] в качестве единственного параметра конструктора. Это сделает [etherStore] общедоступной переменной и, следовательно, более уязвимой для атак.
Подход QuilllAudit
Мы применяем различные методы, чтобы избежать потенциальных уязвимостей повторного входа в смарт-контракты. Самый первый и лучший способ - это использование встроенной функции [transfer] при передаче эфира на любой внешний контракт.
Во-вторых, важно убедиться, что все изменения логики в переменных состояния должны быть выполнены до отправки эфира из контракта. В примере [EtherStore] строки [18] и [19] должны быть помещены перед строкой [17].
Третий метод также может использоваться для предотвращения повторных вызовов; через введение мьютекса. Это добавление переменной состояния, которая блокирует контракт во время выполнения кода.
3. Видимость по умолчанию
Существуют спецификаторы видимости для функций, которые мы используем в Solidity, и они предписывают способ их вызова. Видимость определяет вызов функций; внешними пользователями, другими производными контрактами, только внутренними или только внешними. Давайте посмотрим, как ошибочное использование спецификаторов видимости может вызвать огромную уязвимость в смарт-контрактах.
Уязвимость
По умолчанию видимость функции [общедоступная], поэтому внешние пользователи могут вызывать функции без определенной видимости. Ошибка возникает, когда разработчики забывают указать видимость функций, которые должны быть закрытыми (или могут вызываться в самом контракте). Например;
контракт HashForEther {
function removeWinnings () {
// Победитель, если последние 8 шестнадцатеричных символов адреса равны 0
требуется (uint32 (msg.sender) == 0);
_sendWinnings ();
}
function _sendWinnings () {
msg.sender.transfer (this.balance);
}
}
Вышеупомянутый контракт представляет собой простую игру с угадыванием адресов. Здесь мы видим, что видимость функций не указана, в частности, функция [_sendWinnings] является [общедоступной] (по умолчанию), поэтому ее можно вызвать через любой адрес, чтобы украсть награду.
Подход QuillAudit
Наша внутренняя команда состоит из опытных разработчиков, которые всегда следуют лучшим практикам аудита, здесь видимость функций должна быть четко указана, даже если они должны быть общедоступными, это следует упомянуть.
4. Защита использования конструкторов
Как правило, конструкторы называются специальными функциями, которые используются для выполнения критических и привилегированных задач при инициализации контрактов. До Solidity [v0.4.22] у конструкторов было то же имя, что и в контракте, который их содержал. Теперь рассмотрим случай, когда имя контракта изменяется на этапе разработки, но имя конструктора остается прежним. Эта лазейка также может предоставить злоумышленникам легкий доступ к вашему смарт-контракту.
Уязвимость
Это может привести к серьезным последствиям, если имя контракта изменено, но имя конструктора не изменилось. Например:
контракт OwnerWallet {
адрес публичного собственника;
// конструктор
функция ownerWallet (адрес _owner) public {
владелец = _владелец;
}
// Отступать. Соберите эфир.
function () к оплате {}
function takew () public {
требуется (msg.sender == owner);
msg.sender.transfer (this.balance);
}
}
В приведенном выше контракте мы видим, что только владелец может вывести эфир, вызвав функцию [remove]. Здесь уязвимость возникает из-за того, что конструктор назван иначе, чем контракт (первая буква другая!). Таким образом, эксплуататор может вызвать функцию [ownerWallet] и авторизоваться как владелец, а затем отозвать весь эфир по контракту, вызвав [remove].
Подход QuillAudit
Мы соблюдаем версию [0.4.22] компилятора Solidity. В этой версии появилось ключевое слово; [конструктор], который требует, чтобы имя функции совпадало с именем контракта.
5. Проверка подлинности Tx.Origin
Здесь [Tx.Origin] - глобальная переменная Solidity, она содержит адрес учетной записи, которая первоначально выполнила вызов или транзакцию. Эту переменную нельзя использовать для аутентификации, так как это делает контракт уязвимым для фишинговых атак.
Уязвимость
Контракты, авторизующие пользователей через переменную [tx.origin], подвергаются внешним атакам, вынуждающим пользователей выполнять аутентифицированные действия с ошибочным контрактом. Рассмотрим пример ниже:
контракт Phishable {
адрес публичного собственника;
конструктор (адрес _owner) {
владелец = _владелец;
}
function () external payable {} // собираем эфир
function removewAll (адрес _recipient) public {
требуется (tx.origin == владелец);
_recipient.transfer (this.balance);
}
}
Здесь, в строке [11], контракт разрешает функцию [RemovewAll] с помощью [tx.origin].
Подход QuillAudit
Обычно мы избегаем использования [tx.origin] для авторизации в смарт-контрактах. Хотя использование [tx.origin] строго не запрещено, у него есть некоторые специфические варианты использования. Мы можем использовать [tx.origin], чтобы запретить внешним контрактам вызывать настоящий контракт, он может быть выполнен с помощью [require] формы [require (tx.origin == msg.sender)]. Это сделано для того, чтобы избежать вызова промежуточных контрактов для вызова текущего контракта, который ограничивает контракт обычными адресами без кода.
Заключительное заключение
Мы всесторонне рассмотрели пять распространенных ошибок языка Solidity. Разрабатывая смарт-контракты, мы не должны забывать, что они неизменны по своей конструкции, а это означает, что после их создания нет возможности исправить исходный код.
Это создает большую проблему для разработчиков, чтобы воспользоваться преимуществами доступных инструментов тестирования и аудита безопасности перед развертыванием.
Обнаружение потенциальных вредоносных угроз для смарт-контрактов и рисков, некоторые из которых мы упомянули выше, выполняется уникальным и надежным способом нашей собственной командой экспертов по аудиту. Мы в QuillAudits прилагаем все усилия к исследованиям в области безопасности, чтобы обновлять ваш контракт с учетом всех методов обеспечения безопасности программного обеспечения, чтобы ваш контракт был в безопасности.
Обратитесь к QuillHash
Благодаря многолетнему присутствию в отрасли, QuillHash поставляет корпоративные решения по всему миру. QuillHash с командой экспертов является ведущей компанией по разработке блокчейнов, предоставляющей различные отраслевые решения, включая DeFi Enterprise. Если вам нужна помощь в аудите смарт-контрактов, не стесняйтесь обращаться к нашим экспертам. здесь!
Следите за QuillHash, чтобы узнать больше
- 11
- Учетная запись
- плюс
- Все
- аудит
- Аутентификация
- разрешение
- ЛУЧШЕЕ
- блокчейн
- Ошибка
- ошибки
- призывают
- случаев
- Вызывать
- вызов
- код
- Общий
- Компания
- контракт
- контрактов
- Текущий
- DAO
- Defi
- Проект
- Застройщик
- застройщиков
- Развитие
- Предприятие
- Ether
- Эфириума
- События
- эксперты
- что его цель
- финансовый
- First
- следовать
- форма
- Бесплатно
- функция
- будущее
- игра
- ГАЗ
- Глобальный
- большой
- мотыга
- здесь
- Как
- HTTPS
- огромный
- В том числе
- промышленность
- IT
- язык
- вести
- ведущий
- линия
- Список
- Совпадение
- Другое
- владелец
- Патчи
- шаблон
- фишинг
- фишинговые атаки
- предписывать
- представить
- частная
- Программирование
- что такое варган?
- тянущий
- исследованиям
- ответ
- ОТДЫХ
- безопасный
- безопасность
- Услуги
- набор
- просто
- небольшой
- умный
- умный контракт
- Смарт-контракты
- So
- Software
- основательность
- Решения
- Область
- успех
- Тестирование
- Источник
- угрозы
- время
- топ
- топ 5
- сделка
- Сделки
- us
- пользователей
- ценностное
- Хранилище
- видимость
- Уязвимости
- уязвимость
- Уязвимый
- неделя
- КТО
- в
- лет