Как найти все пароли и ключи в большом количестве файлов
Если даже бегло взглянуть на следующие строки:
M5UWx/N-yjuZ Lg-4mBnrhJ! 22j4J6nbnKJRbs
То можно предположить, что это пароли, поскольку это бессмысленные наборы букв и символов, при этом достаточно короткие, чтобы их можно было запомнить или ввести.
Глядя на эти строки:
lxRV/uiC4knZQxyIZxSSlQ2xNlZMjo4km+LnjNiF M3mmbjOlIZr11OZoULqUWyFA1EpOdZAEcmaC64E/Ft9MRfDEYE7qDJm+9ezGQY15== 23ZRA8UBSLsdhbdJMp7IpbbsrDFDLuBC
Можно предположить, что это API ключи, либо какие-то secret ключи для доступа, поскольку это по-прежнему бессмысленный набор символов, но при этом они слишком длинные, чтобы быть паролями.
Те, кто хоть раз видел сертификаты и публичные или приватные ключи, увидев следующие строки сразу предположит, что это какие-то из этих ключей или сертификатов:
MIIFQDCCBCigAwIBAgIRANLGYBp9c8ZfNCBh256rd4AwDQYJKoZIhvcNAQELBQAw gZAxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTYwNAYD VQQDEy1DT01PRE8gUlNBIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIg Q0EwHhcNMTUxMjI1MDAwMDAwWhcNMTYwMzI0MjM1OTU5WjBLMSEwHwYDVQQLExhE b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxETAPBgNVBAsTCEZyZWUgU1NMMRMwEQYD VQQDEwprYWxpLnRvb2xzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 2M3ci7RJ2lcSYYjNy3UExr5DpcpIAtCm2i/T+n9TlKTnuYi3pfRbRP4JfdNLkKUd +41f7Q1CJfItAOOyazWu3c1rZ1MCOD0/ao7QBt3XAt3nRCSuH/GeGp4Sk+y5POCj EXABgsktVC/Bx7HCljaltMX69uqimIPYPkjucYIov2jqq4/2oYGr3MlRxn7D3B6x ……………………….. ……………………….. ……………………….. ……………………….. ………………………..
Следующие строки являются хешами:
$S$C33783772bRXEx1aCsvY.dqgaaSu76XmVlKrW9Qu8IQlvxHlmzLf $6$q8C1F6tv$zTP/eEVixqyQBEfsSbTidUJfnaE2ojNIpTwTHava/UhFORv3V4ehyTOGdQEoFo1dEVG6UcXwhG.UHvyQyERz01 $1$VnG/6ABB$t6w9bQFxvI9tf0sFJf2TR. adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
То есть простой беглый взгляд на подобные данные позволяет предположить их природу. Но что если получен огромный массив данных на сотни гигабайт и (или) с десятками тысяч файлов? Как извлечь все пароли и ключи из большого количества данных не потратив годы на их изучение вручную?
Именно этой теме и посвящена данная статья. Pawel Rzepa делал исследование об утечки ключей для доступа к облачным платформам; потратив много часов на обзор находок, он решил, что искать пароли и ключи в терабайтах различных файлов просматривая каждый файл — это не вариант. В результате он нашёл метод автоматизировать процесс поиска чувствительной информации в больших объёмах данных и написал программу DumpsterDiver.
Поиск паролей на компьютере
В этой инструкции мы узнаем, как искать пароли и ключи в произвольных файлах, когда они могут быть обнаружены в исходном коде программ или в других случаях, требующих индивидуального подхода. Если же вам необходимо решить более типичную задачу, например, извлечь из компьютера все пароли, введённые в веб-браузер или найти типичные чувствительные файлы, то смотрите статьи:
- Как узнать введённые на сайты пароли
- Как узнать, к каким Wi-Fi сетям подключался компьютер и пароли от этих Wi-Fi сетей
- Извлечение всех паролей (веб-браузеры, почтовые программы и пр.) в Windows и Linux
- Структура директорий Linux. Важные файлы Linux
- Аудит безопасности хостинга и других совместно используемых систем на Linux
Как искать пароли и ключи?
Рассмотрим несколько вариантов:
- мы знаем что нам нужно, например, приватный ключ SSH или Azure Shared key
- мы хотим найти любые пароли и ключи, которые могут присутствовать на компьютере (сервере)
Начнём с первого случая. Предположим, нам нужно найти AWS Secret и ключи Azure Shared, вот их примеры:
lxRV/uiC4knZQxyIZxSSlQ2xNlZMjo4km+LnjNiF M3mmbjOlIZr11OZoULqUWyFA1EpOdZAEcmaC64E/Ft9MRfDEYE7qDJm+9ezGQY15==
Какие характеристики имеют эти ключи? Во-первых, у них фиксированная длина, AWS Secret Key всегда длиной 40 байт, а Azure Shared Key всегда длиной 66. Ещё ключи содержат только Base64 символы. Последняя характеристика, которую мы можем найти у этих ключей — это высокая случайность символов внутри ключа. Можно ли как-то посчитать случайность? Да, можно! Её можно посчитать в битах, используя энтропию Шеннона (Shannon).
Информационная энтропия
Если вам хочется понять, что такое информационная энтропия и как вы можете её посчитать, то хорошее объяснение дано в этой статье (на английском). Используя формулу Клода Шеннона, давайте сравним энтропию одного символа (средний объем информации, доставляемой одним сообщением из источника информации) в следующих строках:
- 404e554d243c1a11d13c96b60129504a31b0abd имеет энтропию 3.57.
- ChuckNorriscountedtoinfinitytwentytwice имеет энтропию 3.81.
- 2r9pAuQxUFAstrWhEy4G4WiVx5iJ74Hja5AWgHq9 имеет энтропию 4.67.
Вы можете сами посчитать энтропию используя этот простой скрипт, который, в том числе, поставляется и с DumpsterDiver:
wget https://gist.githubusercontent.com/xep624/31e06ff461d05d43505f6c6809eda336/raw/58083dab77bc6a8c2f94351a976124c915ed899a/entropy.py
Пример вычисления информационной энтропии строки BCVjd skd;bNhydfdklkg"lgbn,nbldkjgsd:
python entropy.py 'BCVjd skd;bNhydfdklkg"lgbn,nbldkjgsd' The entropy of a character in a string 'BCVjd skd;bNhydfdklkg"lgbn,nbldkjgsd' is 3.37953229264824 bits
Ещё один пример:
python entropy.py 'abcdefghijklmnopqastuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' The entropy of a character in a string 'abcdefghijklmnopqastuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' is 5.661978179679557 bits
Если строка удовлетворяет упомянутым ниже условиям, то вы можем с высокой долей вероятности сказать, что мы имеем дело с ключом:
- Строка содержит только символы из набора Base64 (другими словами, рассматриваем только строки между не Base64 символами, например между “” или ‘’)
- Длина строки между значениями МИНИМАЛЬНАЯ_ДЛИНА и МАКСИМАЛЬНАЯ_ДЛИНА (например, если МИНИМАЛЬНАЯ_ДЛИНА равна 40, а МАКСИМАЛЬНАЯ_ДЛИНА равна 66 байтам, то мы можем найти AWS Secret key и Azure Shared Key)
- Информационная энтропия одиночного символа строки выше значения ЭНТРОПИЯ (энтропия всех AWS secret keys выше 4.2, а энтропия Azure Share Key всегда выше 5.8)
Эти условия стали основой для автоматизации процесса поиска ключей в любом текстовом файле.
Программа для поиска паролей
Используя эти знания, была создана DumpsterDiver, которая в значительной степени была вдохновлена программой TruffleHog (также ищет пароли и ключи основываясь на энтропии строк и регулярных выражений, но только в репозиториях git.
DumpsterDiver — это инструмент для поиска чувствительных данных (паролей, хешей, API ключей, ключей ассиметричного шифрования) в файлах различного типа.
Главные особенности:
- может анализировать любые текстовые файлы
- использует Shannon Entropy для поиска приватных ключей
- может искать по логам git
- распаковывает сжатые архивы (например, zip, tar.gz и т.д.)
- поддерживает продвинутый поиск на основе простых правил (подробности ниже)
- ищет пароли, прописанные в исходном коде или обычных файлах
- полностью настраиваемая, вы можете снизить количество ложных результатов за счёт указания чётких критериев того, что вы ищите
- может искать по регулярным выражениям, поддерживает подстановочные символы
- доступна в качестве образа Docker
- записывает вывод в формат JSON
Как установить DumpsterDiver
Установка DumpsterDiver в Kali Linux
sudo apt install python3-yaml git clone https://github.com/securing/DumpsterDiver cd DumpsterDiver/ sudo pip3 install -r requirements.txt python3 DumpsterDiver.py --help
Установка в BlackArch
sudo pacman -S python-pyaml git clone https://github.com/securing/DumpsterDiver cd DumpsterDiver/ sudo pip3 install -r requirements.txt python3 DumpsterDiver.py --help
Поиск строк с похожих на пароли и ключи (с высокой информационной энтропией)
Для тестирования программы вы можете использовать папки на вашем компьютере, либо создайте специальную тестовую папку:
mkdir ./source_folder/
В этой папке создайте файл с произвольным именем и скопируйте в него:
{ "aws_auth": { "aws_access_key_id": "AKIAJIS5NP79GW2AYZHA", "aws_secret_access_key": "lxRV/uiC4kmZQryIZxSSlQ6xNlZMjo4kn+LnjNiF" }, "azure_auth": { "account": "foobar", "key": "M3mmbjOlIZr11OZoULqUWyFA1EpOdZAEcmaC64E/Ft9MRfDEYE7qDJm+9ezGQY15==", "container": "assets" }, "mail_auth": { "login": "john.doe@evilcorp.com", "password": "M5UWx/N-yjuZ" } }
Предположим, мы ищем любые ключи в этом файле, тогда команда будет выглядеть примерно так:
python3 DumpsterDiver.py -p ./source_folder/ --level 3
Если мы охотимся только за AWS Secret key, тогда мы должны использовать следующую команду:
python3 DumpsterDiver.py -p ./source_folder/ --min-key 40 --max-key 40
Пример запуска программы для анализа исходного кода веб-сайта, в результате которого сразу были найдены приватные API ключи:
Поиск утечек данных по заданным произвольным характеристикам
Теперь давайте предположим, что мы хотим найти файлы, содержащие любой email в домене evilcorp.com и нам не интересные находки с высокой энтропией (то есть нам нужно установить высокое значение энтропии, чтобы в результате возникло условие, которое никогда не будет удовлетворяться, в нашем случае это значение > 6). Для этих целей мы можем использовать следующую команду:
python3 DumpsterDiver.py -p ./source_folder/ -a --entropy 6 --grep-words '*@evilcorp.com*'
Поиск файлов с паролями на диске
Поиск высокой энтропии весьма эффективный метод, но только если вы имеете дело с длинными строками. Для более коротких строк как 8–12 символов этот метод может генерировать множество ложных результатов. Поэтому снова давайте проанализируем характеристики типичных сложных паролей:
- Они длиной 8–12 символов
- Они содержат заглавные и прпоисные буквы, по крайней мере одну цифру и один специальный символ
Для поиска строк, которые удовлетворяют этим условиям, можно использовать библиотеку Python для… вычисления сложности пароля, например, passwordmeter. Далее несколько примеров как это работает на практике.
Используя такой подход мы можем найти все пароли, которые следуют лучшим практикам создания паролей. Что касается тривиальных паролей, то оставим им для брут-форса.
Результаты DumpsterDiver
Результаты сканирования DumpsterDiver не только печатаются в окно терминала, но также все находки записываются в формат JSON (по умолчанию это файл с именем results.json).
Формат JSON довольно распространён и с лёгкостью может быть конвертирован в любой другой формат, например, в .csv. Подробный вывод с любыми ошибками записывается в файл errors.log.
Поиск паролей и ключей на компьютере по определённым параметрам
Имеется три способа настроить DumpsterDiver, чтобы выводимые результаты соответствовали тому, что вам нужно. Это:
- использование уровней поиска
- использование параметров запускаемой команды
- использование файла config.yaml
Настройка уровней поиска
Устанавливая уровень, вы можете ограничить ваши находки (например, только длинные ключи, такие как приватные ключи SSH) и в то же самое время снизить ложные срабатывания. Уровень можно установить в командной строки, и ниже дано подробное описание каждого варианта:
- --level 0 — поиск коротких (длиной 20-40 байт) ключей, например, AWS Access Key ID.
- --level 1 — (по умолчанию) поиск типичных (длиной 40-70 байт) ключей, например, AWS Secret Access Key или Azure Shared Key.
- --level 2 — поиск длиных (длиной 1000-1800 байт) ключей, например, приватных ключей SSH
- --level 3 — поиск любых ключей (длиной 20-1800 байт), будьте осторожны, так как такой вариант выводит много ложных находок
Настройка через параметры строки команды
- --min-key MIN_KEY — указывает минимальную длину ключа для анализа (по умолчанию это 20).
- --max-key MAX_KEY — указывает максимальную длину ключа для анализа (по умолчанию это 80).
- --entropy ENTROPY — указывает минимальное значение энтропии (по умолчанию это 4.3).
- --grep-words GREP_WORDS [GREP_WORDS …] — указывает слова для поиска. Несколько слов должны быть разделены пробелом. Поддерживаются подстановочные символы. Требует использование флага '-a'.
Чтобы оценить примерную энтропию интересующих вас строк, вместе с DumpsterDiver поставляется уже упомянутый выше скрипт entropy.py:
python3 entropy.py f2441e3810794d37a34dd7f8f6995df4
Вы можете использовать его на тестовых паролях, чтобы сориентироваться по примерному вровню энтропии и затем указать уровень информационной энтропии, которой должны соответствовать найденные строки. Это пригодится, когда вы знаете, что ищите.
Далее несколько примеров.
Когда вы ищите AWS Secret Access Key:
python3 DumpsterDiver.py -p [ПУТЬ_ДО_ПАПКИ] --min-key 40 --max-key 40 --entropy 4.3
Когда вы ищите Azure Shared Key:
python3 DumpsterDiver.py -p [ПУТЬ_ДО_ПАПКИ] --min-key 66 --max-key 66 --entropy 5.1
Когда вы ищите приватный ключ SSH (по умолчанию приватные ключи RSA записываются в строки длиной по 76 байт):
python3 DumpsterDiver.py -p [ПУТЬ_ДО_ПАПКИ] --min-key 76 --max-key 76 --entropy 5.1
Когда вы ищите любые совпадения вхождения aws_access_key_id или aws_secret_access_key:
python3 DumpsterDiver.py -p ./test/ --grep-words '*aws_access_key_id*' '*aws_secret_access_key*' -a
Обратите внимание, что подстановочные символы перед и после слов для поиска используются специально. Таким образом выражения вроде "aws_access_key_id" или aws_access_key_id= также будут найдены.
Поиск паролей в исходном коде
Использование энтропии для поиска паролей не очень эффективно, так как это создаёт много ложных сообщений. Поэтому DumpsterDiver использует другой подход для поиска hardcoded (прописанных в файлах исходного кода или настроек) паролей — он проверяет сложность пароля с помощью Passwordmeter. Для настройки этого поиска вы можете использовать следующие опции:
- --min-pass MIN_PASS — указывает минимальную длину пароля для анализа (по умолчанию это 8). Требует использования флага '-s'.
- --max-pass MAX_PASS — указывает максимальную длину пароля для анализа (по умолчанию это 12). Требует использования флага '-s'.
- --pass-complex {1,2,3,4,5,6,7,8,9} — указывает минимальное значение сложности пароля в диапазоне от 1 (тривиальные пароли) до 9 (очень сложные пароли) (по умолчанию это 8). Требует использования флага '-s'.
Например, вы хотите найти сложные пароли (которые содержат заглавные и прописные буквы, специальные символы, цифры и имеют длину от 10 до 15 символов), то вы можете сделать это используя следующую команду:
python3 DumpsterDiver.py -p [ПУТЬ_ДО_ПАПКИ] --min-pass 10 --max-pass 15 --pass-complex 8
Пропуск определённых файлов
При сканировании вы можете пропустить файлы определённого типа. Для этой цели вы можете использовать следующие параметры:
- --exclude-files ИСКЛЮЧИТЬ_ФАЙЛ [ИСКЛЮЧИТЬ_ФАЙЛ …] - указывает имена файлов или расширений, которые не должны анализироваться. Расширения файлов должны содержать символ '.' (например, '.pdf'). Несколько имён файлов или расширений должны быть разделены пробелами.
- --bad-expressions ПЛОХОЕ_ВЫРАЖЕНИЕ [ПЛОХОЕ_ВЫРАЖЕНИЕ …] - указывает плохие выражения — если DumpsterDiver находит такое выражение в файле, тогда этот файл не будет анализироваться. При указании нескольких плохих выражений, они должны быть разделены пробелами.
Если вы хотите указать несколько имён файлов, плохих выражений или слов для поиска которые будут браться из отдельного файла, то вы можете использовать следующий фокус оболочки Bash:
python3 DumpsterDiver.py -p ./test/ --exclude-files `while read -r line; do echo $line; done < blacklisted_files.txt`
Настройка через файлы rules.yaml и config.yaml
Вместо использования множества параметров командной строки, вы можете указать значения для всех выше упомянутых параметров в одном файле config.yaml.
Продвинутый поиск
DumpsterDiver поддерживает также продвинутый поиск. Кроме поиска совпадений по словам с подстановочными символами, этот инструмент позволяет вам создавать условия. Давайте предположим, вы ищите утечку корпоративных email. Дополнительно нам интересные только большие утечки, которые содержат по крайней мере 100 email адресов. Для этих целей вы должны отредактировать файл rules.yaml следующим образом:
filetype: [".*"] filetype_weight: 0 grep_words: ["*@example.com"] grep_words_weight: 10 grep_word_occurrence: 100
Кстати, содержимое файла rules.yaml по умолчанию следующее:
#Rule 1 filetype: [".*"] filetype_weight: 0 grep_words: ["*pass*", "*secret*"] grep_word_occurrence: 1 grep_words_weight: 10
Теперь давайте представим другой сценарий, вы ищите термины "pass", "password", "haslo", "hasło" (последние если вы анализируете репозиторий польской компании) в файлах .db или .sql. Тогда вы можете достичь это изменением файла 'rules.yaml' следующим образом:
filetype: [".db", ".sql"] filetype_weight: 5 grep_words: ["*pass*", "*haslo*", "*hasło*"] grep_words_weight: 5 grep_word_occurrence: 1
Обратите внимание, что правило сработает только когда общий вес (filetype_weight + grep_words_weight) является >=10.
Кстати, по умолчанию содержимое файла rules.yaml следующее:
logfile: './errors.log' base64_chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' archive_types: ['.zip', '.tar.gz', '.tgz', '.tar.bz2', '.tbz'] excluded_files: [ '.jpg', '.jpeg', '.png', '.gif', '.svg', '.mp4', '.mp3', '.webm', '.ttf', '.woff', '.eot', '.css', '.DS_Store', '.pdf'] bad_expressions: [] min_key_length: 40 max_key_length: 66 high_entropy_edge: 4.3 min_pass_length: 8 max_pass_length: 12 password_complexity: 8
Использование Docker
Для DumpsterDiver доступен образ docker. Запускайте его так:
docker run -v /путь/до/моих/файлов:/files --rm rzepsky/dumpsterdiver -p /files
Если вы хотите перезаписать один из конфигурационных файлов (config.yaml или rules.yaml):
docker run -v /путь/до/моих/конфигураций/config.yaml:/config.yaml /путь/до/моих/конфигураций/rules.yaml:/rules.yaml -v /путь/до/моих/файлов:/files --rm rzepsky/dumpsterdiver -p /files
Источники:
- https://medium.com/@rzepsky/hunting-for-secrets-with-the-dumpsterdiver-93d38a9cd4c1
- https://github.com/securing/DumpsterDiver
Связанные статьи:
- Использование Burp Suite в сценариях человек-посередине (MitM): сбор информации, перехват паролей, заражение бэкдорами (59.9%)
- Извлечение всех паролей (веб-браузеры, почтовые программы и пр.) в Windows и Linux (58.3%)
- Как узнать, к каким Wi-Fi сетям подключался компьютер и пароли от этих Wi-Fi сетей (58.3%)
- Расшифровка хранимых в Windows паролей с помощью mimikatz и DPAPI (58.3%)
- Как сбросить пароль Windows (58.3%)
- Аудит безопасности хостинга и других совместно используемых систем на Linux (RANDOM - 28.6%)