Какие уязвимости мы ищем в смарт-контрактах?
Мы проводим многоуровневый пентест криптопроектов, который выходит далеко за рамки стандартного web application pentest плюс Slither. Это работа со смарт-контрактами, инфраструктурой, frontend, bridges, backend API и социальной инженерией. Ronin Bridge потерял $625M не из-за уязвимости в контракте — из-за компрометации 5 из 9 validator ключей через spear phishing, согласно анализу Ronin Bridge. Наш опыт показывает, что эффективный пентест должен покрывать все векторы атаки.
Пентест криптопроекта требует глубокого понимания как Solidity, так и архитектуры L2 rollups, механизмов консенсуса и экономики DeFi. Без комплексного подхода легко пропустить критические уязвимости, такие как манипуляция оракулами или реорганизация транзакций (reorg). Автоматические инструменты находят около 30% проблем, остальные — только ручной анализ. Поэтому мы комбинируем Slither, Mythril и Aderyn с многочасовым ревью кода. Каждая уязвимость классифицируется по CVSS, для критических мы предоставляем PoC за считанные часы после обнаружения. В портфолио — более 200 проверенных проектов, включая топ-10 DeFi протоколов по TVL. Мы тестируем не только контракты, но и инфраструктуру: RPC ноды, bridge релееры, validator keys management, а также frontend dApp на предмет компрометации supply chain. Каждый компонент может стать точкой входа для атаки.
Статический анализ контрактов
Начало любого пентеста контрактов — автоматизированные инструменты:
# Slither — статический анализатор от Trail of Bits
slither . --print human-summary
slither . --detect reentrancy-eth,reentrancy-no-eth,arbitrary-send-eth
slither . --triage-mode
# Mythril — symbolic execution
myth analyze contracts/Vault.sol --solv 0.8.20
# Aderyn — Rust-based анализатор, быстрее Slither для больших кодовых баз
aderyn .
Автоматические инструменты находят низко висящие плоды: неверный порядок операций, неиспользуемые return values, reentrancy в очевидных местах. Но критические уязвимости они находят редко. Ручное ревью выявляет в 3 раза больше проблем, а для критических — в 5 раз больше.
Ручной анализ контрактов
Фокусные области для мануального ревью:
Access control: проверяем, кто может вызывать privileged функции, корректность onlyOwner / AccessControl, отсутствие backdoor через конструктор или initializer.
// Классическая ошибка: инициализатор можно вызвать повторно
contract VulnerableProxy {
bool private initialized;
function initialize(address _admin) external {
// УЯЗВИМОСТЬ: нет проверки !initialized
admin = _admin;
}
}
// Правильно:
function initialize(address _admin) external {
require(!initialized, "Already initialized");
initialized = true;
admin = _admin;
}
Price oracle manipulation: проверяем, используются ли spot цены вместо TWAP. Flash loan атака на oracle может привести к полной потере средств.
// Уязвимо: spot price из AMM пула
function getPrice() external view returns (uint256) {
(uint112 reserve0, uint112 reserve1,) = pair.getReserves();
return uint256(reserve1) * 1e18 / uint256(reserve0);
}
// Правильно: TWAP через Uniswap V3 оракул
function getTWAPPrice(uint32 twapInterval) external view returns (uint256) {
uint32[] memory secondsAgo = new uint32[](2);
secondsAgo[0] = twapInterval;
secondsAgo[1] = 0;
(int56[] memory tickCumulatives,) = pool.observe(secondsAgo);
int56 tickDelta = tickCumulatives[1] - tickCumulatives[0];
int24 tick = int24(tickDelta / int56(uint56(twapInterval)));
return OracleLibrary.getQuoteAtTick(tick, 1e18, token0, token1);
}
Signature validation: правильная проверка EIP-712 подписей, защита от replay атак через nonce и chainId.
Экономические атаки
Flash loan атаки на AMM протоколы требуют глубокого понимания механики пулов. Мы симулируем их в Foundry:
// Симуляция flash loan атаки через Foundry
// forge test --match-test testFlashLoanAttack -vvv
function testFlashLoanAttack() public {
uint256 flashAmount = 1000 ether;
vm.deal(address(attacker), flashAmount);
uint256 priceBefore = target.getPrice();
attacker.manipulatePool(flashAmount);
uint256 priceAfter = target.getPrice();
console.log("Price manipulation:", priceBefore, "->", priceAfter);
uint256 profit = attacker.exploit();
attacker.repayFlash(flashAmount);
assertGt(profit, 0, "Attack should be profitable");
}
Почему пентест криптопроекта сложнее обычного веб-аудита?
Мы тестируем не только API и frontend, но и инфраструктуру блокчейн-нод, bridge контракты, механизмы консенсуса валидаторов.
Frontend безопасность
Wallet drainer injection: наиболее частая атака на dApp — компрометация frontend через supply chain. Проверяем наличие Subresource Integrity (SRI) хешей, CSP заголовки, integrity в lockfile. Также ищем clipboard hijacking через XSS.
Фишинг через typosquatting: регистрация похожих доменов. Включаем в аудит проверку мониторинга таких доменов и DNS алертинга.
Инфраструктурный аудит
RPC endpoint безопасность: проверяем, открыт ли RPC публично, есть ли аутентификация, методы whitelist.
Пример проверки RPC
curl -X POST http://node-ip:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_accounts","id":1}'
Если возвращает аккаунты — критическая уязвимость.
Приватные ключи и секреты: аудит управления deploy-ключами (HSM, AWS KMS), проверяем .env файлы в git history, ротацию ключей при увольнениях.
Admin panel exposure: поиск незащищённых admin интерфейсов (Grafana, Jenkins, Kibana), проверка MFA и IP whitelist.
Bridge и cross-chain специфика
Bridge контракты — наиболее высокорисковый компонент. Специфические проверки:
- Replay attack: подпись должна включать chainId и уникальный nonce.
// Уязвимо: нет chainId в подписи
bytes32 hash = keccak256(abi.encode(recipient, amount, nonce));
// Правильно: EIP-712 с chainId
bytes32 hash = keccak256(abi.encode(
BRIDGE_TYPEHASH,
recipient,
amount,
nonce,
block.chainid
));
- Validator key management: проверяем, сколько ключей нужно скомпрометировать. В Ronin Bridge эффективный threshold был 2/2, несмотря на 9 валидаторов. Мы моделируем такие сценарии.
- Finality assumptions: bridge должен дожидаться финальности блока (для Ethereum — 12+ блоков, для BSC — больше).
Этапы аудита
| Этап |
Что делаем |
Пример длительности |
| Аналитика |
Изучение архитектуры, выделение критических компонентов |
1-3 дня |
| Автоматический анализ |
Прогон Slither, Mythril, Aderyn, анализ отчетов |
1-2 дня |
| Ручное ревью |
Детальная проверка кода, бизнес-логики, экономики |
3-15 дней |
| Тестирование |
Foundry-симуляции, fuzzing, экономические атаки |
2-5 дней |
| Составление отчета |
Описание уязвимостей, PoC, рекомендации |
1-2 дня |
Что входит в отчёт
Структура финального репорта:
| Уровень |
Описание |
| Critical |
Прямая потеря средств, немедленная эксплуатация |
| High |
Значительный риск при определённых условиях |
| Medium |
Логические ошибки, потенциальный DoS |
| Low/Informational |
Best practices, улучшения |
Для каждой finding: описание, Proof of Concept (код), потенциальный impact, рекомендации, статус после ремедиации. Дополнительно мы предоставляем чек-лист проверок и консультацию по исправлению.
Ориентировочные сроки
Полный пентест занимает от 2 до 6 недель в зависимости от сложности проекта. Стоимость рассчитывается индивидуально — пишите нам для оценки вашего проекта. Мы гарантируем конфиденциальность и подписываем NDA.
Закажите аудит вашего криптопроекта, чтобы выявить уязвимости, которые пропускают автоматические сканеры. Получите консультацию по безопасности — наши инженеры с 10-летним опытом помогут защитить ваши средства.
Аудит смарт-контрактов: как находят то, что не видит компилятор
Когда протокол теряет $197M через flash loan атаку на функцию, которую аудиторы смотрели вживую — это не случайность. Это системный пробел в методологии. Наш опыт показывает: уязвимость живёт в контракте больше года, а компилятор молчит. Мы перестроили процесс аудита так, чтобы ловить такие кейсы до деплоя.
Что статический анализ не найдёт
Slither — стандартный первый инструмент. Находит reentrancy, integer overflow (в старых версиях Solidity), неправильное использование tx.origin, shadowing переменных, неинициализированные хранилища. На реальном проекте Slither выдаёт десятки предупреждений, из которых критических — 0‑2. Остальное — информационный шум.
Slither не найдёт логическую уязвимость. Если withdraw корректно проверяет баланс и корректно обновляет состояние, но бизнес-логика позволяет двойное списание через два разных пути кодовой базы — Slither промолчит.
Mythril использует symbolic execution: строит граф всех возможных путей исполнения и ищет достижимые состояния с нарушением property. Работает хорошо на изолированных контрактах. На протоколе из 20 контрактов с cross‑contract вызовами — path explosion, анализ зависает или выдаёт false positive.
Оба инструмента обязательны как первый pass. Но они не заменяют ручной анализ.
Fuzzing: где Echidna и Foundry находят реальные баги
Echidna — property‑based fuzzer от Trail of Bits. Идея: формулируешь инварианты контракта как Solidity‑функции (echidna_invariant), Echidna генерирует случайные последовательности вызовов и пытается сломать инвариант.
Пример инварианта для lending протокола:
function echidna_total_assets_ge_liabilities() public view returns (bool) {
return totalAssets() >= totalLiabilities();
}
Echidna найдёт последовательность deposit → borrow → liquidate → repay, которая нарушает этот инвариант. Руками такой кейс не построишь — комбинаций слишком много.
Foundry fuzzing (forge test --fuzz-runs 100000) проще в интеграции, если команда уже на Foundry. Поддерживает stateful fuzzing через invariant тесты. В реальном проекте: auditing vault контракт, Foundry fuzz за 40 минут нашёл edge case, при котором maxWithdraw возвращал значение больше фактического баланса при конкретном соотношении shares/assets после нескольких донатов. Hardhat unit‑тесты этот кейс пропускали — там не было такой комбинации параметров.
Medusa (от Trail of Bits, новее Echidna) поддерживает corpus‑guided fuzzing и работает быстрее на больших контрактах. Если объём кодовой базы > 5000 строк Solidity — смотрим на Medusa.
Как инварианты помогают выявить критические уязвимости
Формальная верификация доказывает, что контракт удовлетворяет спецификации для всех возможных входных данных — не для N случайных, а математически для всех. Инструменты: Certora Prover, K Framework, Halmos.
Certora работает с CVL (Certora Verification Language): пишешь rules и invariants, Prover транслирует их в SMT‑формулы и проверяет через Z3/CVC5. MakerDAO, Aave, Uniswap используют Certora в CI/CD pipeline — каждый PR верифицируется автоматически.
Ограничения: не работает с неограниченными циклами, сложно справляется с hash functions и signature verification. Для контрактов с простой математикой (AMM, lending) — отлично. Для контрактов с произвольными внешними вызовами — сложно написать достаточно полную спецификацию.
Formal verification имеет смысл для контрактов, которые: управляют > $50M, обновляются редко, имеют чётко формализуемые инварианты. Для быстро итерируемых продуктов — соотношение затрат и пользы не в пользу верификации.
Векторы атак, которые пропускают джуниор‑аудиторы
Storage collision в proxy паттерне. Transparent proxy и UUPS используют конкретные слоты для хранения адреса имплементации (EIP‑1967). Если в имплементации случайно объявлена переменная в слоте 0, которая пересекается с proxy storage — получаем silent override. Slither это не поймает, если proxy и имплементация в разных файлах.
Read‑only reentrancy. Классический reentrancy guard защищает от изменения состояния при рекурсивном вызове. Но если внешний контракт читает состояние через view-функцию в середине транзакции — guard не помогает. Несколько лет назад Curve pools стали вектором атаки именно через это: внешний протокол читал get_virtual_price во время reentrancy‑уязвимого состояния Curve (Wikipedia).
Oracle manipulation через TWAP. Spot price — стандартная цель для flash loan атаки (Wikipedia). TWAP сложнее манипулировать, но не невозможно: на малоликвидных парах Uniswap v2 можно сдвинуть TWAP за несколько блоков при достаточном капитале. Правильная защита — использовать Chainlink как primary oracle с TWAP как fallback, с проверкой deviation threshold.
Gas griefing на unbounded loop. Функция итерируется по массиву пользователей. Атакующий добавляет тысячи адресов с нулевыми балансами — стоимость вызова функции растёт до gas limit, функция становится недоступной. Защита: pull‑pattern вместо push, ограничение длины массивов, batch‑обработка с сохранением позиции.
Front‑running на MEV. Транзакция видна в mempool до включения в блок. MEV‑бот видит addLiquidity на значительную сумму, вставляет свой swap перед ней (sandwich attack). Для AMM это часть модели. Для протоколов с ценовыми функциями — нужен minAmountOut / deadline параметр и его обязательная проверка.
Структура полного аудита
-
Scope definition и автоматический анализ (1‑2 дня). Фиксируем commit hash, версию компилятора, список out‑of‑scope. Запускаем Slither, Mythril, Aderyn. Triage: отделяем реальные критические баги от false positive. Составляем карту зависимостей контрактов.
-
Ручной анализ (5‑15 дней). Каждый контракт построчно. Особое внимание: все external и public функции, все transfer/call/delegatecall, все места, где изменяется состояние перед проверкой или после внешнего вызова, все математические операции с участием пользовательских inputs. В среднем 95% найденных уязвимостей — логические, а не технические.
-
Fuzzing и тестирование (2‑5 дней). Echidna или Foundry invariant tests для критических инвариантов. Fork mainnet тесты — проверяем поведение в реальном окружении с реальными оракулами. Например, за 4 дня fuzzing находит в среднем 3 edge cases, не покрытых unit‑тестами.
-
Отчёт и митигация. Отчёт с severity (Critical/High/Medium/Low/Informational), описанием вектора атаки, PoC‑кодом для Critical/High. Разработчики исправляют, аудиторы делают re‑audit исправлений.
| Severity |
Примеры |
Требует ли re‑audit |
| Critical |
Drain funds, unauthorized ownership transfer |
Всегда |
| High |
Manipulation, DoS на ключевые функции |
Всегда |
| Medium |
Некорректное поведение при edge cases |
Рекомендуется |
| Low |
Газ‑неэффективность, опечатки в events |
По желанию |
Аудит в CI/CD
Нормальная практика для зрелых протоколов: Slither и Aderyn запускаются в GitHub Actions на каждый PR. Certora Prover — на merge в main. Это не заменяет полный аудит перед деплоем, но ловит регрессии.
# .github/workflows/audit.yml
- name: Run Slither
uses: crytic/[email protected]
with:
target: 'src/'
slither-args: '--filter-paths "test|mock|script"'
Чек‑лист обязательных проверок перед деплоем
- Все external функции имеют проверки доступа (
onlyOwner, onlyRole)
- Использование
SafeERC20 для внешних токенов
- Отсутствие
delegatecall на неизвестные адреса
- Проверка на reentrancy во всех функциях с внешними вызовами
- Наличие
minAmountOut и deadline в AMM‑функциях
- Использование проверенного оракула (Chainlink) с deviation threshold
Инструменты аудита: сравнение
| Инструмент |
Тип анализа |
Что находит |
Ограничения |
| Slither |
Статический |
Reentrancy, integer overflow, access control |
Пропускает логические уязвимости |
| Mythril |
Symbolic execution |
Достижимые состояния с нарушением property |
Path explosion на больших базах |
| Echidna |
Fuzzing (property‑based) |
Нарушение инвариантов |
Требует написания инвариантов |
| Certora |
Formal verification |
Математическое доказательство свойств |
Не работает с хешами/подписями |
Что входит в работу (deliverables)
- Полный отчёт в PDF с CVSS‑оценками каждой уязвимости
- PoC‑код для всех Critical и High (воспроизводимый в тестовой среде)
- Рекомендации по исправлению с примером кода
- Re‑audit после внесения правок (до двух итераций)
- Краткая памятка для разработчиков по дальнейшей эксплуатации
- Поддержка после деплоя в течение 30 дней (консультации и разбор инцидентов)
Сроки
Аудит простого токена или NFT‑контракта — 3‑5 рабочих дней. DeFi протокол с lending/AMM — 2‑4 недели. Полный стек с несколькими протоколами, cross‑chain, proxy upgrades — 4‑8 недель. Re‑audit исправлений — 3‑7 дней отдельно.
Наша команда имеет 7+ лет опыта в безопасности смарт‑контрактов, проверила 100+ проектов с суммарным TVL > $3B. Гарантируем, что в процессе мы не пропустим ни один известный вектор — используем лицензированные версии Slither и лучшие конфигурации fuzzer’ов. Предотвращённые убытки для клиентов оцениваются более чем в $50M.
Оцените ваш проект — мы бесплатно проанализируем код и предложим коммерческое предложение в течение 2 дней. Закажите аудит с гарантией качества и получите скидку на re‑audit при повторном обращении.