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

WARNING

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

 

Прежде чем начать

SSLPinning в мобильных приложениях реализуют, внедряя сертификат SSL в саму программу. При открытии защищенного соединения приложение не обращается в хранилище устройства, а использует свой сертификат. Это сразу же устраняет возможность направить трафик на Burp и анализировать его. Ведь для того, чтобы увидеть трафик SSL, нужно внедрить на устройство Burp CA, который бы подтвердил, что созданный Burp сервер валиден и ему можно доверять.

SSLPinning — это не панацея, очень часто появляются заметки про обход защиты на банковских приложениях или вообще про уязвимости в самом SSL. Но если защита построена правильно, то это создает огромные проблемы для исследователя.

Xposed представляет собой фреймворк, который внедряется в Zygote. Это происходит при старте системы, дальше от Zygote делается .fork(), что копирует Xposed во все запущенные процессы. Сам фреймворк предоставляет возможность внедрить любой код перед функцией и после нее. Можно изменить входящие параметры, заменить функцию, прочитать данные, вызвать внутренние функции и многое другое. На самом деле на описания и демонстрацию всех возможностей Xposed уйдет не одна статья. В общем, если ты раньше с ним не работал, рекомендую ознакомиться.

Для работы Xposed нам понадобится рутованный девайс. Для демонстрации атаки возьмем простое мобильное приложение, которое использует одну из самых часто встречающихся сетевых библиотек. В этом приложении отсутствует защита от SSLUnpinning, так как описанная мной атака не пытается атаковать сертификат и сетевое общение, а нацелена на перехват данных до покрытия их SSL. Для демонстрации серверной стороны атаки и бэкенда мобильного приложения используем быстрое решение в виде Python и Flask. Все исходники ты можешь найти на моем GitHub.

Вернемся к проблеме перехвата трафика SSL. С помощью Xposed можно попытаться отключить проверку сертификата, например «затереть» его для программы. Но предположим, атакуемое приложение хорошо защищено, бэкенд проверяет валидность защиты, детектирует попытки перехвата или проксирования трафика. Что делать в таком случае? Сдаться и заняться другим приложением? А что, если перехватить трафик еще до того, как он станет сетевым?

С этого вопроса началось мое исследование.

INFO

В статье я буду работать с Android и Xposed, но подобного результата можно добиться с помощью фреймворка Frida, который доступен и на других ОС.

 

Сбор информации

Для начала попробуем запустить приложение. Видим на экране кнопку SEND и текстовое приглашение ее нажать. Нажимаем — надпись меняется сначала на «Wait...», а после отображается «Sorry, not today». Скорее всего, отправляется запрос, который не проходит проверку на стороне сервера. Давай посмотрим, что происходит внутри приложения.

 

Реверс APK

Отреверсим приложение, чтобы понять, какие библиотеки используются внутри.

$ apktool d app-debug.apk

Открываем проект в Android Studio и смотрим, что есть в smali. Сразу видим okhttp3.

INFO

Я специально использовал OkHttp, так как эта библиотека лежит в основе других библиотек для работы с API, например Retrofit 2.

.method protected onCreate(Landroid/os/Bundle;)V

.line 34
iget-object v0, p0, Lcom/loony/mitmdemo/Demo;->sendButton:Landroid/widget/Button;

new-instance v1, Lcom/loony/mitmdemo/Demo$1;

invoke-direct {v1, p0}, Lcom/loony/mitmdemo/Demo$1;-><init>(Lcom/loony/mitmdemo/Demo;)V

invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

Найдем класс Main, в данном случае это com.loony.mitmdemo.Demo. В onCreate видим создание OnClickListener. Выше от него, через v1, передается как аргумент Demo$1. Посмотрим, что реализует этот класс.

.method public onClick(Landroid/view/View;)V

.line 41
.local v0, "sr":Lcom/loony/mitmdemo/Demo$SendRequest;
const-string v1, "test"

filled-new-array {v1}, [Ljava/lang/String;

move-result-object v1

invoke-virtual {v0, v1}, Lcom/loony/mitmdemo/Demo$SendRequest;->execute([Ljava/lang/Object;)Landroid/os/AsyncTask;

В конце функции onClick вызывается асинхронная задача, которая носит очевидное имя SendRequest. Перейдем в com/loony/mitmdemo/Demo$SendRequest. Здесь мы видим множество обращений к okhttp3. Значит, мы не ошиблись в предположении.

Здесь важный этап — это определение цели для перехвата. Выгодно выбрав функцию или класс, мы можем получить больше возможностей, чем при перехвате какого-либо другого объекта. Зачем, к примеру, перехватывать экземпляр публичного ключа, если можно перехватить все хранилище?

Посмотрим на стандартное применение okhttp3 в проектах Android.

OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, requestJson.toString());
Request request = new Request.Builder()
        .url(url)
        .post(body)
        .build();

Response response = client.newCall(request).execute();

Наиболее выгодным здесь будет перехват execute. Почему? Эта функция возвращает Response и, очевидно, отправляет Request. Это значит, что, перехватив эту функцию, мы получим возможность изменить Request до отправки и получить Response до возвращения в основную функцию.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


Check Also

Как учиться пентесту. Советы экспертов и авторов «Хакера»

Начинать что-то изучать всегда непросто, и для новых дисциплин вроде информационной безопа…

2 комментария

  1. Аватар

    AseN

    26.01.2019 at 18:58

    Интересно, какой смысл в демонстрации MiTM с помощью XPosed? Это не MiTM, а самообман 🙂
    А если основной посыл статьи (заголовок которой, вообще говоря, обещал демонстрацию обхода SSLPinning, а не перехвата HTTP-функций Java, но да ладно) показать обход пиннига на уровне OkHTTP, то frida-share уже содержит готовый сниппет обхода именно пиннига, демонстрирующий универсальный анпин без привязки к конкретному приложению, без танцев с (бубном)XPosed.

    Смысл, заложенный в статью, очень важен, но было бы гораздо интереснее, например, посмотреть технологию перехвата на уровне библиотек операционной системы, в которые в конечном счете уходит Java слой — до момента шифрования: SSL_write\SSL_read из openssl.so и до вызова функций из crypto.so.

    • Аватар

      loonydev

      30.01.2019 at 21:17

      В своей практике я встречал приложение, которое носило на борту очень хорошую защиту именно от анпина сертификата, так же, сразу детектировало frida и любые попытки вмешаться в трафик. С помощью Xposed и получилось обойти эту защиту, вмешиваясь в Java слой. Стоить отметить, что стандартные пакеты Xposed для анпина сертификата приводили к срабатыванию защиты. На основе этого взлома и появилась идея для статьи. Так же, хотелось показать, что можно не просто изменять входящие параметры функции, но и проводить замены целых объектов, создавая новые экземпляры.

      Согласен на счет перехвата данных внутри ssl библиотеки, это хорошая идея и возможно я как-то проверю/напишу об этом.

Оставить мнение