4 метода обхода верификации ssl-сертификатов в android
Прошли те времена, когда мобильные приложения мужественно игнорировали все ошибки, связанные с SSL, и позволяли перехватывать и модифицировать трафик.
Автор: Cody Wass
Прошли те времена, когда мобильные приложения мужественно игнорировали все ошибки, связанные с SSL, и позволяли перехватывать и модифицировать трафик. Современные приложения, как минимум, проверяют цепочки сертификатов на валидность и принадлежность к достоверному центру сертификации. Мы, пентестеры, ставим перед собой задачу «убедить» приложение, что сертификат надежный с целью выполнения атаки типа «человек посередине» и последующего изменения трафика. В этой статье будут рассмотрены следующие техники обхода проверок SSL-сертификатов в Android:
- Добавление сертификатов в хранилище достоверных сертификатов.
- Перезапись упакованных сертификатов.
- Использование скрипта Frida для обхода проверок SSL-сертификатов.
- Изменение кода проверки сертификата.
Некоторые из вышеуказанных техник – простые, другие – более сложные в реализации. Мы рассмотрим каждый из этих методов без особого углубления в специфические детали.
Зачем нужна MITM-атака на SSL
Чтобы просматривать и изменять вызовы веб-службы, используемой мобильным приложением, нам понадобится промежуточный прокси сервер для перехвата, созданный при помощи утилит навроде BurpSuite или ZAP. При перехвате SSL-трафика SSL-соединение прерывается на стороне прокси-сервера. Сертификат, отсылаемый прокси-сервером, анализируется мобильным приложением, как если бы прокси был оконечной точкой веб-службы. По умолчанию самоподписанный сертификат, генерируемые утилитами наподобие Burp, не будет принадлежать проверенной достоверной цепочке. Если сертификат нельзя проверить на достоверность, большинство мобильных будут обрывать соединение вместо того, чтобы подключаться и работать в потенциально незащищенном канале. Техники, представленные ниже, предназначены для одной цели – убедить мобильное приложение, что сертификат, отправляемый прокси-сервером, является достоверным.
Техника 1 – Добавление сертификата в хранилище пользовательских сертификатов
Самый простой способ избежать SSL-ошибок – обзавестись валидным и надежным сертификатом. Эта задача решается относительно просто, если вы сможете установить достоверный сертификат на устройство. Если операционная система доверяет вашему центру сертификации, то будет доверять и сертификату, подписанному центром сертификации.
В Android есть два встроенных хранилища сертификатов, которые отслеживают, каким центрам сертификации доверяет операционная система: системное хранилище (хранит предустановленные сертификаты) и пользовательское хранилище (хранит сертификаты, добавленные пользователями).
Выдержка с сайта developer.android.com:
По умолчанию безопасные соединения (использующие протоколы TLS, HTTPS и им подобные) во всех приложениях доверяют предустановленным системным сертификатам. В Android 6.0 (API level 23) и более ранних версиях по умолчанию также считаются достоверными сертификаты, добавленные пользователями. Приложение может настраивать свои собственные соединения на уровне приложения (base-config) и на уровне домена (domain-config).
Сей факт означает, что, если мы имеем дело с приложением, которое работает в Android 6.0 и более ранних версиях, то можно просто добавить сертификат в пользовательское хранилище. Когда приложение пытается проверить достоверность цепочки для нашего сертификата, то обнаружит, что наш центр сертификации связан с достоверным хранилищем и, следовательно, будет доверять нашему сертификату. В более новых версиях приложение не будет доверять хранилищу пользовательских сертификатов. Чтобы решить эту проблему, нужно прописать такой уровень API и версию Android, чтобы приложение стало доверять пользовательским центрам сертификации. Мы будем редактировать атрибут «platformBuildVersionCode» элемента «manifest» в файле AndroidManifest.xml.
<manifest xmlns:android=”http://schemas.android.com/apk/res/android" package=”com.test.app” platformBuildVersionCode=”25″ platformBuildVersionName=”7.1.1″>
В коде выше в строке «platformBuildVersionCode=25» нужно поменять значение 25 на 23, а в строке platformBuildVersionName=”7.1.1″ значение 7.1.1 на 6.0.
<manifest xmlns:android=”http://schemas.android.com/apk/res/android" package=”com.test.app” platformBuildVersionCode=”23″ platformBuildVersionName=”6.0“>
После переупаковки приложения с обновленным файлом AndroidManifest.xml, доверие пользовательским центрам сертификации будет восстановлено.
Если требуется запуск на конкретной версии платформы, мы можем определить тэг trust-anchors в файле «/res/xml/network_security_config.xml». Например, следующий файл (https://developer.android.com/training/articles/security-config.html) определяет новый достоверный сертификат, который должен храниться по адресу /res/raw/my_ca.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="@raw/my_ca"/> </trust-anchors> </base-config> </network-security-config>
Если в приложении будет проходить проверку только указанный сертификат, условия для успешного выполнения этой техники выполняются.
Техника 2 – Перезапись упакованного сертификата
Если после установки сертификата в пользовательское хранилище, изменении в настройках версии Android и успешном прохождении проверок при просмотре других ресурсов, защищенных протоколом SSL, все равно возникают ошибки, значит, разработчики внедрили дополнительные условия, которым должны удовлетворять достоверные центры сертификации. Если не забыли, в предыдущей технике внутри тэга trust-anchors добавлялся новый путь к сертификату. Подобный трюк может использоваться разработчиками для защиты приложений от перехвата SSL.
Если в приложении используется индивидуальная цепочка сертификатов, может сработать метод, связанный с перезаписью сертификата. Поскольку в некоторых случаях разработчики могут предусмотреть дополнительные методы для проверки достоверной цепочки, эта техника не гарантирует стопроцентного результата.

Рисунок 1: Перечень сертификатов, используемых приложением
Если открыть пакет приложения при помощи, например, APK Studio, то можно сразу увидеть перечень привязанных сертификатов. На картинке выше сертификаты находятся в папке «assets». Замена явно бросающегося в глаза сертификата UniversalRootCA позволит нам подсунуть приложению наш сертификат.
Техника 3 – Подключение к функциям через фреймворк Frida
Если установки собственного сертификата недостаточно для успешного перехвата SSL-трафика, скорее всего, в приложении используются техники навроде SSL pinning или дополнительная SSL-валидация. В этом случае нужно блокировать проверки через непосредственное подключение к соответствующим функциям. Ранее эта техника была доступна для реализации только на устройствах с правами суперпользователя. Однако на данный момент при помощи библиотеки Frida Gadget можно работать с приложением и получить доступ к полному функционалу фреймворка Frida без прав суперпользователя.
Если вы уже выполняли пентесты мобильных приложений, то, вероятно, знакомы с этим фреймворком. Описание всей функциональности Frida выходит за рамки этой статьи, но если говорить в общем, то этот фреймворк позволяет изменять логику работы приложения во время выполнения. Обычно Frida работает как отдельное приложение и требует прав суперпользователя на устройстве. Если у нас нет прав суперпользователя, мы можем инжектировать в пакет приложения динамическую библиотеку Frida Gadget, содержащую большую часть функционала фреймворка Frida. Эта библиотека загружается во время выполнения приложения и позволяет вносить изменения в код.
Чтобы загрузить Frida Gadget, нужно распаковать APK, вставить динамическую библиотеку, отредактировать smali-код так, чтобы динамическая библиотека вызывалась самой первой, а затем переупаковать и установить пакет. Весь этот процесс хорошо задокументирован Джоном Козиракисом (John Kozyrakis). Вначале лучше пройти все этапы вручную, чтобы лучше понять, как работает эта технология. Чтобы сэкономить время, существует утилита – Objection, которая автоматизирует весь вышеупомянутый процесс. Требуется лишь указание целевого пакета, над которым нужно выполнить манипуляции.
C: >objection patchapk -s test_app.apk No architecture specified. Determining it using `adb`... Detected target device architecture as: armeabi-v7a Github FridaGadget is v10.6.28, local is v10.6.13. Updating... Downloading armeabi-v7a library to C:.objectionandroidarmeabi-v7alibfrida-gadget.so.xz... Unpacking C:.objectionandroidarmeabi-v7alibfrida-gadget.so.xz... Cleaning up downloaded archives... Using Gadget version: 10.6.28 Unpacking test_app.apk App already has android.permission.INTERNET Reading smali from: C:Temptmp8dxqks1u.apktempsmalicom/test/app/TestMainActivity.smali Injecting loadLibrary call at line: 10 Writing patched smali back to: C:Temptmp8dxqks1u.apktempsmalicom/test/app/TestMainActivity.smali Creating library path: C:Temptmp8dxqks1u.apktemplibarmeabi-v7a Copying Frida gadget to libs path... Rebuilding the APK with the frida-gadget loaded... Built new APK with injected loadLibrary and frida-gadget Signing new APK. jar signed. Signed the new APK Performing zipalign Zipaling completed Copying final apk from C:UserscwassAppDataLocalTemptmp8dxqks1u.apktemp.aligned.objection.apk to current directory... Cleaning up temp files...
После завершения в нашей рабочей директории должен появиться файл «test_app.objection.apk». По умолчанию утилита objection добавляет постфикс «.objection» к имени пакета. Далее мы можем установить этот пакет так же, как и любой другой APK, при помощи команды adb install test_app.objection.apk. После того как измененный пакет установлен на целевом устройстве, во время запуска приложение должно встать на паузу на начальном экране. В этот момент мы можем подключиться к серверу Frida, который отслеживает наше устройство:
C:>frida-ps -U
PID Name
—- ——
6383 Gadget
C:>frida -U gadget
____
/ _ | Frida 10.3.14 – A world-class dynamic instrumentation framework
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about ‘object’
. . . . exit/quit -> Exit
. . . .
. . . . More info at http://www.frida.re/docs/home/
[Motorola Moto G (5) Plus::gadget]-> Java.available
true
Alternatively, Objection supports interaction with the listening Frida server by using the ‘explore’ command:
C:>objection explore
___| |_ |_|___ ___| |_|_|___ ___
| . | . | | | -_| _| _| | . | |
|___|___|_| |___|___|_| |_|___|_|_|
|___|(object)inject(ion) v1.2.2
Runtime Mobile Exploration
by: @leonjza from @sensepost
[tab] for command suggestions
com.test.app on (motorola: 7.0) [usb] # android hooking search classes TrustManager
android.security.net.config.RootTrustManager
android.app.trust.ITrustManager$Stub$Proxy
android.app.trust.ITrustManager
android.security.net.config.NetworkSecurityTrustManager
android.security.net.config.RootTrustManagerFactorySpi
android.app.trust.TrustManager
android.app.trust.ITrustManager$Stub
com.android.org.conscrypt.TrustManagerImpl
com.android.org.conscrypt.TrustManagerImpl$ExtendedKeyUsagePKIXCertPathChecker
com.android.org.conscrypt.TrustManagerImpl$TrustAnchorComparator
com.android.org.conscrypt.TrustManagerFactoryImpl
javax.net.ssl.TrustManagerFactory$1
javax.net.ssl.TrustManager
javax.net.ssl.TrustManagerFactory
javax.net.ssl.X509TrustManager
javax.net.ssl.TrustManagerFactorySpi
javax.net.ssl.X509ExtendedTrustManager
[Ljavax.net.ssl.TrustManager;
Теперь вы можете воспользоваться функцией для обхода технологии SSL pinning:
com.test.app on (motorola: 7.0) [usb] # android sslpinning disable
Job: 2f633f86-f252-4a57-958e-6b46ac8d69d1 – Starting
[6b46ac8d69d1] [android-ssl-pinning-bypass] Custom, Empty TrustManager ready
Job: 2f633f86-f252-4a57-958e-6b46ac8d69d1 – Started
Техника 4 – Реверс-инжиниринг кода верификации сертификата
Возможен такой случай, когда разработчик использует собственные SSL-библиотеки вместо системных для верификации сертификата. В этой ситуации нам нужно распаковать пакет, сконвертировать smali-код в Java-код и найти функции, отвечающие за проверку сертификата.
Если использовать «dex2jar», синтаксис будет следующим:
C:>d2j-dex2jar.bat “C:test_app.apk”
dex2jar C:test_app.apk -> .test_app-dex2jar.jar
Полученный файл .jar должен быть пригоден для открытия в вашей любимой утилите для исследования Java-приложений (например, JD-GUI).
После того как вы нашли функции, отвечающие за проверку сертификата, можно либо полностью пропатчить код, либо подцепиться к нужной функции при помощи Frida. Чтобы сэкономить время и не пересобирать полностью приложение, эффективнее подцепиться к функциям, отвечающим за проверку сертификата. Шаги, описанные в предыдущей технике, позволят подключиться к приложению, и далее вы можете либо подцепиться к функции при помощи утилит фреймворка Frida, либо при помощи приложения Objection.
Заключение
Техники, описанные в этой статье, позволяют перехватывать SSL-трафик и обходить некоторые наиболее распространенные защиты, используемые разработчиками. Кроме того, я кратко рассказал об утилите Objection и фреймворке Frida. Обход технологии SSL pinning и других защит лишь небольшая часть возможностей, которые позволяют реализовать эти инструменты.
Надеюсь, мне удалось на доступном языке рассказать о техниках, которые могут быть пригодны для оценки безопасности мобильных Android-приложений и демонстрируют важность наличия нескольких способов проведения подобного рода исследований.
Инструкция по настройке шлюза удаленных рабочих столов
Для того чтобы повысить уровень безопасности Windows-сервера бывает недостаточно сменить TCP-порт RDP . Рассмотрим настройку шлюза удаленных рабочих столов (Remote Desktop Gateway / Terminal Services Gateway) в домене Active Directory.
Remote Desktop Gateway, что это?
Remote Desktop Gateway – это роль Windows-сервера, обеспечивающая защищенное соединение, с помощью протокола SSL, с сервером по RDP. Главное преимущество этого решения в том, что не требуется развертывание VPN-сервера, для этого и используется шлюз.
Следует отметить, что начиная с Windows Server 2008 R2, были изменены названия всех служб удаленных рабочих столов. Именуемые ранее службы Terminal Services были переименованы в Remote Desktop Services.
Преимущества Remote Desktop Gateway в следующем:
- Используя зашифрованное соединение, шлюз позволяет подключаться к внутренним сетевым ресурсам без необходимости использования VPN-соединения удаленными пользователями;
- Шлюз дает возможность контроля доступа к определенным сетевым ресурсам, тем самым реализуя комплексную защиту;
- Шлюз разрешает подключение к сетевым ресурсам, которые размещены за межсетевыми экранами в частных сетях или NAT;
- С помощью консоли диспетчера шлюза появляется возможность настраивать политики авторизации для тех или иных условий, которые должны быть выполнены при подключении к сетевым ресурсам удаленными пользователями. В качестве примера, можно указать конкретных пользователей, которые могут подключаться к внутренним сетевым ресурсам, а также должен ли клиентский компьютер при этом быть членом группы безопасности AD, допустимо ли перенаправление устройства и диска;
- Консоль диспетчера шлюза содержит инструменты, предназначенные для отслеживания состояния шлюза. Используя их, вы можете назначить отслеживаемые события для аудита, например, неудачные попытки подключения к серверу шлюза служб терминалов.
Важно! Шлюз служб терминалов должен входить в домен Active Directory. Настройка шлюза выполняется только от имени администратора домена, на любом сервере в домене.
Установим роль.
Открываем Диспетчер серверов.
Выбираем “Добавить роли и компоненты”.
На этапе “Тип установки”, выбираем “Установка ролей и компонентов”.
Следующим шагом выбираем текущий сервер.
Роль сервера – Служба удаленных рабочих столов.
Переходим к службе ролей. Выбираем “Шлюз удаленных рабочих столов”.

Переходим к этапу подтверждения, нажимаем кнопку “Установить”.
Настройка политики авторизации подключения и ресурсов.

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

В открывшемся окне “Мастер создания новых политик авторизации” выбираем рекомендуемый параметр “Создать политику авторизации подключений к удаленным рабочим столам и авторизации ресурсов удаленных рабочих столов”. Нажимаем кнопку “Далее”.

На следующем шаге вводим удобное имя для политики авторизации подключения. Мы рекомендуем давать имена на английском языке.


В окне выбора групп кликаем по кнопке “Дополнительно”.

Окно изменит размеры. Нажимаем кнопку “Поиск”. В результатах поиска находим “Администраторы домена” и нажимаем кнопку “OK”.

В окне выбора группы проверяем выбранные имена объектов и нажимаем “OK”.

Группа добавлена. Для перехода к следующему шагу нажимаем кнопку “Далее”.

На следующем этапе выбираем пункт “Включить перенаправление устройств для всех клиентских устройств” и нажимаем “Далее”.

Устанавливаем таймауты – время простоя и время работы сессии, значения указаны в часах. Нажимаем “Далее”.

Проверяем выполненные настройки. Все правильно – нажимаем “Далее”.

На следующем этапе настроим политику авторизации ресурсов. Указываем желаемое имя политики. Нажимаем “Далее”.

Следующим шагом установим членство в группах. Обычно, группа уже установлена, но если это не выполнено, следует выполнить действия приведенные выше. Нажимаем “Далее”.

Выбираем доступные сетевые ресурсы. Для этого необходимо выбрать группу, которая содержит серверы на которых требуемые группы пользователей могли бы работать с удаленным рабочим столом. Нажимаем кнопку “Обзор”.

В окне выбора группы, нажимаем кнопку “Дополнительно”.

В измененном окне нажимаем кнопку “Поиск”. В окне результатов находим “Контроллеры домена”. Нажимаем “OK”.

Проверяем выбранные объекты и нажимаем “OK”.

Еще раз проверяем какая сетевая группа добавлена и нажимаем “Далее”.

Если номер RDP-порта неизменялся, устанавливаем значение переключателя в “Разрешить подключение только к порту 3389”. Если порт был изменен, следует указать новое значение.

Кликаем “Готово”

На этапе подтверждения создания политики нажимаем кнопку “Закрыть”.

По окончании настройки окно будет выглядеть подобным образом.

Установим SSL-сертификат.
В том же окне “Диспетчер шлюза удаленных рабочих столов”, в левой окна кликаем по значку сервера, в основной части окна – “Просмотр и изменение свойств сертификата”.

В открывшемся окне “Свойства <имя_сервера>” переходим на вкладку “Сертификат SSL”. Устанавливаем переключатель “Создать самозаверяющий сертификат” и кликаем по кнопке “Создать и импортировать сертификат…”.
Хотя возможны еще 2 варианта:
- импорт ранее загруженного сертификата (самоподписанного ранее или стороннего);
- загрузка стороннего сертификата (например, Comodo) и его импорт;

В окне “Создание самозаверяющего сертификата” проверяем параметры и нажимаем кнопку “OK”.

Система уведомит, что сертификат был создан успешно. также присутствует информация, где можно найти сам файл сертификата. Нажимаем кнопку “OK”.

В окне свойств сервера, нажимаем кнопку “Применить”.

Самозаверенный сертификат установлен на TCP-порт 443 (SSL-порт по умолчанию).

Мы рекомендуем, в целях безопасности, изменить порт SSL, используемый по-умолчанию. Для этого, в основном меню окна, выбираем “Действия” → “Свойства”.

Переходим на вкладку “Параметры транспорта” и устанавливаем желаемое значение поля “HTTPS-порт”. Сохраняем параметры нажимая кнопку “Применить”.

Система запросит подтверждение – отвечаем ”Да”.

Выполним подключение через шлюз.
Открываем RDP-клиент, переходим на вкладку “Дополнительно” и нажимаем кнопку “Параметры”.

В открывшемся окне выбираем “Использовать следующие параметры сервера шлюза удаленных рабочих столов”. Указываем доменное имя сервера и через двоеточие (:) указываем SSL-порт. Метод входа – “Запрашивать пароль”. Нажимаем “OK”

Переходим на вкладку “Общие”. Указываем адрес компьютера и пользователя под которым будет выполняться подключение. Нажимаем кнопку “Подключить”

Программа запросит пароль от учетной записи.

Результаты работы шлюза можно проверить трассировкой – команда tracert.
