Solidity. Смарт контракты и аудит – Telegram
Solidity. Смарт контракты и аудит
2.62K subscribers
246 photos
7 videos
18 files
547 links
Обучение Solidity. Уроки, аудит, разбор кода и популярных сервисов
Download Telegram
Задача на день

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

Уверен, мы уже все натренировались с задачами ранее, поэтому в решении я буду просто давать наводку, без примера кода.

Решение

Посмотрите на модификатор и его условия вначале. Затем на функцию statcall(). Вспомните, как можно передать функцию в низкоуровневых вызовах.

#task
Задача с собеседования

Вчера был на паре зарубежных собеседований на должность аудитора смарт контрактов. Вопросы довольно однообразные: опыт работы, знание Solidity и уязвимостей, общие принципы эксплойта, работа defi и т.д.

В большой минус работает то, что у меня пока нет проектов в web3, которые можно показать. Так же как и нет успешных bug bounties. Тем не менее, опыт в задачах Ethernaut и DVD был оценен.

На одном из собеседований была предложена задача из двух частей. В первой нужно было "взломать" контракт и добавить свой адрес в массив. Подтверждением служил хеш транзакции на Etherscan. Во второй - создать подписанное сообщение со своим именем и адресом кошелька, с которого был взлом.

Предлагаю вам самим решить задачу. В этот раз без подсказок. И, пожалуйста, не выкладывайте свое решение в комментариях. Так меня попросили в компании.

Итак, целью задачи является добавление своего адреса в массив winners.

contract Challenge{

address[] public winners;
bool lock;

function exploit_me(address winner) public{
lock = false;

msg.sender.call("");

require(lock);
winners.push(winner);
}

function lock_me() public{
lock = true;
}
}

Задача достаточно легкая. Постом чуть позже расскажу, как создать подписанное сообщение простым способом. Такого на канале еще не было.

#task
👍4
Как создать подписанное сообщение?

Я еще не так хорошо знаком с подписанными сообщениями вне сети (на английском off-chain signed message), но пару слов сказать о них стоит.

Подобные сообщения используются для подтверждения владельца, платежа, авторизации и т.д. Вся фишка в том, что вы создаете такое сообщение вне сети Эфира и можете позже отправить его. Или переслать другому пользователю для исполнения, типа как мета-транзакция.

По сути, в задаче требовалось создать сообщение с текстом содержащим мое имя и подписать его адресом кошелька, с которого была проведена транзакция-решение для контракта из предыдущего поста.

Как я это сделал?

Для начала создать в Ремиксе небольшой контракт с двумя функциями, которые позволяют зашифровать мое сообщение с именем.

function getHash(string memory str) public pure returns (bytes32) {
  return keccak256(abi.encodePacked(str));
}

function getEthSignedHash(bytes32 _messageHash) public pure returns (bytes32) {
  return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash));
}  

Затем получил хеш своего имени через getHash(), а также конечный хеш в getEthSignedHash().

После этого нужно зайти в браузер, где у вас установлен Метамаск, с которого деплоили контракт и проводили транзакцию, в моем случае Хром.

Далее нажимаем f12 или правую кнопку мыши, выбирая Посмотреть код. Откроется консоль Хрома. Переходим на вкладку Console.

Прямо во вкладке ставим курсор и прописываем:

hash = "вставляем наш хеш из функции getEthSignedHash()" 

Это сохранит в переменную наш хеш. Далее прописываем эту строку:

ethereum.enable().then(console.log)

Откроется Метамаск и нужно будет подтвердить действие.

В консоли отобразится ваш адрес кошелька. Сохраните его в переменную account, как сделали это с hash.

Затем прописываем эту строку:

ethereum.request({method: “personal_sign”, params: [account, hash]}).then(console.log)

Снова появится окошко Метамаска с предложением о подписании сообщения. Подписываете его, нажимая sign.

В консоли отобразится хеш вашего подписанного сообщения. Это то, что нам нужно.

Теперь этот хеш можно переслать другому человеку, подтверждая, что кошелек действительно принадлежит нам.

