Перейти к основному содержимому
Блокчейн56ГЛАВА 56Чек-лист и отчёт: как сдавать безопасность5 → 1 находка

Чек-лист и отчёт: как сдавать безопасность

Прочитано0%
Квизы0/4
Тренажёрыне пройден0/1
Уровень 1 · Новичок

Зачем это нужно​

Уязвимости разобраны, инструменты запущены. Осталось самое неочевидное: что делать с находками и как о них рассказать.

Список из вывода инструмента — не отчёт. В нём нет главного: что из этого опасно, что «так задумано», и что вы с этим сделали. Ровно про это спрашивают на защите, и ровно здесь видно, понимает человек предмет или просто запустил команду.

В этой главе разбор идёт на нашем собственном контракте — том самом хранилище, которое мы писали, тестировали и разворачивали.

Пять находок в своём контракте​

1. setRate не сообщает о смене ставки missing-events-arithmetic
2. событие отправляется после внешнего вызова reentrancy-events
3. низкоуровневый вызов low-level-calls
4. имя параметра с подчёркиванием naming-convention
5. owner можно сделать неизменяемым immutable-states
ПЯТЬ НАХОДОК В СОБСТВЕННОМ КОНТРАКТЕ — И НИ ОДНОЙ КРАЖИsetRate не сообщает о смене ставкиисправитьowner можно сделать неизменяемымисправитьсобытие после внешнего вызоваисправитьимя параметра с подчёркиваниемисправитьнизкоуровневый вызовобъяснитьпосле правок:5 → 1 находка16 тестов по-прежнемупроходятразбор — не «исправить всё»: у части находок правильный ответ «так задумано, и вот почему»
Пять находок, и ни одна не позволяет украсть деньги — но четыре стоит исправить

Первое наблюдение, ради которого всё это показано: ни одна из пяти не даёт украсть деньги. Контракт писался по правилам из главы про уязвимости — порядок операций правильный, права проверяются, — и анализатор это подтвердил молчанием там, где было бы опасно.

Второе: четыре из пяти всё равно стоит исправить. Не потому, что страшно, а потому, что каждая делает контракт чуть хуже: без события о смене ставки внешние наблюдатели не узнают о ней; событие после внешнего вызова может встать в журнале не туда; неизменяемое поле дешевле читать.

── после правок ──
находок: 5 → 1
тестов проходит: 16 из 16

Осталась одна — про низкоуровневый вызов. Она не исправляется: перевод эфира так и делается. Это находка из третьей корзины.

Три корзины​

Исправить. Настоящая проблема или просто улучшение, которое ничего не стоит. Большинство находок сюда.

Объяснить. Инструмент прав формально, но так задумано. Низкоуровневый вызов вместо transfer — именно этот случай: transfer устарел из-за жёсткого предела газа. Ответ должен быть готов вслух, а не «ну это нормально».

Отклонить. Ложное срабатывание: инструмент не понял контекст. Редко, но бывает — и тогда в отчёте пишут, почему.

Важно

«Исправить всё» — плохая стратегия. Часть находок носит характер «можно и так, и так», и правка ради зелёного вывода иногда портит код. Гораздо ценнее короткий список из двух-трёх пунктов «оставлено сознательно, потому что…».

Отвечено вопросов: 0 из 2
Анализатор нашёл пять вещей в вашем контракте, и ни одна не позволяет украсть деньги. Что это значит?
В какую корзину попадает низкоуровневый вызов вместо transfer?
Отвечено верно: 0 из 2

Как оценивают серьёзность​

СЕРЬЁЗНОСТЬ — ЭТО УЩЕРБ, УМНОЖЕННЫЙ НА ДОСТУПНОСТЬнасколько легко это сделать →ущербденьги уходяткритичнокритичносреднеработа встаёткритичносреднемелочьнеудобносреднемелочьмелочькто угоднопри стечении обстоятельствтолько владелец«теоретически возможно, но только если владелец сам себе навредит» — это не критично
Ущерб по вертикали, доступность по горизонтали — и клетка на пересечении

