Есть разные подходы к анализу защищенности приложений, но рано или поздно все упирается в изучение взаимодействия программы с API. Именно этот этап дает больше всего информации о работе приложения, об используемых функциях и собираемых данных. Но что, если приложение защищено SSLPinning и защита реализована на уровне? Давай посмотрим, что можно сделать в этом случае.
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
SSLPinning в мобильных приложениях реализуют, внедряя сертификат SSL в саму программу. При открытии защищенного соединения приложение не обращается в хранилище устройства, а использует свой сертификат. Это сразу же устраняет возможность направить трафик на Burp и анализировать его. Ведь для того, чтобы увидеть трафик SSL, нужно внедрить на устройство Burp CA, который бы подтвердил, что созданный Burp сервер валиден и ему можно доверять.
SSLPinning — это не панацея, очень часто появляются заметки про обход защиты на банковских приложениях или вообще про уязвимости в самом SSL. Но если защита построена правильно, то это создает огромные проблемы для исследователя.
Xposed представляет собой фреймворк, который внедряется в Zygote. Это происходит при старте системы, дальше от Zygote делается .fork()
, что копирует Xposed во все запущенные процессы. Сам фреймворк предоставляет возможность внедрить любой код перед функцией и после нее. Можно изменить входящие параметры, заменить функцию, прочитать данные, вызвать внутренние функции и многое другое. На самом деле на описания и демонстрацию всех возможностей Xposed уйдет не одна статья. В общем, если ты раньше с ним не работал, рекомендую ознакомиться.
Для работы Xposed нам понадобится рутованный девайс. Для демонстрации атаки возьмем простое мобильное приложение, которое использует одну из самых часто встречающихся сетевых библиотек. В этом приложении отсутствует защита от SSLUnpinning, так как описанная мной атака не пытается атаковать сертификат и сетевое общение, а нацелена на перехват данных до покрытия их SSL. Для демонстрации серверной стороны атаки и бэкенда мобильного приложения используем быстрое решение в виде Python и Flask. Все исходники ты можешь найти на моем GitHub.
Вернемся к проблеме перехвата трафика SSL. С помощью Xposed можно попытаться отключить проверку сертификата, например «затереть» его для программы. Но предположим, атакуемое приложение хорошо защищено, бэкенд проверяет валидность защиты, детектирует попытки перехвата или проксирования трафика. Что делать в таком случае? Сдаться и заняться другим приложением? А что, если перехватить трафик еще до того, как он станет сетевым?
С этого вопроса началось мое исследование.
В статье я буду работать с Android и Xposed, но подобного результата можно добиться с помощью фреймворка Frida, который доступен и на других ОС.
Для начала попробуем запустить приложение. Видим на экране кнопку SEND и текстовое приглашение ее нажать. Нажимаем — надпись меняется сначала на «Wait…», а после отображается «Sorry, not today». Скорее всего, отправляется запрос, который не проходит проверку на стороне сервера. Давай посмотрим, что происходит внутри приложения.
Отреверсим приложение, чтобы понять, какие библиотеки используются внутри.
$ apktool d app-debug.apk
Открываем проект в Android Studio и смотрим, что есть в smali
. Сразу видим okhttp3
.
Я специально использовал 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 год7190 р. Экономия 1400 рублей! |
1 месяц720 р. 25-30 статей в месяц |
Уже подписан?
Читайте также
Последние новости