Нелегкий путь к динамическому анализу мобильных приложений

Привет, Хабр!

Каждую свою статью я начинаю с упоминания о том, что наша команда разрабатывает платформу анализа защищенности мобильных приложений. Почему? Размещая свои посты, информацию, которая мне кажется полезной, различные находки и трюки, мне хочется делиться с единомышленниками, помогать тем, кто идет по тому же пути, рассказывать об интересном. Я уверен, что не только у нас возникают трудности в процессе создания своих разработок, и здесь мы можем обменяться опытом. Сегодня мне хочется рассказать немного о том, с чем мы столкнулись в последние месяцы, работая над новым релизом нашего продукта. Возможно, это даст кому-то новый импульс, а может, кто-то даст нам совет со своей стороны. Мы открыты к общению!

00575d07da305e0ebc93897ad34ec190.jpg

Оглавление

Введение

Для начала, коротко о сути нашего решения. Платформа Стингрей — это динамический анализатор мобильных приложений. Основная его задача — смотреть на то, как приложение ведет себя на устройстве, к каким системным вызовам обращается, как общается с другими приложениями, что передает на сервер, как и что хранит локально и так далее. При этом, конечно, мы используем и статический анализ, и анализ ресурсов приложения, и многие другие техники. Все, что было описано в моих предыдущих статьях, основано на нашем опыте применения различных техник анализа приложений.

Мы стремимся к тому, чтобы нашим продуктом было легко и удобно пользоваться. Все, кто работает с разными сканерами, анализаторами и прочими инструментами по ИБ (даже не в контексте анализа мобильных приложений), знает, что с ними не так-то просто иметь дело! А нам хочется, чтобы в идеале даже люди, которые никогда не занимались анализом мобилок, могли загрузить приложение, потыкать мышкой в интерфейс и получить понятный отчет с реальными уязвимостями. Чтобы даже из коробки все работало максимально просто, быстро и качественно. Но при этом не забывать и о тех, кто хочет более тонко настроить инструмент и заточить его под себя и свои приложения. Но вот эта простота для пользователя, к которой мы стремимся, создает огромные сложности при разработке и проектировании системы. И наверняка кому-то из вас будет интересно «поднять капот» и посмотреть, как обстоит все внутри на самом деле.

Хотелось бы написать больше, но посмотрим, насколько такой формат повествования будет уместным. Если все будет хорошо, я обязательно напишу краткую историю трансформации нашего продукта и всех сложностей, с которыми мы столкнулись (, а их было достаточно). В начале нашего пути мой коллега, когда его просили описать, что из себя представляет наша система, отметил: «Можно сказать, мы собираем Python в Linux, развернутом внутри Android-эмулятора в Docker». Так было раньше и это было весело, но сейчас все намного интереснее.

Динамический анализ iOS

Довольно долгое время мы специализировались только на Android-приложениях. Это было логично и понятно, ведь Android-устройства более доступные, для них легче получить права суперпользователя, да и в целом система более открытая, есть эмуляторы и много других аспектов. Мы долго планировали добавить полноценную динамику iOS-приложений и несколько раз подступались к ней, но не хватало то времени, то компетенций. И вот, наконец, мы реализовали этот непростой сценарий, но по пути, конечно, набили немало шишек.

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

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

Процесс подготовки устройствПроцесс подготовки устройств

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

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

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

Я не буду сейчас рассказывать про архитектуру решения, которое мы спроектировали и реализовали, (думаю, это тема для отдельной статьи), но отмечу, что нам тоже пришлось поломать голову, как обеспечить постоянную работоспособность, удобство конфигурирования и администрирования всего «зоопарка» и завязать мониторинг в единую систему. Скажу лишь только, что профили устройств в iOS и pfSense совместно с Radius очень нам в этом помогли.

Полноценный IAST для Android-приложений

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

Как вы уже знаете, мы «держим руку на пульсе» и всегда прорабатываем все отчеты, writeup«ы, открытые баги в багбаунти-системах и еще львиную долю материалов, многие из которых я публикую, и у нас накопилось достаточно много уязвимостей, поиск которых мы хотели автоматизировать. Все это — реальные баги, которые можно реализовать на нерутованных устройствах, просто поставив рядышком приложение, а иногда и просто кликнув по ссылке. Это самые сложные и самые «вкусные» уязвимости, поиск которых мы всегда хотели добавить. Мы наметили ближайший план по автоматизации и уже начали точечно их реализовывать.

Классическая схема IASTКлассическая схема IAST

Но после добавления нескольких таких типов стало понятно, что процесс — очень трудоемкий и требует больших «костылей», да и в целом не сильно удобно. В итоге, мы откатились на предыдущее состояние системы, потратив много времени практически впустую. Это подстегнуло нас к попытке найти решение, которое бы упростило дальнейшее добавление новых типов уязвимостей и позволило бы нам абстрагироваться от конкретных проблем безопасности и применить некоторый «общий» подход к их поиску. В течение месяца мы пересмотрели и перепробовали много различных вариантов, исписав всю стену офиса и, после стольких бессонных ночей, кучи кода и экспериментов, нам это удалось.

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

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

Раньше такого рода системы и методики анализа мне встречались только для Web-приложений. Получается, что для мобильных приложений появился первый полноценный IAST-движок. Благодаря простой системе конфигурирования, добавление новых типов уязвимостей практически не занимает времени. Основное, чему приходится уделять внимание, — анализ проблем, понимание их сути и движения данных внутри. После того, как это сделано, достаточно написать пару строчек кода, построить связи и — вуаля — новая уязвимость добавлена и может быть проверена на сотне приложений, которые мы периодически разбираем.

Обновленный дизайн

