Однажды пользователь reddit с ником fitwear достал свой бумажный кошелёк с 9 биткоинами (65000$ по курсу на тот момент), по всем правилам безопасности зашёл с ноутбука с чистой Windows в веб-кошелёк blockchain.info с помощью двухфакторной авторизации, ввёл с клавиатуры номер кошелька и отправил биткоины на свой адрес. Они пролежали там ровно 4 секунды и улетели в неизвестном направлении. В недоумении пользователь написал администрации сайта blockchain.info, где ему ответили, что сделать ничего не могут. Он начал искать описание подобных случаев в интернете, но ничего подобного не нашёл, поэтому создал и тему с описанием ситуации. Его компьютер не мог быть заражен трояном, никто не мог похитить его закрытый ключ (он был напечатан на бумаге), но биткоины всё-таки пропали.
Через некоторое время с адреса, куда ушли биткоины, на известный кошелёк 1FLAMEN6, который является призом за разгадку криптоквеста, поступает пожертвование в 1000$. Автор криптоквеста, coin_artist, пишет об этом в своём твиттере, и там его фолловеры указывают ему, что эти биткоины ворованные. В итоге coin_artist уведомляет у себя о том, что нашёлся владелец украденных биткоинов, и после этого анонимный хакер, укравший деньги, возвращает всю сумму владельцу с объяснением, зачем он это сделал.
Тут начинается самая интересная часть истории. Анонимный хакер выкладывает своё описание произошедших событий. Он описывает, что решил поиграться с поиском зарытых в блокчейне биткоина кладов.
Что такое клады в блокчейне? Кошелёк подписывается закрытым ключом, который является хешем от случайной строки. Эта строка должна быть действительно случайной, так как если кто-то сможет её повторить, он сможет завладеть вашем кошельком. Подойдут броски кубиков или монетки, множество случайных движений мышкой или нажатия клавиш клавиатуры, полученные после очень длительной прогулки по ней кота. В этом случае вероятность, что кто-то другой сможет случайно получить такую же строку, примерно совпадает с вероятностью угадать одну конкретную секунду из всего времени существования вселенной. Но иногда люди случайно и специально выбирают в качестве секретной фразы что-нибудь простое, чтобы это было легко запомнить, или же просто чтобы оставить исторический след в блокчейне. Например, автор указывает кошельки, закрытыми ключами от которых являются разные хешированные фразы Дарта Вейдера, фраза “Это не те дроиды, которых вы ищете” и другие известные цитаты из фильмов, любимых гиками, а также применённые несколько раз хеши слов “Hello”, “Password” (автор указывает, что хеш к ней был применён 1975 раз, вероятно по году рождения владельца). Именно поиском таких кошельков с легко раскрываемыми закрытыми ключами и занимался исследователь. Но пользователь, у которого были украдены 9 биткоинов, получил свой ключ надёжным способом, почему же получилось раскрыть его ключ?
Хакер продолжил свои эксперименты, и попробовал использовать в качестве секретной фразы все существующие открытые адреса кошельков (адрес кошелька - это то, что МОЖНО раскрывать, но, естественно, нельзя использовать в качестве секретной фразы для генерации другого адреса кошелька). Он обнаружил существование более 100 таких кошельков, причём на многих из них недавно осуществлялись переводы. Хакер предположил одно из двух - либо в одной из программ-кошельков допущена ошибка при генерации закрытого ключа, либо же какой-то злоумышленник специально спрятал эту строку в коде, чтобы забирать себе биткоины с “отравленных кошельков”. Эта строка могла бы выглядеть не вызывающей подозрения у других программистов, которые будут читать код, и никто, кроме злоумышленника, придумавшего этот трюк, не знал бы об этом.
Для проверки своей теории, хакер написал бота, который собрал базу из всех хешей публичных кошельков и ждал, пока появится транзакция на один из “отравленных” адресов. Через 48 часов бот сработал, уязвимый кошелёк нашёлся, но хакер забыл протестировать свою программу, и перевод не удался, мимо него пролетели 9,5 биткоинов ($23,000 на момент его экспериментов). Через 15 минут владелец кошелька забрал их сам, а хакер убедился, что об уязвимости никто, кроме него, не знает.
Он отладил своего бота, и оставил перехват только больших сумм, чтобы потом по заявлениям о пропажах найти владельцев кошельков и разобраться, в каком кошельке допущена ошибка. Собственно, так и нашёлся через несколько месяцев (автор пишет, что владелец второго “отравленного” кошелька, с которого он перехватил 2 биткоина, так и не нашёлся) пользователь fitwear. Дальше хакер вернул ему биткоины на нормальный адрес, уведомил bitcoin.info о случившемся (те отписали “у нас всё нормально, кривые ключи сгенерировали не мы”), а сам “ушёл во тьму”, оставив всех разбираться с ситуацией, а авторов кода кошельков, обменников и онлайн-бирж, проверять свой код генерации закрытого ключа.
Дальше достаточно быстро нашлись виновные. Скорее всего,с fitwear произошло следующее. Несколько месяцев назад он воспользовался сервисом bitaddress.org, который позволяет конвертировать один формат записи закрытого ключа в другой ИЛИ же если указан не адрес, то трактует указанный текст, как секретный ключ для генерации нового закрытого ключа. Почему-то код воспринял введённую строку не как адрес кошелька, а как секретную фразу. Это абсолютно то, что и обнаружил хакер - адрес кошелька использован в качестве секретной фразы для генерации другого кошелька! Ошибка авторов кода ценой в 9 биткоинов для того, кто воспользовался их генератором.
Нашёлся и автор кода, которым были сгенерированы другие “отравленные кошельки”. Им оказался автор пхп-шной библиотеки генерации адресов (кто бы мог подумать…) Bitcoin-NoAPI-Shopping-cart. Сколько монет было потеряно из-за него, сосчитать сложнее.
Напоследок, fitwear пожертвовал часть денег, полученных им обратно, в фонд до сих пор неразгаданного криптоквеста. В картинке спрятан ключ от кошелька с 5 биткоинами (~61000$ по текущему курсу). Можете попробовать его разгадать. Правда, судя по описанию разгадки предыдущего квеста от этого автора, для этого надо быть отмороженным савантом.
P.S. А вот и забавный комментарий от чуть-чуть недорешавшего предыдущий квест, из-за ошибке в коде на дельфи.
Проверяйте свой код почаще!