Надеюсь, эта информация была вам полезна.

#sign #message #metamask
👍1
Передача параметров в struct

На форуме увидел вопрос-ответ на тему передачи параметров для struct из одного контракта в другой. Сам еще не пробовал, но решил сохранить себе и поделиться тут.

Итак, у нас есть контракт и struct, например:

interface IExternalContract{

struct one {
address user;
unit amount;
}

function callOne(one[] calldata data) external;

}

и в него из другого контракта нужно передать информацию.

Сделать можно так:

В нужном контракте дублирует struct и передаем его аргументы с помощью abi.encodeWithSignature:

contract YourContract {

  address public contractAddr;

  constructor(address _contractAddr) {

    contractAddr = _contractAddr;

  }

  function callOne(
IExternalContract.one[] calldata data) public {
    IExternalContract(contractAddr).callOne(data);
}
}

Кто-то уже имел дело с передачей инфы в struct? Как справлялись?

#struct
Уязвимости с прокси контрактами

Мы уже встречали несколько задач, где нужно было знать логическую работу прокси контрактов (и transparent, и uups). А сейчас я, на основе этой статьи, перевел список самых популярных уязвимостей.

1. Не инициализированный контракт Логики. Из предыдущих уроков мы знаем, что конструктор может быть только в контрактах прокси, иначе происходят внутренние ошибки и работа контрактов может нарушиться. Поэтому в контракте Логики вместо конструктора используется функция initialize, которая действует по тому же принципу.

Контракт должен быть обязательно инициализирован, иначе это может привести к смене владельца и краже всех средств. Если вы используете библиотеку Initializable.sol от openzeppelin, то проверьте булеву переменную _initialized. Если она вернет вам 0 / false, то контракт еще не инициализирован.

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

3. Function Clashing Vulnerability. Сложно перевести дословно тут, но суть заключается в том, что селекторы в функциях (те, которые 4 первых байта) могут быть одинаковыми в контрактах прокси и логики. Эту часть уязвимости можно проверить специальными инструментами, типа Slither.

4. Metamorphic Contract Rug Vulnerability. Еще одна уязвимость, которую даже не знаю как перевести правильно. Суть ее заключается в процессе создания адреса контракта с create2, который был представлен в хардфорке EIP-1014.

Create2 позволяет деплоить контракт с адресом, который может быть просчитан заранее. К слову, простой create так делать не может. Таким образом можно задеплоить контракт с функцией selfdestruct, а затем уничтожить его и задеплоить на тот же адрес новый контракт с новым функционалом.

Вообще, если встретите контракты в сети, которые были созданы с create2, то проверьте их код на наличие selfdestruct() или delegatecall. В случае наличия таковых, контракт может быть создан мошенниками.

5. Delegatecall with Selfdestruct Vulnerability. Тут и так все понятно: допустим, если контракт А имеет функцию delegatecall, а контракт В - selfdestruct(), то есть вероятность уничтожить контракт А и заблокировать всю логику.

6. Delegatecall to Arbitrary Address. Встречается, когда delegatecall передает исполнения из прокси контракта и использует его переменные состояния или другой контекст. Обращайте на это внимание.

7. Проверка на наличие контракта. Когда используется delegatecall, то в нем не существует проверки на наличие контракта, в смысле существует ли он вообще. При этом даже если его нет, вернется true значение! Для этого желательно делать проверку на существование внешнего контракта.

Как мы видим из списка, в работе с прокси контрактами первым делом стоит обращать внимание на три вещи: initialize, delegatecall и слоты памяти. Это основные моменты, где кроются уязвимости.

#proxy #security
👍3
Чуть больше о собеседованиях

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

Итак, пара слов о поиске работы и собеседованиях.

Я ищу работу в зарубежных компаниях: как на сайтах агрегаторах вакансий, так и на linkedIn, так и просто посещая сайты интересующих компаний. Подаюсь в приоритете на аудитора смарт контрактов, во вторую очередь на блокчейн разработчика. В качестве резюме одна страница pdf с описанием скилов и стека разработки.

