Ссылка скрыта от гостей
Мы знаем, что пароли - отстой.
Если вы этого не понимаете, вбейте в гугл "почему пароли - отстой", и я избавлю вас от нескольких страниц текста.
На протяжении многих лет, веб-сайты требовали от пользователей создавать все более сложные пароли, пытаясь не дать злоумышленнику получить доступ к учетной записи жертвы, путем брутфорса. Каждый сайт имеет свой собственный смехотворный набор правил, в результате чего пароли трудно запоминаются.
Многие предпочитают создать один "хороший" пароль и использовать его для всех своих учетных записей в Интернете. Понятие "хороший" зависит от вашей позиции
Ссылка скрыта от гостей
, но в любом случае результат один - люди используют один и тот же пароль для всех своих аккаунтов.Если оставить кражу пароля в стороне, то это может быть нормально, доверять безопасную передачу и хранение вашего пароля каждому веб-приложению, но дело в том, что они часто
Ссылка скрыта от гостей
. И даже если они не отстают от современных стандартов безопасного хранения, никогда не скажешь, как скоро исследователи сами обнаружат фатальный дефект в хэш-функциях, или когда железо сможет пробрутфорсить какой-то алгоритм за короткое время.Введение в Credential stuffing
В конце концов, хакеры осознали две вещи:
- Каждое веб-приложение хранит пароли по-разному, и некоторые из них делают это таким образом, что восстановление обычного текста становится банальщиной.
- Люди, как правило, повторно используют один и тот же пароль для всех своих учетных записей в Интернете.
Короче говоря, если злоумышленник может украсть ваш пароль с одного сайта, то этот же пароль, скорее всего, можно использовать в другом месте. Еще хуже то, что большинство сайтов принимают адрес электронной почты в качестве действительного логина, тем самым еще больше упрощая атаку - одно письмо, один пароль, и все ваши аккаунты в руках хакера.
Акт кражи учетных данных с одного веб-сайта и попытки их повторного использования на других веб-сайтах в конечном итоге перерастут в так называемую "
Ссылка скрыта от гостей
(с англ. Заполнение учетными данными )". Такие атаки становятся проблематичными, когда используют различные средства защиты, как: двухфакторная или многофакторная аутентификация (2FA / MFA), геолокационное отслеживание и т.д., но даже у них есть свои недостатки (если они вообще есть на веб-сайте).Согласно
Ссылка скрыта от гостей
, опубликованному издательством Akamai, только в 2018 году было зафиксировано около 30 миллиардов попыток атак типа credential stuffing. Трудно найти постоянный источник успеха атаки, но если даже 1% из этих атак окажутся успешными, мы рассматриваем возможность взлома 300 миллионов аккаунтов. В сочетании с тем, что, по словам Акамая, они
Ссылка скрыта от гостей
, и поэтому у нас серьезная проблема.Действия хакеров.
Процесс выполнения этих атак прост:
- Злоумышленник получает (или создает свой собственный) список валидных комбинаций адресов почты и паролей, полученных при утечке данных.
Ссылка скрыта от гостейчасто распространяются в закрытых сообществах.
- Затем злоумышленник использует скрипт или собственное приложение, которое автоматизирует процесс входа с каждой парой учетных данных на различные популярные сайты (Gmail, Facebook, Instagram и т.д.). Иногда они даже автоматизируют процесс размещения вредоносного контента и/или смены пароля аккаунта жертвы, что затрудняет восстановление ее учетной записи.
Эти атаки, как правило, не являются нацеленными на определенного пользователя; злоумышленник просто хочет иметь действительные учетные записи и ему плевать, кому они принадлежат. Украденные аккаунта часто продаются на различных онлайн-маркетов в даркнете.
Защита клиента
Хотя компания Datto уже несколько лет предлагает 2FA в качестве опции, растущая популярность атак credential stuffing даёт понять, что мы несём ответственность за соблюдение политики безопасности от имени наших клиентов и конечных пользователей. Ранее в этом году мы объявили о переходе на обязательную политику
Ссылка скрыта от гостей
для всех аккаунтов Партнерского портала (нашей клиентской платформы). Это позволит гарантировать, что даже если пароль клиента окажется вне игры, злоумышленнику все равно придется пройти 2FA, прежде чем он сможет причинить какой-либо вред.Что, если мы сможем предотвратить атаки credential stuffing, чтобы они стали абсолютно бессмысленными?
Мы придумали несколько идей:
- Вариант №1: Мы могли бы использовать API
Ссылка скрыта от гостей(HIBP) для поиска электронной почты и/или паролей наших клиентов.
- Сопоставление по адресу электронной почты не обязательно означает, что пароль клиента Datto находится в чужих руках.
- HIBP API позволяет искать скомпрометированные пароли, если они находятся в открытом тексте, SHA1 или NTLM форме, но Datto хранит их только в виде хэшей.
- Нам неудобна идея передачи конфиденциальной информации о данных наших клиентов за пределы офиса.
- Вариант #2: Мы можем запустить
Ссылка скрыта от гостейв попытке перебора паролей каждого клиента со списком общих и слабых паролей.
- Вариант #3: Мы можем просто сделать то, что делают хакеры, получив некоторые учетные данные для взлома данных и попробовав их на нашей собственной странице входа.
Используем гибридный подход
После оценки всех инструментов, имеющихся в нашем распоряжении, мы поняли, что можем использовать как учетные данные для взлома данных, так и хэш-пароль bcrypt клиента, чтобы помочь нам:
- Создать нашу собственную базу учетных данных на основе популярных утечек. Использовать те же самые списки, которые используют хакеры, чтобы мы могли предотвратить их использование против нас.
- Найти в базе учетных данных адреса электронной почты клиентов. Поиск адреса электронной почты может дать нулевой или более простой текстовый пароль, связанный с этим адресом.
- Если мы найдем простой текстовый пароль, сравнить его с хэш-паролем клиента Datto. Если они совпадают, то мы знаем, что клиент рискует быть взломанным. Каждый криптовый хэш включает свою соль, немного упрощая эту часть.
- Как только уязвимые клиенты будут идентифицированы, уведомить их и принудительно сбросить пароль по истечении льготного периода. Убедится, что они не пытаются повторно использовать один и тот же пароль.
Первым действием было поиск копий баз паролей, известных как
Ссылка скрыта от гостей
, среди нескольких других. По очевидным причинам, я не буду подробно описывать, как их получить (и, пожалуйста, не спрашивайте). Совокупные списки, как говорят, составляют почти 28 миллиардов украденных учетных записей (большинство из которых были дубликатами, как я позже обнаружил).Списки были упакованы глубоко в рекурсивном лабиринте сжатия различными способами (tar.gz, zip, rar и т.д.). Я не хранил никаких записей во время этой фазы, но вот что я помню:
Многие имена сжатых файлов использовали пробелы, кавычки или нечетные кодировки, что усложняло работу таких инструментов, как tar/unzip/etc. У меня были некоторые трудности с поиском решения, и мне пришлось переименовать/кодировать некоторые из наиболее проблемных файлов, прежде чем я смог их извлечь.
Для безошибочной распаковки потребовался рабочий каталог объемом около 2 ТБ.
Реальные мандаты хранились в файлах различных типов, включая: txt, csv, sql, sqlite, doc, docx, pdf, xls, xlsx и т.д. Также было много других случайных ненужных файлов (exe, dll, com, jpg и т.д.). К счастью, большинство файлов были txt и csv.
Выдача реквизитов
Так как у меня было всего несколько дней, чтобы закончить этот проект, у меня не было времени проанализировать и переварить каждый отдельный список. Я выбрал подход 80/20.
Я подумал, что, так как большинство файлов были txt и csv, то они, скорее всего, будут содержать учетные данные в шаблоне: <email><delimiter><password or hash>
Скорее всего, это было бы неправильно для таких вещей, как SQL дампы, но я случайно отобрал достаточно файлов, которые придерживались этой формы, что бы не останавливаться на этом шаге.
Используя grep и немного свободного регекса, я рекурсивно извлекал все, что соответствовало вышеуказанному шаблону:
grep -arihE -o '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}[,:;\s].*' ./ > list-1
-a: Обратиться с бинарными файлами как с текстом (помогает исправить несколько ошибок).
-r: Рекурсивное чтение всех файлов под каждой директорией
-i: Игнорировать случай
-h: Сгруппировать имена файлов на выходе
-E: Расширенный регекс
-o: Выводить только совпадающие сегменты, а не всю линию
Сам шаблон регекса является упрощенным способом сопоставления на любой строке, которая следует за формой:
<email><comma|colon|semicolon|space><any number of characters>
Делая это таким образом, я также получил нерегулярные и непечатаемые символы, которые я должен был бы разобрать позже.
Нормализация данных
Затем я использовал sed, чтобы осуществить несколько трансформаций: Преобразуйте все двоеточия, точки с запятой и пробелы в запятые для единообразия. Это также приготовит список для импорта в базу данных SQLite.
sed -e "s/[\:\;[[:space:]]/\,/g" -e "s/\,\{2,\}/\,/g" -e "s/\"//g" -e "s/'//g" -e "s/[^[:print:]\n]//g" list-1 > list-2
- Сложите несколько последовательных запятых в одну запятую. Множество последовательных запятых было основным артефактом первого шага. Обратите внимание, что это также может быть выполнено с помощью: tr -s ','.
- Удалить двойные и одинарные кавычки. Не спрашивайте, почему я разделил их, я не знаю.
- Удалите непечатаемые и символы новой строки. Это важно, потому что в противном случае будут тысячи дублирующих друг друга записей, которые различаются только на основе невидимых символов управления.
На данный момент список содержит строки в форме:
<email><comma><a string of text>
Остались две проблемы, обе из которых были решены с помощью awk:
awk -F ',' '{ split($0, a, ","); print tolower(a[1])","a[2] }' list-2 > list-3
- Разделите строку на массив (используя запятую в качестве разделителя), и конвертируйте адрес электронной почты в нижний регистр. Это помогло свернуть дубликаты записей, предотвратив различное обращение с fake@fake.com,password123 и FAKE@fake.com,password123.
- Сохраняйте только первый и второй элементы массива, отбрасывая остальные. Это предотвратило ошибки " too many columns " при импорте списка в базу данных SQLite.
После этого любые строки, которые не следовали формату <email><comma><password>, становились для меня искаженными и бесполезными, но, по крайней мере, не вызывали никаких проблем при импорте SQLite. Я также предположил, что письма и пароли сами по себе не содержат запятых, но обнаружил, что сайты очень редко разрешают подобное.
Далее я отсортировал и унифицировал список вывода. Я использовал параметр -T, чтобы установить пользовательскую рабочую директорию, которую я рекомендую в любое время, когда вы думаете, что у вас закончится дисковое пространство (по умолчанию это /tmp на диске операционной системы). Эта операция может занять несколько дней или недель, поэтому лучше всего выполнить ее в screen/tmux или распараллелить каким-либо другим способом:
sort -u -T ./tmp/ list-3 > credentials.csv
Общий размер до нормализации: 816 ГБ
Общий размер после нормализации: 103 ГБ
Общее количество мандатов после нормализации: 3,4 млрд.
Создание базы данных SQLite
Я хотел создать простую схему, которая бы выполнила три вещи:
- Позволить мне запросить адреса электронных почт как можно быстрее.
- Предотвратить вставку пустых/неудаленных email’ов или паролей.
- Предотвращение вставки дубликатов email’ов/паролей.
SQL:
create table credentials (
email text not null,
password text not null,
constraint uc_credential unique(email, password) on conflict ignore
);
create index credentials_email_index on credentials (email);
Импорт списка учетных данных был так же прост, как:
Код:
sqlite> .mode csv
sqlite> .import ./credentials.csv credentials
Хоть credentials.csv и весил всего 103 Гб, сама база данных SQLite была размером в 396 Гб. Это было в основном результатом индексирования почтового столбца.
Взлом хэшей
Все, что осталось сделать, это запросить базу учетных данных для каждого клиентского email’a и проверить, соответствует ли любой из полученных паролей клиентскому при хэшировании. Библиотека bcrypt на Python делает это тривиальным, предоставляя функцию checkpw, позволяющую проверять обычный текстовый пароль на соответствие заданному хэшу bcrypt.
Весь процесс взлома был выполнен с помощью простого скрипта на Python:
Python:
#!/usr/bin/env python3
import bcrypt
import csv
import sqlite3
db = sqlite3.connect('credentials.sqlite3')
c = db.cursor()
# Assumes csv file formatted as <email>,<hash>
with open('customer-emails-and-hashes.csv', 'r') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
next(csv_reader) # Skip header row
for row in csv_reader:
customer_email = row[0].lower()
if customer_email:
potential_passwords = []
for plaintext_password in c.execute('SELECT password FROM credentials WHERE email = ?', (customer_email,)):
if plaintext_password:
potential_passwords.append(plaintext_password[0])
if potential_passwords:
customer_hash = row[1]
for plaintext_password in potential_passwords:
if bcrypt.checkpw(plaintext_password.encode('utf-8'), customer_hash.encode('utf-8')):
print(f'{customer_email} : {customer_hash} : {plaintext_password}')
break
db.close()
Окончательные результаты, последующие размышления и будущие улучшения
Мы можем получить статистику наихудшего случая, используя электронные адреса @example.com. Эти адреса имеют десятки соответствующих текстовых паролей, что должно значительно снизить скорость нашего взлома.
Взлом этих хэшей на Intel i5-4460 занял около двух секунд на хэш, что теоретически составляет около 43 000 хэшей в день. На самом деле, большинство адресов электронной почты имеют только несколько паролей, связанных с ними (если таковые имеются), что означает, что процесс будет намного быстрее по сравнению с реальными данными.
Запуск этого скрипта против десятков тысяч наших клиентов занял всего около часа. Общий коэффициент успешности составил около 0.56% - несколько сотен клиентов в нашем случае. Мы предупредили уязвимых клиентов о наших исследованиях и принудительно сбросили пароль после льготного периода.
Хотя первоначально предполагалось, что это будет быстрое, легкое и одноразовое испытание, позже я реализовал долгосрочный потенциал построения профессионального внутреннего сервиса из этой концепции. Полнофункциональное приложение могло бы включать в себя:
- Аутентифицированный веб-интерфейс API: Позволяет внутренним службам вашей компании идентифицировать клиентов, пытающихся использовать скомпрометированный пароль. Если ваша база данных поддерживается в актуальном состоянии, это поможет вырубить проблему на корню.
- Импорт, экспорт и удаление списка нарушений: Предоставить управление данными для различных баз данных и типов файлов. Вы можете включить метаданные и журнал изменений для каждого импорта, что позволит вам отслеживать происхождение учетных данных.
- Поддержание распространенных типов хэшей и методов «посолки»: Позволит пользователям указывать хэш-функцию (bcrypt, md5 и т.д.), а также положение «соли» в процессе взлома.
- Параллельное взламывание и повышение эффективности: Процесс взлома не занимает слишком много времени, но его можно улучшить с помощью GPU, многопоточности или интеграции с хэш-памятью.
Профилактика
На сегодняшний день можно утверждать, что лучшая профилактика от credential stuffing - это ее использование:
-
Ссылка скрыта от гостей, с уникальным паролем для каждого сайта.
- 2FA/MFA, для каждого сайта.
Кроме того, я бы порекомендовал следить за своими адресами электронной почты,
Ссылка скрыта от гостей
на функцию "Уведомить меня" (ссылка в верхней части главной страницы). Они будут высылать вам сообщения по электронной почте всякий раз, когда ваш адрес будет связан с дампом данных, и даже будут содержать подробную информацию о том, какого рода информация была раскрыта. Стоит отметить, что многие менеджеры паролей включают эту функцию и могут автоматически запрашивать API HIBP от вашего имени.Спасибо за внимание!
Последнее редактирование модератором: