🔒 Поможем найти и удалить захардкоженные пароли и секреты в проекте |

🔒 Поможем найти и удалить захардкоженные пароли и секреты в проекте

Мануал

Случайная утечка секретов в git-коммитах – это не самае приятная новость.

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

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

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

Проверка известных файлов вручную

Вот несколько мест, где мы можем увидеть секреты:

  • README.md или более общая документация
    Здесь легко скопировать/вставить что-нибудь, например, команду curl с токеном
  • .env.example
    Это самое подходящее место для их существования из соображений удобства
  • Dockerfile
    Инструкции ARG, ENV и RUN могут иметь секреты, но они могут быть и в другом месте
  • docker-compose.yml
    Свойства сборки, окружения или команды могут содержать секреты
  • Скрипт entrypoint Docker
    Путь к файлам зависит от вашего проекта, но они могут существовать здесь
  • Различные файлы в каталогах config/, settings/ и т. д. вашего приложения
    Здесь их может быть довольно много

🐳 Разница между ENTRYPOINT и CMD в Dockerfile

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

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

Кстати, мы уже писали об этом: 🔎 Аудит исходного кода с помощью GREP

Нужно подумать о том, безопасно ли коммитить секрет.

Например, в некоторых файлах .env.example мы коммитим значение POSTGRES_PASSWORD=password, потому что оно используется только в разработке.

Мы не против “утечки” этого значения, потому что это значительно упрощает работу с проектом, а производственный секрет отличается и не коммититься.

Поиск обычных подозреваемых

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

# Выполните рекурсивный поиск без учета регистра regex для известных значений, но игнорируйте
# конкретные каталоги. Вы можете использовать `git grep` вместо grep, если хотите.

grep -REi --exclude-dir=”.git” \
“(auth|authentication|authorization|bearer|secret|token|pass|password|username)” .

Вышеприведенное выражение не отлавливает все.

Обычно это токены bearer или ключи API в целом.

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

Мы оставили auth|authentication|authorization и pass|password как отдельные элементы, хотя их можно было бы упростить до auth и pass, потому что преимущество их разделения в том, что вы можете добавить флаг -w к приведенной выше команде grep, чтобы ограничить поиск только целыми словами.

Например, приведенная выше команда будет соответствовать secretToken, но при использовании -w этого не произойдет, потому что она будет соответствовать только secret или token по отдельности.

Другой пример, когда не использовать -w удобно, это что-то вроде app_password.

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

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

Например, если у вас есть postgresql://admin:myuniquepw@example.com/mydb, то приведенный выше regex не сможет его поймать.

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

Поиск длинных строк без пробелов

Надеемся, что вышеперечисленные два метода поймали практически все, но никогда не знаешь так ли это.

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

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

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

Что мы должны искать?

Например, может быть, ваш критерий – любые 12+ символов, которые появляются между одинарными или двойными кавычками.

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

Например, если вы просканируете файлы HTML-шаблонов на предмет “images/hello.jpg”, они будут совпадать, потому что в них 16 символов, а это > 12, но если вы попытаетесь быть хитрым и игнорировать значения, содержащие /, вы можете пропустить легитимные токены, потому что определенные алгоритмы включают /.

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

Позже вы всегда сможете все уточнить.

Может быть, для начала вы можете использовать:

  • Любые 24+ символа без пробела, заключенные в одинарные или двойные кавычки
  • Следующий символ – пробел, ., ; или конец строки

Это второе правило поможет снизить уровень шума.

Варианты, подобные этому, будут подхвачены, я использую abcdef123456 вместо более длинного токена:

  • tok = "abcdef123456";
  • tok = "abcdef123456"\n
  • tok = "abcdef123456" . "?filter=cool"
  • tok = "abcdef123456"."?filter=cool"

Но в то же время <img src=”images/hello.jpg”> не будет обнаружен, потому что > не является одним из следующих символов, которые мы ищем.

Кроме того, в зависимости от того, на каком фреймворке или инструментах построено ваше приложение, можно пропустить несколько каталогов, если это поможет уменьшить количество ложных срабатываний.

Например, вы можете спокойно пропустить каталог css/, хотя JavaScript на стороне клиента стоит просканировать, потому что в нем могут быть жестко закодированы токены (я видел это много раз в работе с клиентами).

🌐 Как найти общеизвестные уязвимости безопасности в веб-библиотеках JavaScript веб-сайта

Вы можете задать параметры –exclude-dir и –exclude несколько раз, чтобы игнорировать несколько каталогов и файлов.

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

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

Как будет выглядеть наша команда grep?

Эти команды должны работать как в GNU, так и в BSD-версии grep, что означает их совместимость с Linux, WSL 2 и macOS.

Вот более жесткая версия (меньше ложных срабатываний):

grep -REi \
--exclude-dir=".git" \
--exclude-dir="assets/css" \
"('|\")\S{24,}('|\")(\s|\.|;)" .

Вот более слабая версия (больше ложных срабатываний, но можно обнаружить больше утечек):

grep -REi \
--exclude-dir=".git" \
--exclude-dir="assets/css" \
"('|\")\S{12,}('|\")" .

Вот описание регулярки:

  • (‘|\”) соответствует одинарной или двойной кавычке
  • \S{24,} соответствует любым 24+ символам, не содержащим пробелов
  • (‘|\”) совпадает с одинарной или двойной кавычкой
  • (\s|\.|;) соответствует любому символу, похожему на пробел, точку или точку с запятой

Не стесняйтесь корректировать любой из них, https://regex101.com/ – отличный сайт для тестирования регулярки.

Имейте в виду, что приведенные выше варианты не идеальны.

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

В тех случаях, с которыми мы сталкивались, вышеописанное сработало достаточно хорошо.

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

Если есть сомнения, проверяйте все вручную

Если ставки высоки и вы считаете, что произошла утечка секретов, то последняя линия обороны – ручная проверка каждой строки каждого файла.

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

Возможно, вы справитесь с этой задачей за час или несколько часов.

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

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

см. также:

Пожалуйста, не спамьте и никого не оскорбляйте. Это поле для комментариев, а не спамбокс. Рекламные ссылки не индексируются!
Добавить комментарий