На данный момент у меня было 3 собеседования вживую. Проходили по скайпу и зуму в вечернее время на английском языке. Спрашивали, в основном, про опыт работы и навыки работы с кодом. Никто не просил писать код в эфире.

Также пара компаний выслала тестовые задания: где-то нужно было найти уязвимости, где-то взломать контракт, где-то дописать код по логике. Все достаточно просто, если чуть посидеть.

На данный момент, предложений пока не получил. Отказов +5.

На что стоит обратить внимание для прохождения собеседования?

1. Стандарты ERC и их уязвимости. Меня спрашивали про ERC20, ERC721 и ERC1155. Как происходит transfer, approve и на что стоит обращать внимание, работая с ними.

2. Прокси контракты. Очень важная часть! Нужно знать про transparent, uups, beacon прокси контракты и их upgradable версии.

3. Openzeppeling. Подключение и настройка.

4. В какой ide работаешь? Далее вопросы про hardhat были.

5. Ethers js и его основные функции: как тестировать контракты.

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

7. Для DAO приложений нужно понимать как происходят голосования и в чем фишка таких контрактов.

Пока что, это основные моменты, которые удалось вспомнить. Если уверены в своих силах, то в резюме лучше не писать Junior, а сразу Blockchain Developer (Auditor), так будет больше шансов, что резюме заметят.

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

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

Приятной недели и легкого обучения!
7👍4
Zero trust и постоянные проверки

Мне сильно импонирует основная идея блокчейна и разработки смарт контрактов, которая основывается на постоянные проверках любых действий и доступов с минимумом доверия к пользователям.

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

Остановитесь и взгляните на код на скрине. Функция позволяет пользователя отменить их транзакции в очереди. Сможете найти там баг? Давайте пройдемся по коду.

Пользователь вызывает данную функцию, которая проходит по массиву транзакций, которые должны быть отменены, одновременно проверяя, что transfer.from и msg.sender сходятся. Затем ставит статус транзакции, как "отменена", переводит токены пользователю и порождает событие. И все бы ничего, если бы не одно "но".

Решение

Тут нет проверки на то, была ли данная транзакцию уже отменена раньше. Другими словами злоумышленник может "залить" в массив одну и туже транзакцию несколько раз, она будет прогоняться через цикл и выводить деньги с контракта.

Подробнее об этом можно прочитать тут. Этот баг был вовремя обнаружен и хакер получил 10 000 в качестве вознаграждения.

Будьте внимательны и проводите больше времени над раздумьем о дополнительных проверках в коде, особенно там, где есть переводы.

#security
👍1
Изучаем Foundry

На канале у Ильи вышел новый урок про Foundry. Это что-то вроде Hardhat, но для написания тестов используется Solidity.

Вот этот видео урок.

Я бы, возможно, пропустил его в рамках своего обучения, так как привык к hh и не видел смыла, тогда, изучать его. Если бы не текущие собеседования.

В рамках одного из них предлагали скачать архив с файлами для проверки контрактов на уязвимости, и что вы думаете? Проект там был создан для foundry. И мне пришлось в скором темпе перекидывать и адаптировать его под hh, чтобы начать работу.

Поэтому, чтобы вам в будущем не "прижало", просто покопайтесь в foundry в ближайшее время и поймите, как там настраиваются проекты. А в следующем посте я напишу, какие у меня возникли трудности с ним.

#foundry #forge
👍1
Возможные проблемы с Foundry

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

Во-первых, это время установки. У меня достаточно слабый ноут и время установки заняло больше часа. Поэтому, если захотите поработать с ним, имейте ввиду, что это может занять у вас продолжительное время.

В видео уроке хорошо объясняются базовые моменты, и упоминается, что перед установкой Foundry на Windows, нужно будет скачать и установить еще две программы.

Вообще, как оказалось, Windows достаточно дырявая система для работы со смарт контрактами, тестами и взломами. Но не об этом сейчас.

Во-вторых, скачивание пакетов (типа npm). Тут это работает немного по другому. Тут вы скачиваете git репозиторий. Причем не по ссылке, а именно в команде указываете название репозитория на GitHub, например

