Промт: Кот-хакер исследует трафик мобильного приложения
Промт: Кот-хакер исследует трафик мобильного приложения

Обычно я такими непотребствами не занимаюсь и уважаю частную жизнь приложений. Однако на днях мне довелось исследовать одно мобильное приложение написанное индусом в метро под 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

Не надо пробовать расшифровать весь трафик. Очень много адресов вас просто не поймут, потому что сертификат не будет надлежащим образом сформирован (а угодить всем невозможно). Также это не гарантирует, что в конкретном пакете не прописаны исключительные сертификаты, которым доверяет приложение. Поэтому, чтобы не было кучи ошибок, откройте приложение, посмотрите, какие запросы оно сгенерировало, и подпишите только эти точки входа. Затем можно перезайти в приложение.

Доступные действия

Когда мы завернули таким образом трафик, то мы можем делать следующее:

  • Расшифровать запросы и посмотреть заголовки и body каждого запроса.

  • Подменить запрос на сервер, чтобы подставить какие-то отличные данные.

  • Подменить содержимое ответа от сервера.

  • Повторить запрос с помощью cURL из системы (тем более имеем тот же адрес, что и android).

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

Итог

Мы рассмотрели то, как можно с помощью подготовленного окружения, собрать, расшифровать и исследовать трафик в Android. Уверен подобное можно провернуть и jailbreak-нутым iOS. Какие уроки можно из этого простого до безобразия примера извлечь?

  • Не доверяйте приложению на клиентской стороне, при разработке приложения. Особенно смешно видеть это со стороны frontend-разработчиков. Если ваше приложение содержит в себе хоть сколько угодно важную логику, то она должна быть на сервере. Более того, если с помощью вашего приложения пользователь получает какие-то привилегии или бенифиты (например, сертификация и тесты, после которых получается документ с подписью), то рано или поздно найдётся тот, кто автоматизирует на этом "чёрный бизнес".

  • Не полагайтесь на методику шифрования HTTP+TLS, потому что это лишь первая линия обороны. Сам протокол взломать довольно сложно (но тоже есть нюансы), но взломать устройства и провести MitM атаку возможно (мой пример про отладку).

  • Используйте все самые новые фишки безопасности (по возможности) в новых мобильных операционных системах. Хотя и это не гарантия, потому что можно перепаковать apk с собственными манифестами.

  • В некоторых случаях возможно разумно использовать нетекстовую сериализацию данных. Очень трудно отладить то, что невозможно прочитать. Но взломать это становится чуточку труднее. Мне довелось видеть некоторую разновидность msgpack, который gzip'али и подписывали на клиенте. Это конечно перебор, но может пригодиться.

Ещё раз повторюсь: эта статья не про взлом и даже не исследования безопасности. Этой статьёй я хочу помочь разработчикам клиентских приложений немного углубиться в матчасть передачи данных поверх HTTPS и оценить риски в своих приложениях.

Всем безопасного кодинга.

Комментарии (8)


  1. user18383
    12.04.2023 14:16
    +2

    А что если ssl pining стоит? Есть некоторые приложения с ним и нужно их патчить. Но некоторые приложения настолько закриптованы что это не представляется возможным


    1. onegreyonewhite Автор
      12.04.2023 14:16
      -1

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


      1. user18383
        12.04.2023 14:16
        -1

        Я немного про другое. Ssl pining это когда сертификат сервиса находится в самом приложении, и шифрование идёт только этим сертификатом. А этот сертификат может быть закриптован.


        1. onegreyonewhite Автор
          12.04.2023 14:16

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

          Скажем так, приведённый пример окружения ssl pining вполне может решить. Не решит это план Б исследователя: перепаковку приложения для проведения тщательного исследования.

          Есть более интересный способ, когда ответ от сервера имеет какие-то определённые признаки в самом пакете, которые после перепаковки пропадают из ответа или запроса. Эта техника применяется вполне успешно, но требует некоторых навыков. Стандартные инструменты в данном случае бессильны либо требуют знания алгоритма этих случайных данных. Я не писал лично код, который подобную технику защиты от MitM реализует, но разбирался в коде, где видел её реализацию. Это довольно изящное решение, потому что подменить сертификат даже зашифрованный можно в пакете. А вот подменить алгоритм уже требует полной пересборки или нехилых навыков.


  1. amakhrov
    12.04.2023 14:16

    Одна из причин, почему надо быть аккуратнее с VPN простым пользователям, — возможность делать с вашим трафиком всё что угодно

    Так HTTPS же никуда не делся при этом. При попытке завернуть трафик на свой сервис получим сообщение типа "сертификат подписан неизвестно кем, продолжить на свой страх и риск?".


    1. onegreyonewhite Автор
      12.04.2023 14:16

      Так будет, если сертификат самоподписан (при этом криво) и если залезть через браузер, и если сертификат не положили в хранилище доверенных (привет рутованым телефонам, плюс не забываем, что некоторые vpn могут законно потребовать положить сертификат), и если в пакете приложения не разрешено доверять пользовательским сертификатам. И много других если.

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


      1. amakhrov
        12.04.2023 14:16
        +1

        Думаю, готовы на многое.

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

        некоторые vpn могут законно потребовать положить сертификат

        А такие есть? Зачем они это делают?


        1. onegreyonewhite Автор
          12.04.2023 14:16

          Вообще чтоб авторизацию по сертификату производить. Но хранилище то же самое. Кажется Android даже не спрашивает для чего его использовать. Просто сертификат для vpn и приложений.