Я занимаюсь поиском уязвимостей в различных системах безопасности. В определённый момент мне стало понятно, что мои клиенты недостаточно хорошо знакомы (если вообще знакомы) с базовыми приёмами «хакинга». Ключи к API, пароли, SSH-ключи, сертификаты — всё это отличные механизмы защиты. Но это так до тех пор, пока их держат в секрете. После того, как подобные данные оказываются доступными тем, у кого доступа к ним быть не должно, оказывается, что сложность паролей и продвинутость алгоритмов хеширования уже значения не имеют. В этом материале я хочу рассказать о концепциях, методах и инструментах, применяемых исследователями систем безопасности для нахождения секретных данных. Такие данные используются для взлома систем. Я, кроме того, расскажу тут о простых последовательностях действий, которые помогут снизить риск успешной хакерской атаки.
Важно отметить то, что «игра» в нападение и защиту, в которую играют хакеры и владельцы компьютерных систем, это — нечестная игра. Атакующему достаточно, чтобы проникнуть в систему, выиграть лишь раз. А тому, кто защищается, выиграть можно лишь всегда побеждая. Главная сложность тут — знать о том, на что надо обращать внимание. Но после того, как защитник будет знать о том, через какие именно виртуальные «двери» в его систему может проникнуть хакер, эти «двери» можно защитить с помощью достаточно простых механизмов. Я полагаю, что простота этих механизмов иногда принижает их важность и является причиной того, что многие защитники компьютерных систем упускают эти механизмы из виду.
Вот основные правила защиты систем, которые я собираюсь раскрыть в этом материале. Они просты, но это не значит, что о них можно безнаказанно забыть:
- Включайте многофакторную аутентификацию (multi-factor authentication, MFA) везде, где это возможно. Защищайте с её помощью учётные записи Google и GitHub, аккаунты облачных провайдеров, личные кабинеты VPN-сервисов. Если используемая вами система не предусматривает использование MFA — подумайте о переходе на другую систему.
- Выполняйте ротацию паролей и ключей, применяйте политики ротации паролей.
- Регулярно проверяйте код на наличие в нём того, чего в нём быть не должно. Лучше всего сделать такие проверки частью процесса проверки кода перед публикацией.
- Делегируйте одной центральной системе задачи по работе с профилями регистрации и по управлению доступом к другим система. Эта система должна находится под вашим контролем, вы должны постоянно за ней наблюдать.
В деле предотвращения утечек секретной информации и недопущения появления «дыр» в системах безопасности действует принцип Парето, в соответствии с которым 20% усилий дают 80% результата.
Как же действуют хакеры, находя пароли и секретные ключи? Какими инструментами они пользуются?
Хакеры находят секретные данные в JavaScript-файлах
Ключи к API разбросаны по всему интернету. Воспользоваться ими может кто угодно. Это — факт. Часто у того, что ключи оказываются в общем доступе, нет каких-то особых причин. Разработчики просто повсюду их забывают. Например, ключи попадают в код по следующим причинам:
- Для отладочных целей.
- Для целей локальной разработки.
- В виде комментариев, предназначенных для тех, кто будет поддерживать проект позже.
Блоки кода, напоминающие следующий, можно встретить в интернете довольно часто:
// DEBUG ONLY
// TODO: remove -->
API_KEY=t0psecr3tkey00237948
Хотя многие хакеры самостоятельно читают код JavaScript-файлов, такие файлы, в основном, ищут с помощью инструментов вроде meg, а потом проверяют то, что нашли, на наличие там соответствующих паттернов.
Как они это делают? После использования сканера вроде meg
они ищут в найденных файлах строки, соответствующие различным шаблонам. Тот же, кто создал meg
, написал ещё одну отличную программу, именно для этого и предназначенную. Она называется gf и представляет собой улучшенный вариант grep
. В данном случае использование при запуске gf
опции truffleHog
или, в другом варианте её написания, trufflehog
, позволяет инструменту находить высокоэнтропийные строки, представляющие собой ключи к API. То же самое касается и поиска строки API_KEY
. Результаты поиска по такой строке часто (слишком часто) оказываются успешными.
Нередко у того, что ключи появляются в коде, есть совершенно нормальные причины, но такие ключи не защищены от посторонних. Приведу пример. Один клиент, с которым я работал, пользовался внешним сервисом картографической информации. Так делается во многих проектах. Для того чтобы загружать картографическую информацию и работать с ней, нужно было выполнять обращения к соответствующему API с использованием ключа. Но мой клиент забыл настроить применяемый им сервис так, чтобы ограничить источники, с которых в этот сервис могут поступать запросы, использующие этот конкретный ключ. Несложно представить себе простую атаку, которая заключается в том, чтобы истощить квоту на использование ресурсов картографического сервиса путём отправки к нему множества запросов. Это может стоить пользователю такого сервиса больших денег. Или, что ещё «лучше» (с точки зрения атакующего), такая атака может привести к тому, что те части проекта клиента, которые завязаны на картах, попросту «упадут».
JS-файлы используются хакерами не только для поиска секретных данных. Ведь такие файлы — это код вашего приложения, который может увидеть любой, кому этот код интересен. Хороший хакер может, внимательно прочтя код, разобраться в используемом в нём подходе к именованию сущностей, выяснить пути к API, может обнаружить ценные комментарии. Подобные находки оформляются в виде списка слов, передаваемого автоматическим сканерам. Это — то, что называется «интеллектуальным автоматизированным сканированием» («intelligent automated scan»), когда хакер комбинирует автоматические инструменты и собранную им информацию о конкретном проекте.
Вот реальный комментарий с домашней страницы одного проекта, в котором открытым текстом говорится о незащищённых API, данные из которых может получить кто угодно:
/* Debug ->
domain.com/api/v3 not yet in production
and therefore not using auth guards yet
use only for debugging purposes until approved */
▍Что делать?
- Минифицируйте код. Благодаря этому код обфусцируется. Подобная обработка кода обратима, но благодаря ей можно обойти многие автоматические сканеры, что уменьшает потенциальные возможности атаки.
- Оставляйте в коде только абсолютный минимум ключей и путей к API. В то время как без некоторых из них обойтись не получится, о большинстве из них сказать того же самого нельзя. Оставляйте в коде только те ключи, которым совершенно необходимо в нём присутствовать.
- Понизьте разрешения, связанные с ключами, до абсолютного минимума. Если вспомнить пример с сервисом картографической информации, то можно сказать, что ключи должны быть такими, чтобы с их помощью можно было бы делать только то, для чего они предназначены, и чтобы пользоваться ими можно было бы только там, где они должны использоваться. Удостоверьтесь в том, что эти ключи нельзя использовать для атаки на систему.
- Используйте те же инструменты для автоматического сканирования кода, которые используют хакеры. Включайте их в системы непрерывной интеграции. Особенно это касается средств для поиска строковых паттернов, которые работают очень быстро. Используйте простые инструменты вроде
grep
илиgf
для поиска строк. Такая проверка кода сродни тестам. Она позволяет убедиться в том, что разработчики не оставляют в коде дыр, которыми может воспользоваться злоумышленник для взлома системы. - Внедрите у себя практику код-ревью. Всегда полезно, когда кто-то проверяет ваш код. Все автоматические сканеры мира не способны выявить 100% возможных проблем. Код-ревью — это отличный способ повышения качества и защищённости кода.
Хакеры анализируют информацию из прошлого, пользуясь интернет-архивами
Архив Интернета (известный ещё как «Wayback Machine») хранит периодически создаваемые снимки веб-сайтов. Этот проект позволяет увидеть то, каким был интернет многие годы тому назад. Данные архива представляют немалый интерес для хакеров, которым нужно собрать сведения о некоем проекте. Сканировать файлы старых вариантов веб-сайтов можно с помощью инструментов наподобие waybackurls (он основан на waybackurls.py). Это значит, что даже если вы нашли в коде сайта ключ и убрали его оттуда, но не произвели ротацию ключей, хакеры могут найти этот ключ в старой версии сайта и воспользоваться этим ключом для взлома системы.
Вот что нужно сделать в том случае, если вы нашли ключ там, где его быть не должно:
- Создайте ключ, предназначенный для замены скомпрометированного ключа.
- Выпустите новую версию кода, в которой используется новый ключ. Этот код должен быть переписан так, чтобы в нём не было бы строк, позволяющих легко идентифицировать ключ.
- Удалите или деактивируйте старый ключ.
▍Архив Интернета — это не единственное место, где можно найти ключи
Старый код даёт злоумышленникам самую разную интересующую их информацию.
- Секретные пути к API. Речь идёт о незащищённых конечных точках API, сведения о которых, как думал разработчик, никогда не попадут в общий доступ. Хотя те пути, которые обнаружит хакер, могут оказаться для него бесполезными, эти пути способны помочь в понимании структуры API проекта и принятых в нём соглашений по устройству API. После того, как код сайта уходит в продакшн, у разработчика уже нет способов скрыть этот код от любопытных взглядов. Об этом очень важно помнить.
- Сведения для доступа к панелям администраторов веб-проектов. Эти данные, так же как и сведения о конечных точках API, оказываются в открытом доступе по разным причинам. Они часто становятся объектом интереса хакеров, которые находят и используют их. Открытые панели администрирования, в основном, можно обнаружить в проектах больших организаций. Такие панели создают команды, ответственные за ИТ-инфраструктуру. Рекомендуется периодически проверять такие панели и анализировать их на предмет того, какие возможности по доступу к системам они дают тому, кто ими пользуется. Например, недавно взломали одного производителя автомобильного оборудования, воспользовавшись дырой в подобной панели. Оказалось, что для проникновения в систему достаточно было убрать
s
изhttps
.
Хакеры пользуются GitHub
GitHub — это настоящая золотая жила для хакеров. Если знать о том, где искать, то, воспользовавшись простыми инструментами поиска, можно найти много всего интересного. Если учётная запись вашей организации на GitHub не защищена механизмом многофакторной аутентификации, то все без исключения сотрудники организации представляют собой ходячие дыры системы безопасности. Вполне реально то, что некоторые из сотрудников используют везде один и тот же пароль, и то, что этот пароль уже был украден у них через какую-то другую систему. Хакер, которого интересует некая организация, может легко автоматизировать поиск скомпрометированных паролей, да что там говорить, он может найти такие пароли и вручную.
Список сотрудников организации можно создать, воспользовавшись методами разведки, основанной на открытых источниках (Open source intelligence, OSINT). Помочь в этом злоумышленнику может LinkedIn или общедоступный список сотрудников компании с GitHub.
Если, например, кто-то решил взломать компанию Tesla, то он вполне может начать изучение компании с этой страницы:
https://api.github.com/orgs/teslamotors/members
А даже если компания не использует GitHub в качестве git-платформы, на GitHub, всё равно, можно найти что-то ценное. Достаточно, чтобы этой платформой пользовался хотя бы один из сотрудников компании, например, для домашнего проекта. Если в коде этого проекта (или в истории git) появится что-то секретное, относящееся к компании, этого будет достаточно для того чтобы проникнуть в системы этой компании.
Отслеживание полной истории изменений, вносимых в каждый проект, это — природа git. В свете вопросов безопасности этот факт играет огромную роль. Другими словами, каждое изменение, внесённое в код любым, кто имеет доступ к каким-либо системам некоей организации, подвергает эту организацию опасности.
▍Почему это происходит?
- Компании не проверяют свои системы на предмет наличия в них уязвимостей.
- Те компании, которые выполняют подобные проверки, обычно не обращают внимания на общедоступные учётные записи своих сотрудников.
- Те компании, которые проверяют и свои системы, и учётные записи сотрудников (а таких, по грубым оценкам, менее 1%), часто слишком сильно полагаются на автоматические сканеры и не проверяют историю коммитов (то есть — анализируют не всё дерево git, а лишь то, что лежит на поверхности, представленное самой свежей версией кода).
- И наконец, достаточно часто компании не выполняют ротацию ключей и не применяют двухфакторную аутентификацию. Два этих приёма способны закрыть большинство вышеупомянутых брешей систем безопасности.
▍Основы использования особых поисковых запросов в GitHub
Существует такое понятие, как «дорки» («dorks») — особые поисковые запросы, использующие различные возможности поисковых систем для нахождения того, что имеет отношение к определённым данным. Вот — интересный список подобных поисковых запросов для Google, подготовленный exploit-db.com.
Если вы хотите углубиться в эту тему, а я рекомендую это сделать, то, прежде чем давать вам краткий список строк, используемых для поиска ключей и паролей на GitHub, предлагаю ознакомиться с этим ценнейшим материалом, написанным талантливым исследователем безопасности систем. Он рассказывает о том, как, что и где искать на GitHub, как пользоваться дорками, детально расписывает ручной процесс поиска секретных данных.
Дорки, применимые на GitHub, не так сложны, как те, которыми можно пользоваться в Google. Дело тут в том, что GitHub просто не предлагает пользователю столь же продвинутых поисковых возможностей, которые предлагает Google. Но, несмотря на это, правильный поиск по GitHub-репозиториям может прямо-таки творить чудеса. Попробуйте поискать в интересующем вас репозитории по следующим строкам:
password
dbpassword
dbuser
access_key
secret_access_key
bucket_password
redis_password
root_password
А если попробуете искать определённые файлы, используя запросы вроде filename:.npmrc _auth
или filename:.htpasswd
, то вы сможете фильтровать результаты поиска по типам утечек данных. Вот ещё один хороший материал на эту тему.
▍Меры по снижению рисков, связанных с GitHub
- Сделайте сканирование кода на предмет уязвимостей частью CI-процесса. В этом вам может помочь отличный инструмент GitRob.
- Сканируйте репозитории сотрудников компании. GitRob выполняет подобные проверки без дополнительных настроек. Для того чтобы это отключить, можно запустить его с флагом
no-expand-orgs
. - Проверяйте историю репозиториев. GitRob, по умолчанию, сканирует 500 коммитов, но вы можете решить пойти ещё дальше, воспользовавшись параметром вида
-commit-depth <#number>
. - Включите на GitHub двухфакторную аутентификацию!
- Выполняйте, во всех без исключения системах, ротацию ключей доступа, секретных ключей, паролей. Рекомендуется использовать централизованную систему доступа к другим системам наподобие G Suite или Active Directory. Нужно обеспечить применение в подобной системе политик безопасности, касающихся ротации и сложности паролей.
После того, как этот материал был опубликован, некоторые его читатели сделали ценные замечания, касающиеся сложности паролей и их ротации, а так же — использования аппаратных средств защиты информации.
Вот комментарии @codemouse92:
Применяйте везде, где используется парольный вход в систему, сложные и уникальные пароли. Но учитывайте то, что сложный пароль — это не обязательно такой, который представляет собой таинственную мешанину из букв, цифр и специальных символов. Сейчас лучшей стратегией считается использование в качестве паролей длинных фраз. Мне хотелось бы сделать одно примечание по поводу менеджеров паролей. Хотя, определённо, такими программами пользоваться стоит, всё равно лучше использовать пароли, представляющие собой фразы, которые пользователи помнят и могут вводить самостоятельно.
Вот что говорит пользователь @corymcdonald:
Там, где я работаю, всем выдают аппаратные средства многофакторной аутентификации. У каждого имеется по 2 устройства YubiKey. Кроме того, каждая команда пользуется менеджером паролей 1Password, для каждой команды создано собственное хранилище паролей. Когда некий сотрудник покидает компанию, команда техподдержки выполняет ротацию паролей в каждом хранилище, к которому был доступ у этого сотрудника. Лично я, например, совершил непростительную ошибку, выложив на GitHub ключи для доступа к AWS. Рекомендовано, перед выполнением коммитов, проверять материалы с использованием git-secrets. Это позволит не дать уйти в общий доступ тому, что напоминает секретные сведения.
Хакеры используют Google
Теперь, когда мы в общих чертах познакомились с дорками, мы можем поговорить о применении особых поисковых запросов в Google. Тут с их помощью можно найти просто невероятные вещи. Google — мощная поисковая система, которая позволяет строить запросы, описывая строки, которые должны и не должны присутствовать в искомых данных. Google, кроме прочего, позволяет искать файлы с определёнными расширениями, умеет выполнять поиск по заданным доменам, по URL. Взгляните на следующую поисковую строку:
"MySQL_ROOT_PASSWORD:" "docker-compose" ext:yml
Эта строка рассчитана на поиск файлов с расширением yml
, причём, это должны быть файлы docker-compose
, в которых разработчики нередко хранят пароли. Не особенно уникальные пароли. Попробуйте запустить в Google поиск по этой строке. Вас удивит то, что вы найдёте.
Другие интересные поисковые строки могут быть рассчитаны на поиск RSA-ключей или учётных данных AWS. Вот ещё один пример:
"-----BEGIN RSA PRIVATE KEY-----" ext:key
Тут перед нами открываются безграничные возможности. Качество поиска зависит лишь от уровня креативности исследователя и от того, насколько хорошо он знаком с различными системами. Вот, если хотите поэкспериментировать, большой список Google-дорков.
Хакеры тщательно изучают интересующие их системы
Когда некая система очень интересует исследователя безопасности (или мотивированного хакера), он приступает к глубокому изучению этой системы. Он близко знакомится с ней. Его интересуют конечные точки API, соглашения по именованию сущностей, особенности взаимодействия внутренних частей систем, наличие доступа к разным версиям системы в том случае, если одновременно используются её разные версии.
Не очень хороший подход к защите API заключается в том, чтобы усложнять пути доступа к ним, скрывать их с использованием чего-то вроде генератора случайных символов. Это не заменяет реальных механизмов обеспечения безопасности. Исследователи безопасности пытаются найти незащищённые пути доступа к системам, конечные точки API, например, пользуясь инструментами для «нечёткого» поиска уязвимостей. Такие инструменты используют списки слов, строят из них пути и проверяют эти пути, анализируя получаемые при попытке обращения к ним ответы. Подобный сканер не найдёт конечную точку, путь к которой представлен совершенно случайным набором символов. Но такие инструменты прекрасно показывают себя в деле идентификации паттернов и в нахождении конечных точек, о которых владельцы системы либо забыли, либо никогда и не знали.
Помните о том, что «безопасность через неясность» («security through obscurity») — это не лучший способ защиты систем (хотя полностью игнорировать его не стоит).
Тут на помощь злоумышленникам и приходят GitHub-дорки, о которых мы говорили выше. Знание о том, какие правила используются при составлении путей к конечным точкам системы (например — нечто вроде api.mydomain.com/v1/payments/...
) может оказать хакеру огромную помощь. Поиск по GitHub-репозиторию компании (и по репозиториям её сотрудников) на предмет строк, связанных с API, часто позволяет находить и пути, включающие в себя случайные символы.
Но и у «случайных строк», тем не менее, есть своё место в системах. Их применение всегда лучше, чем использование в путях к API последовательностей из идентификаторов ресурсов, строк вроде users
и orders
.
Вот — потрясающий репозиторий SecLists, который содержит множество строк, используемых при именовании сущностей. Им пользуются практически все, имеющие отношение к индустрии защиты данных. Часто эти материалы модифицируют под конкретную систему. Ещё один инструмент, который можно использовать для поиска «зашифрованных» путей, это FFuf — чрезвычайно быстрая программа, основанная на нечёткой логике, написанная на Go.
Итоги
Вопросы безопасности часто обходят вниманием в стартапах. Программисты и менеджеры обычно делают приоритетом скорость разработки и частоту выхода новых версий продукта, жертвуя качеством и безопасностью. Тут встречается включение в код, попадающий в репозитории, секретных сведений, использование в разных местах системы одних и тех же ключей, применение ключей доступа там, где можно воспользоваться чем-то ещё. Иногда может показаться, что нечто подобное позволяет ускорить работу над проектом, но, со временем, это может привести к очень плохим последствиям.
В этом материале я попытался показать вам то, как строки, которые, как кажется, защищены тем, что хранятся в закрытом репозитории, могут легко уйти в общий доступ. То же касается и клона репозитория, сделанного сотрудником из лучших побуждений и не предназначенного для чужих глаз, но оказавшегося общедоступным. Но можно создать базу для безопасной работы, воспользовавшись инструментом для организации безопасного совместного использования паролей, применив централизованное хранилище секретных данных, настроив политики безопасности паролей и многофакторную аутентификацию. Это позволит, не игнорируя безопасность, не замедлить скорость работы над проектом.
Если говорить о защите информации, то тут не очень хорошо работает идея, в соответствии с которой скорость — это самое главное.
Приобретение знаний о том, как работают хакеры, обычно представляет собой очень хороший первый шаг на пути к пониманию того, что такое информационная безопасность. Это — первый шаг к защите систем. Защищая системы, учитывайте вышеперечисленные способы проникновения в них, и то, что хакеры используют достаточно ограниченный набор таких способов. Рекомендуется рассматривать с точки зрения безопасности абсолютно всё, что так или иначе имеет отношение к некоей системе, вне зависимости от того, идёт ли речь о внешних или внутренних механизмах.
Защита систем иногда может восприниматься как дело не особо важное, но трудозатратное и беспокойное. Но будьте уверены: предпринятые вами простые действия по защите ваших систем способны избавить вас от огромных неприятностей.
Как вы защищаете свои системы?
Автор: ru_vds