![Промт: Кот-хакер исследует трафик мобильного приложения Промт: Кот-хакер исследует трафик мобильного приложения](https://habrastorage.org/getpro/habr/upload_files/dd4/612/e28/dd4612e2863e5ecf0489269a11efe396.png)
Обычно я такими непотребствами не занимаюсь и уважаю частную жизнь приложений. Однако на днях мне довелось исследовать одно мобильное приложение написанное индусом в метро под iOS, а затем адаптированное под Android пьяным студентом «в комнате раздумий». Все действия выполнялись с целью дебага и понимания оптимальных условий для работы. Само приложение мы анализировать не будем, но подготовим среду для проведения исследований.
Эта статья не про взлом и даже не исследование безопасности. Этой статьёй я хочу помочь разработчикам клиентских приложений немного углубиться в матчасть передачи данных поверх HTTPS и оценить риски в своих приложениях.
Самая главная проблема исследования https‑трафика с мобильных приложений это флаг, который сообщает системе, что не собирается доверять всяким пользовательским центрам сертификации. Второй проблемой является нежелание и игнорирование настроек прокси приложениями (во всяком случае на Android 9–11 так и было).
Для чего это может понадобиться? Ну например, чтобы убедиться, что приложение не отправляет лишних данных о вас, что особенно будет интересно безопасникам. А ещё для реверс‑инжиниринга структуры API и понимания, как можно интегрироваться или автоматизировать какие‑то процессы. Тут на Хабре много юристов специализирующихся на ИТ, поэтому можно обратиться к ним, чтобы уточнить законность тех или иных действий. Самое главное, вы можете исследовать собственные приложения на предмет того, что они работают корректно.
Итак, приступим.
Матчасть
Каждое приложение в Android или iOS имеет возможность отправлять некоторые запросы в API. Да, я кэп, но есть нюанс, почему всё меньше разработчиков поддерживают старые версии ОС (для андроид всё что старше 7ой версии). Дело в том, что там появилась возможность указывать в манифесте пакета, что именно это приложение не будет доверять центрам сертификации, которые пользователь внёс вручную. С одной стороны, это защищает пользователя от взлома, например, банковских приложений, становится невозможно перехватить токен авторизации и через запросы вывести все деньги на свои офшоры. Или же это защищает пользователя от недобросовестных сотрудников ИБ, которые будут лезть в переписки в мессенджерах. Но есть и другая сторона медали. Пользователь теряет контроль над своим трафиком, становятся недоступны некоторые возможности кеширующих прокси и т. п.
В целом, мобильные операционные системы позволяют настроить прокси‑сервер для большинства подключений. Конкретно в Android это настраивается внутри подключения к Wi‑Fi без каких‑то сложностей. Однако эти настройки применимы только для части приложений, таких как Chrome и ему подобных. Единственный способ, которым можно заставить все приложения отправлять трафик на нужный и подконтрольный вам сервер, — это VPN. Одна из причин, почему надо быть аккуратнее с VPN простым пользователям, — возможность делать с вашим трафиком всё что угодно. Поэтому предупредите своих не смыслящих в сетях и протоколах друзей, что использование банковских приложений поверх VPN подключений, которые вы не контролируете, — зло в чистом виде.
Чтобы провести MitM‑атаку, нужно собрать достаточно пакетов, чтобы перехватить ключи, которыми сервер с клиентом обмениваются в момент рукопожатия TLS. Весь дальнейший трафик этого соединения считается скомпрометированным.
Вот тут я немного "плаваю".
Это не совсем так. В этом плане HTTP/1.1 проявляет себя с лучшей стороны, потому что соединение устанавливается в большинстве случаев на каждый запрос (keepalive не считается).
HTTPS работает по такому принципу:
Устанавливается tcp-соединение.
Сервер и клиент обмениваются поверх асимметричного шифрования ключами для симметричного шифрования.
Делается обмен данными, зашифрованными симметричными ключами.
Закрывается соединение и симметричные ключи протухают.
HTTP/2 в отличии от HTTP/1.1 подразумевает сохранение соединения в целях экономии времени на рукопожатиях TLS.
Я не могу утверждать, что я достаточно глубоко разбираюсь в этом вопросе, чтобы давать экспертную оценку. Просто изучите этот вопрос, а если знаете, научите нас всех в комментариях с пруфами на стандарт протокола.
Но на самом деле это очень сложный процесс с перехватом и вычленением данных. Можно с помощью некоторой магии (всего одной переменной окружения) заставить браузер писать ключи симметричного шифрования в файл, но это не подходит для мобильных приложений.
Самым простым способом является возможность внедрить свой сертификат центра сертификации в список системных. И вот тут все рутованые телефоны открывают свои чресла...
Инструментарий
Самый главный инструмент для нашего исследования - это любая MitM-прокси, поддерживающая SOCKS5. Мне было удобно использовать Charles Proxy. Были некоторые проблемы с mitmproxy, потому что я не смог подобрать оптимальные настройки для конкретных приложений. Плюс там я встретил багу, связанную с TLS, из-за которой проще было взять CP. Подбирайте инструмент так, чтобы вы смогли его настроить и могли удобно смотреть трафик. Главное получать драйв от проделанной работы, а не мучить себя заточкой инструментов.
Второй инструмент - любой Android с доступом к root. Для целей исследования можно установить Android 9 x86 на виртуальную машину (qemu вполне подойдёт). Чтобы попасть в cli-интерфейс, достаточно зажать Alt+F1.
Чтобы завернуть трафик с андроида на вашу машину, есть два подхода:
Можно через usb-подключение с включённым режимом отладки завернуть весь трафик через свой комп (проект Gnirehtet), предварительно настроив маршрутизацию через proxy с помощью tun2proxy. Это какой-то особенный способ извращения, но он вполне рабочий. Из плюшек - можно смотреть весь трафик с помощью wireshark, даже не HTTP.
Можно поставить tun2socks из PlayMarket и завернуть весь трафик в VPN подключение, которое обернёт трафик в SOCKS5 проксю. Из минусов, что доступ к прокси не должен пересекаться с остальными маршрутами. Но большего и не нужно для исследователя.
Также нам понадобится сертификат центра сертификации, который мы сделаем системно доверенным и openssl, чтобы... задать ему правильное имя в системе. Для Charles Proxy вполне подойдёт её стандартный сертификат. Его можно найти в ~/.charles/ca/charles-proxy-ssl-proxying-certificate.cer
.
Можно сгенирировать свой, но он должен обладать всеми необходимыми флагами, что очень трудно для ленивого мамкиного хацкера исследователя безопасности.
Также может пригодиться любая версия Python с модулем http, чтобы быстро поднять свой http-сервер. Но у вас может быть любой другой сервер для статики.
Настройка окружения
Процесс установки Андроида в виртуалку описывать я не буду. Нам нужно установить приложение для исследования и tun2socks на наше устройство, что тоже не должно вызвать проблем. Сеть можете настроить простым NAT от системы виртуализации.
Сертификат необходимо подготовить. В системе он должен иметь имя соответствующее его [subject_hash_old].0
. Лучше это сделать на целевой машине, потому что в Android инструментария openssl вы не найдёте.
openssl x509 -inform PEM -subject_hash_old -in ~/.charles/ca/charles-proxy-ssl-proxying-certificate.cer | head -n -1
Первая строка вашего output как раз и будет нужной информацией. Копируем файл в любую директорию с переименованием:
cp -v ~/.charles/ca/charles-proxy-ssl-proxying-certificate.cer ~/mitm-test/32a6d529.0
В этой же директории можно поднять web-сервер со статикой. В принципе кроме этого файла нам ничего не понадобится.
Далее, заходим в наш Android и переходим в его консоль. Нам необходимо перемонтировать системный раздел в режиме записи, выкачать наш сертификат в директорию с сертификатами с такими же уродливыми названиями, назначить ему все необходимые права, и перемонтироваться назад. Спасибо добрым людям, которые подсказали, как это правильно делать.
mount -o rw,remount,rw /system
cd /system/etc/security/cacerts/
wget http://мой-сервер-ip:8000/32a6d529.0
chown root:root /system/etc/security/cacerts/*
chmod 644 /system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
mount -o ro,remount,ro /system
Там написано, что нужно не делать reboot, но у меня только после него заработало как надо.
Далее, мы запускаем наш прокси, указываем ему, на какие адреса необходимо подменять сертификат, и запускаем tun2socks. В tun2socks мы указываем адрес нашей прокси, порт и нажимаем start connect. Он поднимет VPN соединение до самого себя, а само приложение будет транслировать трафик до прокси.
![Интерфейс tun2socks Интерфейс tun2socks](https://habrastorage.org/getpro/habr/upload_files/19f/0bc/c19/19f0bcc19b09218609626e38426ecc13.png)
Не надо пробовать расшифровать весь трафик. Очень много адресов вас просто не поймут, потому что сертификат не будет надлежащим образом сформирован (а угодить всем невозможно). Также это не гарантирует, что в конкретном пакете не прописаны исключительные сертификаты, которым доверяет приложение. Поэтому, чтобы не было кучи ошибок, откройте приложение, посмотрите, какие запросы оно сгенерировало, и подпишите только эти точки входа. Затем можно перезайти в приложение.
Доступные действия
Когда мы завернули таким образом трафик, то мы можем делать следующее:
Расшифровать запросы и посмотреть заголовки и body каждого запроса.
Подменить запрос на сервер, чтобы подставить какие-то отличные данные.
Подменить содержимое ответа от сервера.
Повторить запрос с помощью cURL из системы (тем более имеем тот же адрес, что и android).
Это не исчерпывающий список возможностей, но достаточно полный, чтобы понять насколько становится уязвимым устройство, в котором подкинут ненадёжный сертификат центра сертификации. Однако, это позволяет заглянуть в трафик нашего приложения и отладить его работу в тех условиях, которые у нас есть. Также это позволяет увидеть некоторые векторы атаки на приложение, потому как само приложение не может гарантировать нам надёжность порядка и данных запросов к нашему API.
Итог
Мы рассмотрели то, как можно с помощью подготовленного окружения, собрать, расшифровать и исследовать трафик в Android. Уверен подобное можно провернуть и jailbreak-нутым iOS. Какие уроки можно из этого простого до безобразия примера извлечь?
Не доверяйте приложению на клиентской стороне, при разработке приложения. Особенно смешно видеть это со стороны frontend-разработчиков. Если ваше приложение содержит в себе хоть сколько угодно важную логику, то она должна быть на сервере. Более того, если с помощью вашего приложения пользователь получает какие-то привилегии или бенифиты (например, сертификация и тесты, после которых получается документ с подписью), то рано или поздно найдётся тот, кто автоматизирует на этом "чёрный бизнес".
Не полагайтесь на методику шифрования HTTP+TLS, потому что это лишь первая линия обороны. Сам протокол взломать довольно сложно (но тоже есть нюансы), но взломать устройства и провести MitM атаку возможно (мой пример про отладку).
Используйте все самые новые фишки безопасности (по возможности) в новых мобильных операционных системах. Хотя и это не гарантия, потому что можно перепаковать apk с собственными манифестами.
В некоторых случаях возможно разумно использовать нетекстовую сериализацию данных. Очень трудно отладить то, что невозможно прочитать. Но взломать это становится чуточку труднее. Мне довелось видеть некоторую разновидность msgpack, который gzip'али и подписывали на клиенте. Это конечно перебор, но может пригодиться.
Ещё раз повторюсь: эта статья не про взлом и даже не исследования безопасности. Этой статьёй я хочу помочь разработчикам клиентских приложений немного углубиться в матчасть передачи данных поверх HTTPS и оценить риски в своих приложениях.
Всем безопасного кодинга.