Site icon AppTractor

Не используйте токены, ключи и учетные данные в коде приложений

Некоторые разработчики считают свои мобильные приложения безопасным хранилищем.

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

Проблема рассмотрения скомпилированных мобильных приложений как безопасного хранилища вполне реальна. В этой статье утверждается, что 0.5% мобильных приложений содержат ключи AWS API, что приводит к раскрытию данных более 100 миллионов пользователей. Это число наверняка больше 0.5%, поскольку в этой статье рассматриваются только ключи AWS. Есть гораздо более важные ключи, которые не следует хранить непосредственно в коде, и вы можете найти множество статей, описывающих такие случаи. Также есть статьи CWE, описывающие эту тему.

Риск

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

Давайте посмотрим на несколько примеров.

  1. Ключи, обеспечивающие чтение данных из открытого бесплатного API
    В таких случаях нет реального риска, поскольку запросы API бесплатны, а хранимые данные являются общедоступными. Злоумышленник может сам сгенерировать такой ключ для себя, поэтому у него нет причин использовать ваш ключ.
  2. Ключи, обеспечивающие чтение  конфиденциальных данных
    Одним из лучших примеров здесь является ключ AWS API. Он может содержать разрешения на чтение, что позволяет злоумышленнику загрузить всю базу данных, хранящуюся там. В результате у вас будет утечка конфиденциальных данных и, как следствие, вы можете получить штраф за нарушение GDPR или других законов о защите персональных данных. Самый большой штраф за нарушение GDPR  на настоящий момент составил 50 миллионов евро.
  3. Ключи для доступа к SMS-шлюзам
    Представим себе службу, в которой злоумышленник может отправить SMS, используя ваш ключ, и подписать всю вашу службу на рассылку спама, который будет приносить ему деньги за ваш счет. Это может привести к потере крупных сумм за короткое время.
  4. Ключи для доступа к платежным сервисам
    Давайте рассмотрим приложение, в котором есть ключ, который позволяет отправлять деньги в биткойн-кошелек или из него. Злоумышленник может найти этот ключ и отправить все деньги с вашего счета или даже использовать его в качестве цепочки для отмывания денег.
  5. Серверный ключ облачных функций Firebase
    Из официальной документации:
    «Важно: не включайте ключ сервера в код клиента. Кроме того, убедитесь, что вы используете только серверные ключи для авторизации вашего сервера приложений. Ключи Android, iOS и браузерные отклоняются FCM».
    Используя серверный ключ облачных функций Firebase, злоумышленник может отправлять уведомления каждому пользователю приложения. Такие уведомления могут, например, содержать вредоносные ссылки и устанавливать вредоносные приложения.

Решение

Не храните ключи в коде.

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

Насколько сложно извлечь секретные данные из приложения?

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

С другой стороны, это может быть очень просто. Если в приложении нет обфускации, злоумышленник может автоматизировать поиск секретных ключей. После создания такого сценария злоумышленник сможет автоматически протестировать все приложения и найти множество таких секретных значений. Нужен будет только шаблон, который нужно будет искать. В простом сценарии можно будет создать словарь конфиденциальных ключевых слов, таких как key, secret и т.д., и искать эти строки внутри скомпилированного кода приложения или файлов, хранящихся внутри приложения, таких как plists или xml. Это простой и только один из многих сценариев. Другие сценарии могут быть действительно продвинутыми и покрывать лучше защищенные секреты. Вот почему так важно не хранить секретные ключи, которые могут вам навредить.

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

Android

Для Android вы можете ознакомиться с моими туториалами, в которых я объясняю все, от зондирования Android-приложений до создания автоматического скрипта Frida, который находит скрытые секреты на Uncrackable Level 1.

Вы также можете ознакомиться с другими руководствами в репозитории OWASP.

iOS

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

Ключ как переменная

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

private let topSecretKey = "top_secret_key_value"

Это самое простое решение для хранения секретного ключа в iOS, но его можно легко извлечь с помощью подходящего инструмента, например Hopper Disassembler..

Загрузите файл ipa в Hopper и нажмите кнопку Str в левом меню.

Затем найдите значение представленного ключа.

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

Ключ как массив Ints

Распространенным решением для хранения секретных строк является их шифрование и кодирование в массив Ints. Таким образом, мы не увидим их в разделе str в Hopper. Однако мы можем выполнить код класса, который его содержит, чтобы получить его свойства, используя инструмент динамического анализа, такой как Frida.

Для класса ObjC код Фриды будет выглядеть так:

var instance = ObjC.classes["ClassWithKeys"].alloc().init();
console.log("Class properties: " + instance["- _ivarDescription"]());

Он вернет нам все свойства и методы класса в String.

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

Резюме

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

Поэтому лучшее решение для хранения секретов — вообще не хранить их :)

Если вам нужно взаимодействовать со сторонним API, создайте для этого отдельную конечную точку на своем сервере.

Источник

Exit mobile version