forge install foundry-rs/forge-std

В-третьих, я еще до конца не разобрался, но, когда вам присылают архив с проектом в Foundry, то вас скорее всего потребуется установить пакеты для его работы. Пример такого проекта на скрине.

В моем есть remappings.txt, где прописаны следующие строки:

@openzeppelin/=lib/openzeppelin-contracts/contracts/
@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
@chainlink/=lib/chainlink/

Это те контракты, которые используются в примерах и которые нужно установить к себе. Как это сделать напрямую из файла я еще не разобрался.

А с командой, как показано в документации:

forge install foundry-rs/forge-std (это пример команды)

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

fatal: not a git repository (or any of the parent directories): .git

которая исправилась у меня через git init, и вторая:

This command requires clean working and staging areas, including no untracked files. Modify .gitignore and/or add/commit first, or add
the --no-commit option.

которая решается удалением из папки lib пустой одноименной директории и последующей командой:

forge install foundry-rs/forge-std --no-commit

После этого в lib создастся папка с нужными контрактами и настройками.

Я еще разбираюсь с остальными файлами, и если будут возникать ошибки, отпишусь здесь.

Буду рад советам, если кто-то уже работал с Foundry и может поделиться секретами быстрой настройки и установки.

#foundry #forge
👍4
Задача от Immunefy

Вчера в Дискорде канале Immunefy выложили прекрасную задачу, над которой я предлагаю подумать и вам.

Что же не так с этим кодом?

Решение

Это прекрасный пример возможности frontrun атаки с кражей личной подписи пользователя. Мы же все помним, что все транзакции изначально попадают в мемпул, откуда их добавляют валидаторы в блокчейн?

Так вот, хакер может стащить вашу подпись транзакции из мемпула, создать свою транзакцию, в которой с вашего счета сделать депозит к себе. И с помощью увеличенной платы газа, его транзакция пройдет быстрее вашей.


Все таки у них прикольные задачи! Там еще есть несколько на канале, постепенно разберем их все.

#security #task
👍2
Кратко о Beacon Proxy

Пару раз в контрактах на аудит встречал интеграции openzeppelin с Beacon Proxy. Я знал и работал с transparent и uups, но про beacon ничего не знал. Давайте поговорим о нем немного.

Beacon Proxy - это такой прокси паттерн,в котором несколько прокси контрактов ссылаются на один контракт Исполнения. Например, у вас есть несколько прокси контрактов, и все они работают с одним контрактом, в котором выполняются все действия. Если бы мы использовали uups или transparent, но нам вручную бы пришлось обновлять контракт Исполнения в каждом прокси, что не очень удобно и может занять некоторое время.

С Beacon Proxy мы можем обновить ссылку на адрес контракта Исполнения только в нем, и все остальные прокси контракты "подцепят" это.

Другими словами Beacon Proxy это некая прослойка между прокси контрактами и контрактом Исполнения.

Информации про работу с beacon не так много, все в основном ссылаются на обычные прокси, но есть неплохой пример его использования в этой статье. Для новичком может быть слегка сложновато, особенно с js файлом. Поэтому стоит все повторить в своем редакторе, прописав строчку за строчкой.

#proxy #beacon
🔥3
Нужен совет сообщества

Хочу посоветоваться с вами по поводу материалов на канале.

За все время мы прошли кучу тем по Solidity и блокчейн разработке, узнали о популярных паттернах, разобрали задачи, постигли некоторые нюансы кода. В целом, материала для новичков очень и очень много.

Недавно я решил двигаться в сторону профессии аудитора смарт контрактов и стал все свое время посвящать разборам задач и уязвимостей в коде. Из этих задач я понимаю 95% кода и их логики. Остальные 5% гуглю, и если инфа действительно новая, то делаю посты на канал. И вот, что получается.

Новой информации, на своем пути, я пока встречаю достаточно мало. Делать мейнстримные посты я не хочу. Мне нравится, что канал остается одним из немногих крутых с технической точки зрения.