Серьёзность — не свойство ошибки, а произведение двух вещей: насколько велик ущерб и насколько легко его причинить.

  • Критично — деньги уходят, и сделать это может кто угодно.
  • Средне — либо ущерб меньше (работа встаёт, но средства целы), либо нужно стечение обстоятельств.
  • Мелочь — неудобство, или требуется доступ, который и так всё ломает.

Типичная ошибка новичка — объявлять критичным всё, что теоретически возможно. «Владелец может установить ставку 100 %» — это не уязвимость: владелец и так владелец. А вот «ставку может установить кто угодно» — критично, потому что кто угодно.

Чек-лист по контракту​

Проходят сверху вниз, для каждой функции:

  1. Права. У каждой изменяющей функции есть ограничение? Проверено тестом с запрещённым счётом?
  2. Порядок. Нет вызова наружу до записи в хранилище?
  3. Результаты вызовов. Признак успеха проверен везде?
  4. Начальная настройка. Нельзя вызвать дважды? Нулевой адрес отсекается?
  5. Арифметика. Деление на ноль? Потеря остатка? Блоки без проверок переполнения?
  6. Время и случайность. Ничего важного не решается по метке времени блока и не берётся из блока как «случайное»?
  7. Списки. Нет обхода списка неограниченной длины в изменяющей функции?
  8. Приём эфира. Что будет, если получатель откажется принимать?
  9. События. Каждое изменение состояния видно снаружи?
  10. Обновление. Если есть прокси — раскладка хранилища не съедет? Настройка защищена от повторного вызова?

Чек-лист по интерфейсу​

Про эту половину забывают, а спрашивают и о ней:

  1. Ключей в коде нет. Ни в исходниках, ни в переменных сборки.
  2. Чужие строки вставляются текстом. Адрес, имя токена, подпись операции приходят из сети.
  3. Адрес получателя показывается целиком перед подписью.
  4. Номер сети проверяется перед каждой операцией, меняющей состояние.
  5. Контрольная сумма адреса проверяется при ручном вводе.
  6. Кнопка выключается на время операции.
  7. Отказ пользователя не показывается как ошибка.
  8. Отказ контракта переводится на человеческий язык.

Из чего состоит находка​

ИЗ ЧЕГО СОСТОИТ ОДНА НАХОДКАгдеVault.sol:33, функция withdraw()чтособытие отправляется после внешнего вызовачем грозитпри повторном входе порядок событий в журнале перепутаетсясерьёзностьнизкая: деньги не затрагиваются, но история становится невернойкак чинитьперенести emit выше вызова; правка в одну строкунаходка без «чем грозит» и «как чинить» — это не находка, а строчка из вывода инструмента
Пять строк: где, что, чем грозит, насколько серьёзно, как чинить
### С-03. Событие отправляется после внешнего вызова

**Где:** `Vault.sol:33`, функция `withdraw()`
**Что:** `emit Withdrawn(...)` стоит после `msg.sender.call{value: amount}("")`
**Чем грозит:** при повторном входе порядок событий в журнале перепутается;
внешний наблюдатель увидит операции не в том порядке, в каком они произошли
**Серьёзность:** низкая — средства не затрагиваются
**Как чинить:** перенести `emit` выше вызова
**Статус:** исправлено, тесты проходят

Находка без «чем грозит» и «как чинить» — это не находка, а строчка из вывода инструмента. Именно эти две части показывают, что вы поняли проблему, а не скопировали её.

Нажми на часть выражения

Что показывать на защите​

Порядок, который занимает три минуты и закрывает большинство вопросов:

  1. Вывод компилятора — пустой. Одна команда.
  2. Вывод анализатора — и разбор. «Пять находок, четыре исправлены, одна оставлена сознательно, вот почему».
  3. Тест-нападение. «Вот контракт, который пытается опустошить хранилище. Вот тест, где он не смог».
  4. Утверждения со случайными данными. «Никто не может забрать больше, чем внёс — проверено на 256 наборах».
  5. Покрытие. «Сто процентов, непокрытых строк нет».
  6. Чек-лист по интерфейсу. Восемь пунктов, каждый показывается на экране за секунду.

