Проведение пентеста криптопроекта
Пентест криптопроекта — это не стандартный web application pentest плюс Slither. Это многоуровневая работа: смарт-контракты, инфраструктура, frontend, bridges, backend API и социальная инженерия. Ronin Bridge потерял $625M не из-за уязвимости в контракте — из-за компрометации 5 из 9 validator ключей через spear phishing. Эффективный пентест покрывает все векторы атаки.
Scope и методология
Перед началом нужно чётко определить scope. Типичные компоненты криптопроекта:
| Компонент | Векторы атак |
|---|---|
| Смарт-контракты | Reentrancy, flash loan, overflow, access control |
| Frontend dApp | XSS, wallet drainer injection, clipboard hijacking |
| Backend API | Auth bypass, IDOR, rate limiting, key exposure |
| Инфраструктура | Node RPC exposure, private key management, admin panels |
| Bridge / relayer | Replay attacks, signature malleability, validator compromise |
| Discord/Telegram | Bot manipulation, invite phishing, admin account takeover |
Смарт-контракт анализ
Статический анализ
Начало любого пентеста контрактов — автоматизированные инструменты:
# Slither — статический анализатор от Trail of Bits
slither . --print human-summary
slither . --detect reentrancy-eth,reentrancy-no-eth,arbitrary-send-eth
slither . --triage-mode # интерактивный режим для отметки false positives
# Mythril — symbolic execution
myth analyze contracts/Vault.sol --solv 0.8.20
# Aderyn — Rust-based анализатор, быстрее Slither на больших кодовых базах
aderyn .
# 4naly3er — специализирован на gas и security паттернах
Автоматические инструменты находят низко висящие плоды: неверный порядок операций, неиспользуемые return values, reentrancy в очевидных местах. Критические уязвимости они находят редко.
Ручной анализ контрактов
Фокусные области для мануального ревью:
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); // spot price
}
// Правильно: 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 протоколы требуют понимания механики пулов:
// Симуляция flash loan атаки через Foundry
// forge test --match-test testFlashLoanAttack -vvv
function testFlashLoanAttack() public {
// 1. Берём flash loan 1000 ETH
uint256 flashAmount = 1000 ether;
vm.deal(address(attacker), flashAmount);
uint256 priceBefore = target.getPrice();
// 2. Манипулируем пулом — резко покупаем токен
attacker.manipulatePool(flashAmount);
uint256 priceAfter = target.getPrice();
console.log("Price manipulation:", priceBefore, "->", priceAfter);
// 3. Эксплойтим протокол с манипулированной ценой
uint256 profit = attacker.exploit();
// 4. Возвращаем flash loan
attacker.repayFlash(flashAmount);
assertGt(profit, 0, "Attack should be profitable");
}
Frontend безопасность
Wallet drainer injection
Наиболее распространённая атака на dApp пользователей — компрометация frontend для внедрения вредоносных approve транзакций:
Supply chain атака: злоумышленник компрометирует npm пакет (web3-utils, ethers fork) или CDN, из которого подгружается frontend код. Внедрённый скрипт заменяет адрес получателя в транзакциях или подсовывает setApprovalForAll для NFT контракта.
Проверка в пентесте:
- Наличие Subresource Integrity (SRI) хешей для внешних скриптов
- Content Security Policy заголовки
- Lockfile (
package-lock.json,yarn.lock) с integrity хешами - Используемые CDN и их цепочка доверия
Clipboard hijacking: скрипт подменяет адрес в буфере обмена при копировании. Простое DOM injection через XSS.
// Вредоносный скрипт заменяет адрес при копировании
document.addEventListener('copy', function(e) {
e.clipboardData.setData('text/plain', ATTACKER_ADDRESS);
e.preventDefault();
});
Проверяется через анализ CSP заголовков и manual XSS тестирование.
Phishing через typosquatting
Регистрация похожих доменов: uniswap-app.io, app-uniswаp.com (с кириллической 'а'). В пентест входит проверка наличия мониторинга похожих доменов и DNS алертинга.
Инфраструктурный аудит
RPC endpoint безопасность
Многие протоколы держат собственные Ethereum ноды. Проверяем:
# Открыт ли RPC публично?
curl -X POST http://node-ip:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_accounts","id":1}'
# Если возвращает аккаунты — критическая уязвимость
# Нода доступна без аутентификации
# Проверка methods whitelist
curl -X POST http://node-ip:8545 \
-d '{"method":"admin_nodeInfo","id":1}' # должен быть заблокирован
Приватные ключи и секреты
Аудит управления ключами:
- Где хранятся deploy ключи? (HSM, AWS KMS, локальный файл?)
- Кто имеет доступ к multisig? Используется ли hardware wallet?
- Есть ли
.envфайлы с ключами в репозитории (git history)? - Заротированы ли ключи после увольнения сотрудников?
# Поиск секретов в git истории
git log -p --all | grep -E "(private_key|PRIVATE_KEY|mnemonic|MNEMONIC)" | head -20
# TruffleHog — специализированный инструмент
trufflehog git file://. --only-verified
# GitLeaks
gitleaks detect --source . -v
Admin panel exposure
Найти незащищённые admin интерфейсы:
https://project.io/admin
https://project.io/grafana
https://project.io/jenkins
https://project.io/kibana
Проверить: наличие MFA, IP whitelist, rate limiting на login.
Bridge и cross-chain специфика
Bridge контракты — наиболее высокорисковый компонент. Специфические проверки:
Replay attack: одна и та же signed message может быть использована на нескольких чейнах. Подпись должна включать 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: сколько validator ключей нужно скомпрометировать для атаки? Ronin Bridge имел 9 валидаторов, 5 из которых контролировались одной организацией (Axie Infinity / Sky Mavis). Эффективный threshold был 2/2, не 5/9.
Finality assumptions: bridge должен дожидаться финальности блока перед минтингом на destination chain. Для Ethereum — 12+ блоков (PoS finality). Для BSC — больше из-за иного консенсуса.
Отчёт о пентесте
Структура финального репорта:
Critical: прямая потеря средств, возможна эксплуатация немедленно
High: значительный риск при определённых условиях
Medium: логические ошибки, потенциальные DoS векторы
Low/Informational: best practices нарушения, улучшения
Для каждой findings:
- Описание уязвимости
- Proof of Concept (код или шаги воспроизведения)
- Потенциальное impact
- Рекомендации по исправлению
- Статус после ремедиации
Пентест — это snapshot. Протокол меняется, и новый код требует нового аудита. Лучшие протоколы (Uniswap, Aave) проводят аудит каждого значимого обновления и поддерживают bug bounty программу через Immunefi для непрерывного покрытия.