Поэтому думаю как поступить лучше.

Делать посты реже, но добавлять только новую информацию на канал? Типа как, "Как сделать это?", "Как подключить кошелек?", "Как использовать uniswap?" и т.д.

Или временно превратить канал в некий задачник, где выкладывать по несколько постов в день с задачами / кодом с уязвимостями и разбирать их? Я читаю много отчетов по аудиту, разборы кода и задач от компаний для подготовки к собеседованиям, и могу всем этим делиться на канале.

Другими словами вопрос стоит так: делать посты реже только с новой инфой по Solidity и блокчейн разработке или посвятить несколько недель задачам и разборам кода?

Что вы думаете?
По следам вчерашнего поста

Спасибо всем, кто оставил коммент вчера. Я специально подождал сутки, в надежде, что и другие выскажут свое мнение.

Вы правы, нужно делать то, что заводит самого. Будут и задачи, и разборы, и новости, и другие штуковины по смарт контрактам, на которые я натыкаюсь по мере своего обучения, без "удержания" какой-либо конкретной темы.

Всем спасибо! Продолжаем!
Аудиторы будут больше не нужны?

Вчера в твиттере стали появляться все больше сообщений, что был запущен некий AI бот, который определяет уязвимости в смарт контрактах и дает отчет по ним. Пример такого отчета вы можете видеть на скрине, а почитать больше на официальном сайте.

Я хотел поиграться с ним, но сервис не доступен для пользователей из России (регистрация с смс), более того виртуальные номера с VoIP также отсекаются.

Как я понял, код смарт контракта на Solidity прогоняется через бот, и тот отлавливает все популярные уязвимости, сопоставляя их с теми, что уже в его базе. Понятное дело, все шутят, что скоро аудиторы будут не нужны.

Хотя я немного другого мнения.

Даже с учетом того, что уже несколько лет существуют такие крутые инструменты как Slither, Echidna, Manticore и другие, работы у аудиторов не убавилось, также как не прекратились и взломы. А текущей версии бота еще далеко до этих сервисов.

Да и после его совершенствования, где гарантии, что он будет отслеживать кросс-контрактные и кросс-блокчейн уязвимости? Или симулировать логические операции с flash займами и временными отрезками?

Так или иначе подобные сервисы будут крайне полезны для первоначального тестирования смарт контрактов, но полностью заменить человека не смогут в ближайшие 5-10 лет.

#ai #security
👍1
Возможные скамы с NFT. Часть 1

Когда искал информацию по различным уязвимостям и взломам, то нашел репо от одной аудиторской компании Quillhash, в которой сделали подборку популярных обманов в мире NFT. Делаю короткий перевод.

1. NFT Swap Scams. Помимо площадок, где вы можете купить NFT, есть маркетплейсы для их обмена. Скам, в этом случае, происходит, когда мошенник общается с жертвами на популярных каналах (телеграм, дискорд), а затем предлагает обменяться токенам на каком-либо сером сайте. Жертва переводит свой NFT на такой сайт для обмена и теряет его навсегда.

2. "Trojan Horse" NFT. Кратко говоря, это такой токен, который жертва может получить через airdrop, который содержит вредоносный коди и после может вызвать окошко / кнопку / что-то еще для совершения действия пользователем. Действие это может разрешить перевод всех его NFT на адрес мошенника.

3. Impersonation scams. Мошенники выдают себя за службу поддержки сервиса, например Opensea, мониторят форумы, где пользователи пишут о своих проблемах. Через диалог с таким пользователями они крадут все токены через фишинг или подписанные транзакции.

4. Rug Pull. Это такой скам, когда мошенники "раздувают" инфо о своем NFT, нагоняют спрос, и сваливают в закат, как только получают крупные суммы от вкладчиков, закрывая проект.

#nft #scam
👍1
Чуть больше о взломе ANKR сегодня

Кто не слышал: сегодня был взломан сервис ANKR и украдено, по разным источникам, 10-20 миллиардов токенов aBNBc. До сих пор идут обсуждения, как это произошло. Пока что вот некоторая доступная информация.