Почему-то именно с UI у нас очень интересные взаимоотношения. Если вспомнить начало нашей истории, то самый первый вариант — это просто html, который мы генерировали на стороне сервера и отдавали в браузер. Второй версией стала моя покупка темы для Angular и разработка нового интерфейса, который был отделен от сервера и представлял собой полноценный SPA. Что сказать, это была одна из самых бесполезных покупок в моей жизни. Я вооружился скачанным курсом по Angular, новой купленной темой, которая практически сразу ушла в корзину, запасом энергетика и написал свой первый SPA, который просуществовал достаточно долго, пока мы не нашли толкового и выделенного разработчика под эти задачи. Посмотрев на тот ужас, что творился в коде, было решено переписать все практически с нуля и реализовать интерфейс, используя современные технологии и правильные подходы. Это привело нас к проектированию каждой страницы (правда ввиду ограниченности ресурсов на тот момент — на листочке в клеточку, но это не важно) и к последовательной их реализации. Как итог — мы получили стабильно работающий, хороший интерфейс, который просуществовал достаточно долго.

Три версии одного экранаТри версии одного экрана

На протяжении всей жизни этой версии мы собирали обратную связь от пользователей, подмечали различные неудобные моменты, и на основе всего этого сформировали неплохой список улучшений и пожеланий к новому интерфейсу. Изучив все фичи, которые нам хотелось бы реализовать, и взглянув на то, что есть у нас, мы решились на очередную авантюру — переписать и перерисовать «лицо» нашей системы практически полностью. По факту, единственное, что осталось неизменным, — это функционал по получению данных и работе с API. Все остальное (включая элементы интерфейса, даже кнопки, переключатели, шрифты, поля ввода, обработки файлов и картинок) переосмыслили, изменили и отрисовали вручную. Все переходы между экранами, весь «пользовательский путь» был переработан и переделан, наконец-то появилась полная адаптивность интерфейса под различные разрешения экрана. Все, чего не хватало прежде, появилось в новой версии. На самом деле, изменений столько, что в какой-то момент мы перестали их считать и записывать, а просто полностью ушли в работу.

В какой-то момент мне казалось, что наш фронтенд-разработчик меня ненавидит, но зато теперь использовать Стингрей не только удобно, но еще и визуально приятно и, в некоторых случаях, намного более очевидно и просто.

Интеграции

Наша команда прекрасно понимает, что без наличия интеграций со смежными системами, когда инструмент «стоит в стороне» от основной разработки, никакого полноценного процесса выстроить не получится.

Именно поэтому мы решили поразмыслить над добавлением новых способов получения приложений для анализа. Итогом стала возможность загружать и отправлять на анализ системы из Firebase, Google Play и App Store, но скольких седых волос нам это стоило.

При разработке этих интеграций было очень сложно сделать так, чтобы все не просто функционировало, а не сбоило, чтобы не возникало проблем. И ведь каждая система дистрибуции и магазин приложений реализует функционал загрузки по-своему, а кто-то специально его прячет или вообще не дает такой возможности.

Взять, к примеру, интеграцию с Firebase. Если зайти в Web-приложение, то там есть замечательная большая кнопка «Скачать дистрибутив». Но при этом никакого внешнего API для загрузки нет, не было и не планируется. Для того, чтобы все-таки реализовать возможность скачать приложение, пришлось изрядно потрудиться, изучить строение внутренних вызовов внутри Firebase, определить, как и на чем основывается аутентификация и авторизация в сервисах Google, понять, какие внутренние вызовы нужно совершить, с какими заголовками и много-много чего еще.

Казалось бы, разобрались с аутентификацией в Google, теперь можно и Play Store безболезненно подключить. Как бы не так! Судя по всему, разрабатывают их абсолютно разные команды с разными подходами и степенью продуманности интерфейсов. И все, что мы делали для Firebase, оказалось абсолютно неприменимо для интеграции с магазином приложений. Поэтому пришлось начинать все с чистого листа: изучать API, способы регистрации устройства и дальнейший процесс получения apk-файлов. В итоге, мы реализовали это функционал, но вот незадача — буквально на днях Google изменил процесс логина в магазин приложений, и теперь нам приходится снова искать варианты для обхода ограничений. Нужно снова смотреть трафик и понять, что же сделал Гугл.

С Apple AppStore, на удивление, возникло куда как меньше проблем, потому что нам удалось найти практически готовое решение, которые мы интегрировали в наш общий скрипт. Окрыленные успехом, мы замахнулись на святая святых, на загрузку файлов из системы дистрибуции TestFlight, на данный момент известную как Apple Connect. И тут нас ждал большой облом. Раньше, еще до переименования, в консоли TestFlight была замечательная кнопка по загрузке тестовых сборок, и можно было относительно легко ей воспользоваться, но сейчас, после того, как произошла реорганизация системы дистрибуции Apple, эту возможность убрали в принципе. Потратив несколько недель на поиск решения, оплатив разработческий аккаунт, пройдя через несколько кругов ада на подтверждение своих данных, зарегистрировавшись в нескольких программах, мы поняли, что варианта скачать приложение найти не можем. Заглянув в трафик приложения TestFlight, удалось поймать интересный запрос на загрузку ipa-файла, но при попытке установить загруженное приложение ничего не получалось. По итогу, мы пока не добавили эту интеграцию, но как только появится время, я думаю, мы попробуем вернуться к этому вопросу и все-таки попробовать заставить это работать.

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

Заключение

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

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

И, конечно, эта статья никогда бы не появилась без потрясающей команды, которая реализовала все, о чем написано, и много больше. Поэтому хотелось бы поблагодарить всех, кто приложил руку к созданию нашего продукта. Ребята, спасибо вам огромное, вы самая лучшая команда!

Всем спасибо за время и внимание, и до новых встреч!

© Habrahabr.ru