Это не «рассказ про безопасность» — это демонстрация. Разница видна сразу.

Отвечено вопросов: 0 из 2
Что обязательно должно быть в находке кроме места и описания?
«Владелец может установить ставку 100 %» — насколько это серьёзно?
Отвечено верно: 0 из 2

Типичные ошибки​

Прикладывают вывод инструмента как отчёт. Без разбора это выглядит как «мы запустили команду».

Исправляют всё подряд. Часть правок ухудшает код; отсутствие пункта «оставлено сознательно» читается как неумение отличать важное.

Называют критичным всё теоретически возможное. Обесценивает настоящие находки.

Пишут название детектора вместо последствия. «reentrancy-events» не объясняет ничего.

Проверяют только контракт. Половина требований — про интерфейс.

Статус находки пустой. Читается как «не разбирались».

Не готовят ответ вслух. На защите спрашивают именно про оставленные находки.

Отвечено вопросов: 0 из 2
Почему в отчёте пишут последствие, а не название детектора?
Что означает безопасность на чемпионате?
Отвечено верно: 0 из 2

Слова главы​

  • Разбор находок — три корзины: исправить, объяснить, отклонить.
  • Серьёзность — ущерб, умноженный на доступность; не свойство самой ошибки.
  • Критично — деньги уходят, и сделать это может кто угодно.
  • Оставлено сознательно — находка, на которую есть готовый ответ.
  • Строение находки — где, что, чем грозит, насколько серьёзно, как чинить, статус.
  • Последствие вместо названия — не имя детектора, а что случится.
  • Чек-лист контракта — десять пунктов по функциям.
  • Чек-лист интерфейса — восемь пунктов; про них забывают чаще.

Тренажёр: набрать вслепую​

Цель: скорость ≥ 95 зн/мин, точность ≥ 88%

npx hardhat build && npx solhint "contracts/**/*.sol"

На чемпионате​

Отчёт — одна страница. Таблица находок со статусами плюс два-три абзаца про то, что проверено. Больше не читают.

Оставленные находки — с готовым объяснением. Это тот самый вопрос, который задают.

Тест-нападение показывайте первым. Он производит впечатление сильнее всего остального вместе взятого.

Чек-лист интерфейса пройдите вслух сами. Восемь пунктов, минута времени — и половина вопросов снята заранее.

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

Куда углубиться​

  • Публичные отчёты аудиторов — как выглядит настоящий документ на сорок страниц.
  • Оценка серьёзности по общепринятым шкалам — и чем они отличаются друг от друга.
  • Соревнования по поиску уязвимостей — формат, где находки оценивают деньгами.
  • Повторный аудит после правок — почему исправление одной находки иногда создаёт другую.
  • Мониторинг после запуска — что делать, когда контракт уже в сети и уязвимость нашлась.

Сводная проверка по всей главе: 8 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.

Экзамен по блоку «Безопасность»​

Три главы: уязвимости, инструменты, отчёт.

Экзамен по блоку: Безопасность и аудит

Сводная проверка по 3 главам блока: 15 вопросов, 10:00 на всё, по одному вопросу, без возврата. Пересдавать можно сколько угодно раз.

Готовность: экзамены глав сданы 0 из 3. Блок можно сдавать и так, но шанс выше после всех глав.

Куда дальше: проверенные ресурсы​

Видео по теме

ВидеоИнструментарий аудитора смарт-контрактов. Алгыз Иевлев.Positive Events
ВидеоАудит безопасности смарт-контрактов / Дмитрий Мишунин (HashEx)Blockchain Channel
ВидеоРеальное тестовое на аудитора смарт-контрактов Solidity - разбираемБлокчейн-разработка с Юлией Бедросовой
ВидеоHow to Audit a Smart Contract | Can you find the Solidity Security Vulnerabilities?Patrick Collins
ВидеоSmart contract auditor: from zero to hero 👾 Сергей ПрилуцкийCyber Academy

Комментарии

Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.