Многие пользователи, в том числе аудиторы из крупных компаний, сходятся на том, что изначально были скомпрометированы приватные ключи ANKR.

Затем хакер несколько раз обновлял прокси контракт (Twitter).

В то время как функция mint() защищена модификатором, хакер вызвал другую функцию 0x3b3a5522, которая позволяла обойти проверки и сминтить токены. (Twitter).

Эти токены предназначались для наград (rewards) пользователей за действия на сервисе, таким образом все оригинальные токены BNB не были задеты, и взлом никак не повлиял на его цену.

Далее он обменял украденные токены на биржах PancakeSwap и ApeSwap на BNB, чем практически опустошил оба пула и задампил цену.

Чуть позже он перевел все на Tornado cash и через мост на Ethereum и обменял часть BNB на USDC.
 
Вот к чему может привести кража приватных ключей.

Остается один вопрос: каким образом это произошло? Некоторые склоняются, что слив ключей произошел в момент обновления сервиса и его кода за несколько часов до взлома (Twitter).

Код контракта можно посмотреть тут.

Далее снова про скамы NFT.

#ankr #break
👍1
Возможные скамы с NFT. Часть 2

5. NFT Duplicity.
Каждый может сминтить дубликат популярных NFT и затем выдавать их за оригинал, вводя доверчивых покупателей в заблуждение. Так и хочется добавить: "Без лоха и жизнь плоха...".

6. Recovery Scams. Были случаи, когда после кражи токена, эта новость проскальзывала в соцсетях и мошенники или их боты писали жертве с предложением восстановить владение токеном. Однако за это придется заплатить. Понятное дело, что ни NFT, ни денег жертва потом не увидит.

7. Wash Trading. Скам происходит за счет быстрого перемещения NFT по адресам (ввод / вывод / перепродажа). Нацелен скорее на на получение какого-либо большого профита, а для наград. Многие площадки дают специальные награды, если пользователи совершают определенные действия внутри маркета.

8. Flash Loans. Мошенники используют займы для манипулирования ценой токенов и быстрой их перепродажи.

9. Spoofing. В точности копирование популярных сайтов (дизайн / логика) для обмана пользователей. При регистрации крадутся данные (секретная фраза, NFT, токены).

10. Ramping the Market. Как я понял, это что-то вроде использования инсайдерской информации для незаконного обогащения за счет распиаренных NFT.

11. "Fake" News. Если кратко, то: "распиарить и кинуть". Мошенники используют соцсети и статьи в популярных сми, чтобы раскрутить токен и смыться с деньгами пользователей. Очень похож на Rug Pull. Не понимаю, почему компания выделила его в отдельный вид.

#nft #scam
Возможные скамы с NFT. Часть 3

12. Bots.
Боты используются для манипулирования ценой ставки на аукционах. Они могут совершать ставки в последние секунды, таким образом выигрывая. Другой способ использования бота, это добавление токена в корзину без его покупки. Таким образом токен временно становится недоступен для покупки другим пользователям.

13. Bugs in Platform. Ошибки во внутренних сервисах маркета может быть использованы мошенниками.

14. Influencers / Shilling. Иногда для привлечения внимания к NFT и накрутке его цены могут использоваться знаменитости. Однако после продажи токена, зведы выходят из проекта, тем самым обесценивая токен в разы.

15. Unlimited Permissions on Token Approval. Когда мы работаем с маркетами, они просят разрешение (approve) на перевод токенов с вашего адреса на любой другой. Иногда такое разрешение дается не на один конкретный токен, а вообще на все. Будьте аккуратны с этим.

P.S. Не уверен, что этот баг актуален в наши дни. Вроде как,  сейчас разрешения даются на конкретный токен и его количество.

16. Rewards not Updated. Пользователи могут неограниченно минтить токены в качестве награды за какое-либо действие. Это скорее ошибка в логике контракта, которая приводит к обесцениванию NFT.

17. Code Exploits. Ошибки в смарт контрактах маркета или других контрактах, с которыми он взаимодействует. 

#nft #scam