- Inscrit
- 17 Fév. 2007
- messages
- 678
- Score de réaction
- 1,026
- Points
- 93
Finding secret data in the source code
Original author: Vickie Li
When developers add sensitive data like passwords and API keys directly into the source code, that data can easily reach public repositories.
As a developer, I admit that I used to allow secrets to get into public GitHub repositories. This kind of data, hardcoded into code, has always been a problem in various organizations. When I perform penetration testing in order to check the security systems of companies, I always first of all examine the code of these companies for the presence of secret data. If a developer introduces something like passwords into the code, this data can end up in public repositories or in application packages, and after that it can fall into the hands of attackers.
As microservice architectures and applications built around certain APIs become more and more widespread, developers often need software mechanisms to exchange identities and other secrets. This means that programmers, working with such data, can sometimes make mistakes.
Consider a practical example of an identity leak written directly into the source code of one system. Here bug report regarding reverb.com. The researcher found in the code the credentials used to access Cloudinary. The secret key was present in the source code of the Android Reverb application. Anyone who downloads this app can retrieve the appropriate credentials and be able to read, edit, and delete the files stored in the respective Cloudinary instance:
private static final java.lang.String CONFIG = "cloudinary: // 434762629765715: █████ @ reverb";
And such vulnerabilities are not at all uncommon. I am testing systems for penetration resistance, and I can say that I have happened to find a variety of classified data in public code or in compiled files of many organizations. Among them are credentials for authentication in various services, AWS keys, keys to the GitHub API. Sometimes a hacker who wants to hack a certain company just needs to search its GitHub repository for the credentials sent there accidentally to log into various systems.
Using regular expressions
How to detect secret data in the code before it gets into the public domain and leads to information leakage from the organization? The easiest and most straightforward way to find such data, hardcoded into the code, is to use text search tools and regular expressions.
If your code contains API keys, encryption keys, database passwords, you can often find them using keyword search tools like grep. For example, you can search for key, secret, password, or aws. This approach searches by identifiers, such as variable names, that are used to store the data of interest. Similarly, you can use text search to find file names and service data associated with secret data that are specific to files of a certain format. For example, you can search for the string ----- BEGIN RSA PRIVATE KEY -----.
Many API keys are also written using a specific data format. You can find such keys by performing a regular expression search. For example, AWS Access Key IDs typically start with the string AKIA followed by 16 alphanumeric characters. Therefore, if you search using the regular expression AKIA [0-9A-Z], you can find the corresponding keys in the code.
Keys for the Twilio API start with SK followed by 32 alphanumeric characters. This means that you can find them using the regular expression SK [a-z0-9] {32}. Passwords in URLs can be found by searching for patterns that match the basic syntax used in the respective authentication mechanisms: [a-zA-Z] {3,15}: \ / \ / [^ \ / \\: @] +: [^ \ / \\: @] + @. {1,100}. By using this pattern, you can discover the credentials included in the URL: protocol: // username: password@example.com ... To search for secret data in your own code, you need to find out how the keys used in the code are arranged, and then write regular expressions to find them.
Thanks to the two strategies described above for finding secret data in the code, you can find the bulk of such data. But, relying only on text search, we run the risk of missing those secret data that are not represented by strings of a certain format. Here we can come to the aid of entropy code analysis.
Let's talk about entropy
We can think of entropy as a measure of how "random" and "unpredictable" data is. For example, a single-character string like aaaaa has very low entropy. But a string that contains more different characters, like wJalrXUtnFEMI / K7MDENG / bPxRfiCYEXAMPLEKEY, has a higher entropy. You can check such lines and find out how the entropy index is calculated using by this Shannon's entropy calculator.
The entropy exponent is a good way to find highly randomized, complex strings. By calculating this metric for string literals used in your code, you can detect suspicious strings of any format.
What's next?
Code submitted to public repositories should be checked for any accidental secrets. If something like this has got into public access, it makes sense to consider it stolen, the corresponding keys, passwords, and so on, need to be changed.
Of course, not all code is open source, not all secret data, hard-coded in the code, end up in public repositories. But such a practice, anyway, can result in a problem, since this data can leave the company in executable files of applications, in the form of logs, if the source code is stolen. A good strategy to minimize the risk of sensitive data leaks is to perform a code scan using pattern search and entropy data analysis. This is done before the code gets into production. And the secret data themselves must be stored either in configuration files, or - using special services designed to manage such data.
Sometimes it may seem that secret data just needs to be stored in code, which, in the form of an application, gets to end users. For example - we can talk about API keys used in mobile applications. In such a case, you can take measures to prevent the possibility of detection of such data. For example, it is better not to give the variables in which some keys are stored, names that unambiguously indicate their contents, such as api_key and password. It is recommended to obfuscate the code, which will complicate the extraction of secret data from it. Finally, you can simply execute the portion of the application code that is responsible for accessing third-party services on the server, avoiding the need to include this code as part of the application package that is passed to the end user.
Always check your code for sensitive data and investigate the possibility of this data falling into the hands of intruders. If such data does not enter the code by accident, think about whether it really should be present in the code, and whether it is well protected.
As a result, I can say that static analysis is the most reliable way to detect secret data that accidentally got into the code.
Translation source
Original author: Vickie Li
When developers add sensitive data like passwords and API keys directly into the source code, that data can easily reach public repositories.
As a developer, I admit that I used to allow secrets to get into public GitHub repositories. This kind of data, hardcoded into code, has always been a problem in various organizations. When I perform penetration testing in order to check the security systems of companies, I always first of all examine the code of these companies for the presence of secret data. If a developer introduces something like passwords into the code, this data can end up in public repositories or in application packages, and after that it can fall into the hands of attackers.
As microservice architectures and applications built around certain APIs become more and more widespread, developers often need software mechanisms to exchange identities and other secrets. This means that programmers, working with such data, can sometimes make mistakes.
Consider a practical example of an identity leak written directly into the source code of one system. Here bug report regarding reverb.com. The researcher found in the code the credentials used to access Cloudinary. The secret key was present in the source code of the Android Reverb application. Anyone who downloads this app can retrieve the appropriate credentials and be able to read, edit, and delete the files stored in the respective Cloudinary instance:
private static final java.lang.String CONFIG = "cloudinary: // 434762629765715: █████ @ reverb";
And such vulnerabilities are not at all uncommon. I am testing systems for penetration resistance, and I can say that I have happened to find a variety of classified data in public code or in compiled files of many organizations. Among them are credentials for authentication in various services, AWS keys, keys to the GitHub API. Sometimes a hacker who wants to hack a certain company just needs to search its GitHub repository for the credentials sent there accidentally to log into various systems.
Using regular expressions
How to detect secret data in the code before it gets into the public domain and leads to information leakage from the organization? The easiest and most straightforward way to find such data, hardcoded into the code, is to use text search tools and regular expressions.
If your code contains API keys, encryption keys, database passwords, you can often find them using keyword search tools like grep. For example, you can search for key, secret, password, or aws. This approach searches by identifiers, such as variable names, that are used to store the data of interest. Similarly, you can use text search to find file names and service data associated with secret data that are specific to files of a certain format. For example, you can search for the string ----- BEGIN RSA PRIVATE KEY -----.
Many API keys are also written using a specific data format. You can find such keys by performing a regular expression search. For example, AWS Access Key IDs typically start with the string AKIA followed by 16 alphanumeric characters. Therefore, if you search using the regular expression AKIA [0-9A-Z], you can find the corresponding keys in the code.
Keys for the Twilio API start with SK followed by 32 alphanumeric characters. This means that you can find them using the regular expression SK [a-z0-9] {32}. Passwords in URLs can be found by searching for patterns that match the basic syntax used in the respective authentication mechanisms: [a-zA-Z] {3,15}: \ / \ / [^ \ / \\: @] +: [^ \ / \\: @] + @. {1,100}. By using this pattern, you can discover the credentials included in the URL: protocol: // username: password@example.com ... To search for secret data in your own code, you need to find out how the keys used in the code are arranged, and then write regular expressions to find them.
Thanks to the two strategies described above for finding secret data in the code, you can find the bulk of such data. But, relying only on text search, we run the risk of missing those secret data that are not represented by strings of a certain format. Here we can come to the aid of entropy code analysis.
Let's talk about entropy
We can think of entropy as a measure of how "random" and "unpredictable" data is. For example, a single-character string like aaaaa has very low entropy. But a string that contains more different characters, like wJalrXUtnFEMI / K7MDENG / bPxRfiCYEXAMPLEKEY, has a higher entropy. You can check such lines and find out how the entropy index is calculated using by this Shannon's entropy calculator.
The entropy exponent is a good way to find highly randomized, complex strings. By calculating this metric for string literals used in your code, you can detect suspicious strings of any format.
What's next?
Code submitted to public repositories should be checked for any accidental secrets. If something like this has got into public access, it makes sense to consider it stolen, the corresponding keys, passwords, and so on, need to be changed.
Of course, not all code is open source, not all secret data, hard-coded in the code, end up in public repositories. But such a practice, anyway, can result in a problem, since this data can leave the company in executable files of applications, in the form of logs, if the source code is stolen. A good strategy to minimize the risk of sensitive data leaks is to perform a code scan using pattern search and entropy data analysis. This is done before the code gets into production. And the secret data themselves must be stored either in configuration files, or - using special services designed to manage such data.
Sometimes it may seem that secret data just needs to be stored in code, which, in the form of an application, gets to end users. For example - we can talk about API keys used in mobile applications. In such a case, you can take measures to prevent the possibility of detection of such data. For example, it is better not to give the variables in which some keys are stored, names that unambiguously indicate their contents, such as api_key and password. It is recommended to obfuscate the code, which will complicate the extraction of secret data from it. Finally, you can simply execute the portion of the application code that is responsible for accessing third-party services on the server, avoiding the need to include this code as part of the application package that is passed to the end user.
Always check your code for sensitive data and investigate the possibility of this data falling into the hands of intruders. If such data does not enter the code by accident, think about whether it really should be present in the code, and whether it is well protected.
As a result, I can say that static analysis is the most reliable way to detect secret data that accidentally got into the code.
Translation source
Original message
Поиск секретных данных в исходном коде
Автор оригинала: Vickie Li
Когда разработчики вносят прямо в исходный код секретные данные, вроде паролей и ключей API, эти данные вполне могут добраться до общедоступных репозиториев.
Я — разработчик, и я признаю то, что раньше допускала попадание секретных данных в открытые GitHub-репозитории. Подобные данные, жёстко заданные в коде, всегда были проблемой в различных организациях. Я, выполняя испытания на проникновение с целью проверки систем защиты компаний, всегда в первую очередь исследую код этих компаний на наличие в нём секретных данных. Если разработчик вносит что-то вроде паролей в код, эти данные могут оказаться в общедоступных репозиториях или в пакетах приложений, а после этого могут попасть в руки злоумышленников.
По мере того, как микросервисные архитектуры и приложения, построенные вокруг неких API, получают всё более и более широкое распространение, разработчики часто нуждаются в программных механизмах обмена идентификационными данными и другими секретными сведениями. А это значит, что программисты, работая с подобными данными, иногда могут совершать ошибки.
Рассмотрим практический пример утечки идентификационных данных, вписанных прямо в исходный код одной системы. Вот отчёт об ошибке, касающийся reverb.com. Исследователь обнаружил в коде идентификационные данные, используемые для доступа к Cloudinary. Секретный ключ присутствовал в исходном коде Android-приложения Reverb. Любой, кто загрузит это приложение, может извлечь соответствующие учётные данные и получить возможность, чтения, редактирования и удаления файлов, хранящихся в соответствующем экземпляре Cloudinary:
private static final java.lang.String CONFIG = "cloudinary://434762629765715:█████@reverb";
И подобные уязвимости — это вовсе не редкость. Я занимаюсь тестированием систем на устойчивость к проникновениям, и могу заявить, что мне доводилось находить в общедоступном коде или в скомпилированных файлах многих организаций самые разные секретные данные. Среди них — учётные данные для аутентификации в различных службах, ключи AWS, ключи к API GitHub. Иногда хакеру, который хочет взломать некую компанию, достаточно всего лишь поискать в её GitHub-репозитории случайно отправленные туда учётные данные для входа в различные системы.
Использование регулярных выражений
Как обнаруживать в коде секретные данные до того, как их попадание в общий доступ приведёт к утечке информации из организации? Самый простой и понятный способ поиска таких данных, жёстко внесённых в код, заключается в использовании инструментов текстового поиска и регулярных выражений.
Если в коде имеются ключи API, ключи шифрования, пароли к базам данных, их часто можно обнаружить, воспользовавшись инструментами для поиска ключевых слов, вроде grep. Искать, например, можно по словам key, secret, password или aws. При таком подходе осуществляется поиск по идентификаторам, вроде имён переменных, которые используются для хранения интересующих нас данных. Аналогично — можно пользоваться поиском по текстам для нахождения связанных с секретными данными имён файлов и служебных данных, характерных для файлов определённого формата. Например, можно поискать по строке -----BEGIN RSA PRIVATE KEY-----.
Многие ключи API, кроме того, записываются с использованием определённого формата данных. Обнаружить такие ключи можно, выполнив поиск с применением регулярных выражений. Например, идентификаторы ключей доступа к AWS обычно начинаются со строки AKIA, за которой следует 16 алфавитно-цифровых символов. Поэтому, если выполнить поиск с использованием регулярного выражения AKIA[0–9A-Z], можно обнаружить в коде соответствующие ключи.
Ключи для API Twilio начинаются с символов SK, за которыми следуют 32 алфавитно-цифровых символа. А это значит, что найти их можно с помощью регулярного выражения SK[a-z0–9]{32}. Пароли в URL можно обнаружить, выполнив поиск по шаблонам, соответствующим базовым синтаксическим конструкциям, используемым в соответствующих механизмах аутентификации: [a-zA-Z]{3,15}:\/\/[^\/\\]+:[^\/\\]+@.{1,100}. Благодаря использованию такого шаблона можно обнаружить учётные данные, включённые в состав URL: protocol://username:password@example.com. Для поиска секретных данных в собственном коде нужно выяснить то, как устроены используемые в коде ключи, после чего — составить регулярные выражения для их поиска.
Благодаря двум вышеописанным стратегиям поиска секретных данных в коде можно обнаружить основной объём таких данных. Но, полагаясь только на поиск по текстам, мы рискуем пропустить те секретные данные, которые не представлены строками определённого формата. Тут нам на помощь может прийти энтропийный анализ кода.
Поговорим об энтропии
Мы можем воспринимать энтропию как показатель того, насколько «случайными» и «непредсказуемыми» являются некие данные. Например, у строки, составленной лишь из одного символа, вроде aaaaa, показатель энтропии очень низок. А вот строка, в состав которой входит большее количество различных символов, наподобие wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY, обладает более высоким показателем энтропии. Проверить подобные строки и узнать о том, как вычисляется показатель энтропии, можно, воспользовавшись этим калькулятором энтропии Шеннона.
Применение показателя энтропии — это хороший способ поиска сильно рандомизированных, сложных строк. Вычисляя этот показатель для строковых литералов, применяемых в коде, можно обнаруживать подозрительные строки любого формата.
Что дальше?
Код, отправленный в общедоступные репозитории, нужно проверять на предмет случайного попадания в него секретных данных. Если нечто подобное попало в общий доступ — это имеет смысл считать украденным, соответствующие ключи, пароли, и прочее подобное нужно поменять.
Конечно, не весь код является опенсорсным, не все секретные данные, жёстко заданные в коде, попадают в общедоступные репозитории. Но подобная практика, всё равно, может вылиться в проблему, так как эти данные могут покинуть пределы компании в исполняемых файлах приложений, в виде логов, при краже исходного кода. Хорошей стратегией по минимизации рисков утечек секретных данных является выполнение сканирования кода с использованием поиска по шаблону и энтропийного анализа данных. Делается это до попадания кода в продакшн. А сами секретные данные нужно хранить либо в конфигурационных файлах, либо — пользуясь специальными службами, предназначенными для управления такими данными.
Иногда может показаться, что секретные данные просто необходимо хранить в коде, который, в виде приложения, попадает к конечным пользователям. Например — речь может идти о ключах API, используемых в мобильных приложениях. В подобном случае можно принять меры по предотвращению возможности обнаружения подобных данных. Например, переменным, в которых хранятся некие ключи, лучше не давать имена, недвусмысленно указывающие на их содержимое, вроде api_key и password. Рекомендуется обфусцировать код, что усложнит извлечение из него секретных данных. И, наконец, можно просто выполнять ту часть кода приложения, которая отвечает за доступ к сторонним службам, на сервере, что позволит избежать необходимости включения этого кода в состав пакета приложения, передаваемого конечному пользователю.
Всегда проверяйте свой код на предмет наличия в нём секретных данных и исследуйте возможности попадания этих данных в руки злоумышленников. Если такие данные попадают в код не по случайности, подумайте о том, действительно ли они должны присутствовать в коде, и о том, достаточно ли хорошо они защищены.
В результате могу сказать, что статический анализ — это самый надёжный способ обнаружения секретных данных, которые случайно попали в код.
Источник перевода
Автор оригинала: Vickie Li
Когда разработчики вносят прямо в исходный код секретные данные, вроде паролей и ключей API, эти данные вполне могут добраться до общедоступных репозиториев.
Я — разработчик, и я признаю то, что раньше допускала попадание секретных данных в открытые GitHub-репозитории. Подобные данные, жёстко заданные в коде, всегда были проблемой в различных организациях. Я, выполняя испытания на проникновение с целью проверки систем защиты компаний, всегда в первую очередь исследую код этих компаний на наличие в нём секретных данных. Если разработчик вносит что-то вроде паролей в код, эти данные могут оказаться в общедоступных репозиториях или в пакетах приложений, а после этого могут попасть в руки злоумышленников.
По мере того, как микросервисные архитектуры и приложения, построенные вокруг неких API, получают всё более и более широкое распространение, разработчики часто нуждаются в программных механизмах обмена идентификационными данными и другими секретными сведениями. А это значит, что программисты, работая с подобными данными, иногда могут совершать ошибки.
Рассмотрим практический пример утечки идентификационных данных, вписанных прямо в исходный код одной системы. Вот отчёт об ошибке, касающийся reverb.com. Исследователь обнаружил в коде идентификационные данные, используемые для доступа к Cloudinary. Секретный ключ присутствовал в исходном коде Android-приложения Reverb. Любой, кто загрузит это приложение, может извлечь соответствующие учётные данные и получить возможность, чтения, редактирования и удаления файлов, хранящихся в соответствующем экземпляре Cloudinary:
private static final java.lang.String CONFIG = "cloudinary://434762629765715:█████@reverb";
И подобные уязвимости — это вовсе не редкость. Я занимаюсь тестированием систем на устойчивость к проникновениям, и могу заявить, что мне доводилось находить в общедоступном коде или в скомпилированных файлах многих организаций самые разные секретные данные. Среди них — учётные данные для аутентификации в различных службах, ключи AWS, ключи к API GitHub. Иногда хакеру, который хочет взломать некую компанию, достаточно всего лишь поискать в её GitHub-репозитории случайно отправленные туда учётные данные для входа в различные системы.
Использование регулярных выражений
Как обнаруживать в коде секретные данные до того, как их попадание в общий доступ приведёт к утечке информации из организации? Самый простой и понятный способ поиска таких данных, жёстко внесённых в код, заключается в использовании инструментов текстового поиска и регулярных выражений.
Если в коде имеются ключи API, ключи шифрования, пароли к базам данных, их часто можно обнаружить, воспользовавшись инструментами для поиска ключевых слов, вроде grep. Искать, например, можно по словам key, secret, password или aws. При таком подходе осуществляется поиск по идентификаторам, вроде имён переменных, которые используются для хранения интересующих нас данных. Аналогично — можно пользоваться поиском по текстам для нахождения связанных с секретными данными имён файлов и служебных данных, характерных для файлов определённого формата. Например, можно поискать по строке -----BEGIN RSA PRIVATE KEY-----.
Многие ключи API, кроме того, записываются с использованием определённого формата данных. Обнаружить такие ключи можно, выполнив поиск с применением регулярных выражений. Например, идентификаторы ключей доступа к AWS обычно начинаются со строки AKIA, за которой следует 16 алфавитно-цифровых символов. Поэтому, если выполнить поиск с использованием регулярного выражения AKIA[0–9A-Z], можно обнаружить в коде соответствующие ключи.
Ключи для API Twilio начинаются с символов SK, за которыми следуют 32 алфавитно-цифровых символа. А это значит, что найти их можно с помощью регулярного выражения SK[a-z0–9]{32}. Пароли в URL можно обнаружить, выполнив поиск по шаблонам, соответствующим базовым синтаксическим конструкциям, используемым в соответствующих механизмах аутентификации: [a-zA-Z]{3,15}:\/\/[^\/\\]+:[^\/\\]+@.{1,100}. Благодаря использованию такого шаблона можно обнаружить учётные данные, включённые в состав URL: protocol://username:password@example.com. Для поиска секретных данных в собственном коде нужно выяснить то, как устроены используемые в коде ключи, после чего — составить регулярные выражения для их поиска.
Благодаря двум вышеописанным стратегиям поиска секретных данных в коде можно обнаружить основной объём таких данных. Но, полагаясь только на поиск по текстам, мы рискуем пропустить те секретные данные, которые не представлены строками определённого формата. Тут нам на помощь может прийти энтропийный анализ кода.
Поговорим об энтропии
Мы можем воспринимать энтропию как показатель того, насколько «случайными» и «непредсказуемыми» являются некие данные. Например, у строки, составленной лишь из одного символа, вроде aaaaa, показатель энтропии очень низок. А вот строка, в состав которой входит большее количество различных символов, наподобие wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY, обладает более высоким показателем энтропии. Проверить подобные строки и узнать о том, как вычисляется показатель энтропии, можно, воспользовавшись этим калькулятором энтропии Шеннона.
Применение показателя энтропии — это хороший способ поиска сильно рандомизированных, сложных строк. Вычисляя этот показатель для строковых литералов, применяемых в коде, можно обнаруживать подозрительные строки любого формата.
Что дальше?
Код, отправленный в общедоступные репозитории, нужно проверять на предмет случайного попадания в него секретных данных. Если нечто подобное попало в общий доступ — это имеет смысл считать украденным, соответствующие ключи, пароли, и прочее подобное нужно поменять.
Конечно, не весь код является опенсорсным, не все секретные данные, жёстко заданные в коде, попадают в общедоступные репозитории. Но подобная практика, всё равно, может вылиться в проблему, так как эти данные могут покинуть пределы компании в исполняемых файлах приложений, в виде логов, при краже исходного кода. Хорошей стратегией по минимизации рисков утечек секретных данных является выполнение сканирования кода с использованием поиска по шаблону и энтропийного анализа данных. Делается это до попадания кода в продакшн. А сами секретные данные нужно хранить либо в конфигурационных файлах, либо — пользуясь специальными службами, предназначенными для управления такими данными.
Иногда может показаться, что секретные данные просто необходимо хранить в коде, который, в виде приложения, попадает к конечным пользователям. Например — речь может идти о ключах API, используемых в мобильных приложениях. В подобном случае можно принять меры по предотвращению возможности обнаружения подобных данных. Например, переменным, в которых хранятся некие ключи, лучше не давать имена, недвусмысленно указывающие на их содержимое, вроде api_key и password. Рекомендуется обфусцировать код, что усложнит извлечение из него секретных данных. И, наконец, можно просто выполнять ту часть кода приложения, которая отвечает за доступ к сторонним службам, на сервере, что позволит избежать необходимости включения этого кода в состав пакета приложения, передаваемого конечному пользователю.
Всегда проверяйте свой код на предмет наличия в нём секретных данных и исследуйте возможности попадания этих данных в руки злоумышленников. Если такие данные попадают в код не по случайности, подумайте о том, действительно ли они должны присутствовать в коде, и о том, достаточно ли хорошо они защищены.
В результате могу сказать, что статический анализ — это самый надёжный способ обнаружения секретных данных, которые случайно попали в код.
Источник перевода