УДК 519.612:632.4
Я. А. Александров, Л. К. Сафин2, К. Н. Трошина3, А. В. Чернов4
СТАТИЧЕСКИЙ БИНАРНЫЙ АНАЛИЗ МОБИЛЬНЫХ ПРИЛОЖЕНИЙ ДЛЯ ПЛАТФОРМЫ ANDROID ПО ТРЕБОВАНИЯМ ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ
В данной статье представлен подход к решению задачи автоматического анализа мобильных приложений для платформы Android на предмет соответствия требованиям информационной безопасности при отсутствии исходного кода.
Ключевые слова: статический анализ, бинарный анализ, безопасность мобильных приложений.
1. Введение. Мобильные приложения входят в состав многих широко используемых сервисов. Они хранят, передают, обрабатывают конфиденциальные данные. Эксплуатация программных уязвимостей в таких приложениях может привести к серьезным потерям как клиентов, так и владельцев сервиса. Таким образом, исследование информационной безопасности (ИБ) мобильных приложений является необходимой частью обеспечения качества сервиса.
Устройства, работающие под управлением мобильной платформы Android, занимают большую часть рынка мобильных устройств [1]. Проведенное нами исследование защищенности мобильных приложений, находящихся в открытом доступе на Google Play Market, к которым предъявляются повышенные требования безопасности, показывает, что во многих приложениях присутствуют уязвимости критичной степени важности. Исследование проводилось с применением средств статического, динамического и ручного анализа кода. Результаты исследования показывают, что задача автоматической оценки безопасности мобильных приложений для платформы Android является актуальной.
Целью данной работы является разработка подхода к решению задачи статического бинарного анализа мобильных приложений для платформы Android. Статический анализ обеспечивает полное покрытие кода, бинарный анализ позволяет анализировать приложения, когда их исходный код недоступен.
В процессе статического бинарного анализа происходит преобразование бинарного образа в промежуточное представление. Далее к промежуточному представлению применяются алгоритмы статического анализа, результаты работы которых используются для применения правил анализа, с помощью которых обнаруживаются уязвимости. В контексте такого подхода необходимо решить три задачи.
1. Определить промежуточное представление, пригодное для анализа и для последующего представления его результатов.
2. Определить набор алгоритмов статического анализа и специфику их реализации в рамках задачи для достижения полноты реализации базы правил.
3. Составить базу правил, позволяющую искать максимальное количество уязвимостей, возникающих в приложениях для платформы Android.
Данная работа имеет следующую структуру. В п. 2 представлены существующие методы, которые используются при реализации описываемого подхода: преобразование арк-файла (пакета, в котором хранится исполняемый код приложения), методы статического анализа, специфика их реализации для данной задачи. Также кратко описаны известные средства статического анализа. В п. 3 представлен наш метод преобразования бинарного кода с восстановлением информации, связывающей его с исходным кодом, для последующего отображения результатов анализа. В п. 4 описывается составленный нами набор уязвимостей, встречающихся в мобильных приложениях
1 Факультет ВМК МГУ, асп., e-mail: yaroslavalexandrovQgmail.com
2 Факультет КТИ СПбГЭТУ, асп., e-mail: safin.191Qgmail.com
3 SmartDec, ген. директор, к.ф.-м.н., e-mail: katerinaQsmartdec.ru
4 Факультет ВМК МГУ, доц., к.ф.-м.н., e-mail: blackavQgmail.com
для платформы Android, и разработанные в рамках данной работы правила, по которым происходит их поиск. В п. 5 описана реализация предлагаемого подхода в рамках инструментального средства inCode и результаты экспериментов. В п. 6 представлены основные выводы.
2. Используемые методы.
2.1. Преобразование арк-файла. После компилирования исходного кода мобильного приложения в байткод виртуальной машины Java (JVM) компилятор виртуальной машины Dalvik (DalvikVM) объединяет class-файлы и перекомпилирует код в байткод для DalvikVM, получая исполняемый на мобильном устройстве dex-файл. Исполняемый файл вместе с ресурсами и файлом конфигурации AndroidManifest.xml упаковывается в арк-файл. Существует несколько работ, посвященных обработке и преобразованиям арк-файла: распаковке арк-файла (см., например, [2]), трансляции кода DalvikVM (например, трансляции в байткод Java [3]).
Для специалиста, выполняющего анализ, важно отображать уязвимости на исходный код, а не на анализируемый байткод. Для этого применяется декомпиляция байткода JVM в исходный код на языке Java. Известно, что при декомпиляции байткода JVM может достигаться достаточно высокое качество исходного кода [4]. Существует множество средств, осуществляющих декомпи-ляцию байткода Java (см., например, [5]).
2.2. Методы статического анализа. Простейшим методом статического анализа является поиск по шаблонам [6]. Для некоторой уязвимости создается параметризируемый фрагмент кода, совпадение с которым говорит о наличии уязвимости. При анализе байткода JVM шаблоны формулируются в терминах параметризируемых участков графа потока управления. Такой подход позволяет обнаруживать простые уязвимости и показывает большое количество ложных срабатываний.
Основные алгоритмы статического анализа, применяемые в контексте поиска уязвимостей, можно условно разделить на две категории: стандартные алгоритмы — алгоритмы, широко применяемые в компиляторных технологиях, и алгоритмы, специфичные для анализа по требованиям информационной безопасности. Эти алгоритмы в основном относятся к классу алгоритмов анализа потока данных. К первой категории можно отнести анализ синонимов, распространение констант, поиск достигающих определений, построение цепочек определение-использование и т.д. [7, 8]. Ко второй категории можно отнести taint-анализ, интервальный анализ, строковый анализ [6].
Результатом работы таких алгоритмов является множество состояний переменных в каждой точке программы. Далее в терминах таких состояний применяются заранее сформулированные правила поиска уязвимостей. Например, если данная переменная, передающаяся напрямую в функцию обращения к базе данных, помечена меткой "taint", то необходимо заявить о наличии уязвимости SQL Injection.
В работе [9] описывается реализация taint-анализа для Android-приложений. Основным применением taint-анализа здесь является поиск утечек конфиденциальных данных. Основной спецификой реализации метода является наличие дополнительных точек входа в программу — компонент межпроцессного взаимодействия, а также наличие callback-функций.
2.3. Инструментальные средства статического анализа. Существует несколько коммерческих и открытых инструментальных средств статического анализа кода по требованиям ИБ, с помощью которых можно анализировать мобильные приложения для платформы Android.
Среди коммерческих средств наиболее известными являются HP Foritfy [10] и IBM AppScan Source [11]. Оба средства позволяют анализировать исходный код на языке Java и обладают наборами правил, специфичных для мобильных приложений. Однако в рамках обоих средств не реализована возможность анализа мобильных приложений по бинарному коду и последующему отображению результатов на исходный код.
Среди открытых средств можно выделить FlowDroid [9]. FlowDroid позволяет анализировать мобильные приложения для платформы Android в виде арк-файлов, однако не отображает результаты анализа на декомпилированный исходный код. FlowDroid обнаруживает только уязвимости, связанные с утечкой данных.
3. Преобразование бинарного кода. Бинарный код мобильного приложения может не содержать информации о связи с исходным кодом: информация может быть удалена при компиля-
ции, к байткоду могут быть применены средства запутывания [12], при преобразовании байткода DalvikVM в байткод JVM при помощи средства dex2jar данная информация может быть изменена. Кроме этого, информация отладки в исполняемом файле может оказаться бесполезной при восстановлении связей декомпилируемого байткода с полученным программным кодом высокого уровня, так как он может сильно отличаться от исходного программного кода по расположению строк.
В данной работе разработано средство декомпиляции, реализующее установление связи байт-кода с получаемым исходным кодом. Вывод исходного кода происходит в процессе обхода абстрактного синтаксического дерева (AST). Алгоритм восстановления информации, связывающей номера строк в исходном коде и позиции соответствующих инструкций в байткоде, описан далее.
1. Функция line () возвращает номер текущей генерируемой строки, функция pos О возвращает
позицию текущей инструкции в байткоде.
2. Массивы LiiieNumbers и Bounds инициализируются пустыми массивами.
3. Для каждого класса приложения:
а) при посещении узла AST в массив LineNumbers сохраняется пара (pos О , line О);
б) при посещении отвечающего за метод класса узла AST m, с которого начинается поддерево t:
• перед обходом t в переменную methodStart сохраняется line О, в переменной sig вычисляется сигнатура текущего метода;
• по завершении обхода t в массив Bounds сохраняется тройка (sig, methodStart, line О);
в) в байткод класса в таблицы номеров строк каждого метода добавляются необходимые записи из массива LineNumbers с учетом полученных ограничений из массива Bounds. При получении информации из массива Bounds учитывается наличие анонимных классов, границы методов которых могут находиться внутри границ основного метода.
4. Поиск уязвимостей. В данном разделе описан поиск уязвимостей, наиболее часто встречающихся в мобильных приложениях для платформы Android и представляющих наибольшую опасность в смысле информационной безопасности. Перечень уязвимостей составлен по результатам ручного исследования более сорока мобильных приложений, взятых в Google Play Market, к которым предъявляются повышенные требования безопасности. В процессе исследований проводился как статический анализ кода с экспертной верификацией результатов, так и ручная проверка приложения в процессе выполнения (работа с сетью, работа с файловой системой, система авторизации) .
Основные уязвимости мобильных приложений для платформы Android можно разделить на несколько категорий. Шаблоны поиска уязвимостей для наглядности представлены в терминах языка Java, а не байткода JVM. Поиск данных уязвимостей реализован в рамках инструментального средства inCode.
4.1. Передача данных. Уязвимости при передаче данных могут возникать по следующим причинам: использование незащищенных протоколов передачи данных; использование протоколов передачи данных, обладающих уязвимостями; недостаточная проверка цепочки сертификатов или домена сертификата. Наличие таких уязвимостей может привести к эксплуатации атаки "человек посередине" [13].
Большинство уязвимостей, связанных с передачей данных, можно обнаруживать с помощью шаблонного поиска. Например, использование недостаточной проверки цепочки сертификатов можно обнаруживать с помощью следующего шаблона: применение класса, реализующего интерфейс X509TrustManager и обладающего тривиальными телами соответствующих методов проверки.
При поиске использования http-соединения необходимо комбинировать поиск по шаблонам и строковый анализ. Следующий шаблон позволяет обнаруживать такую уязвимость:
HttpClient httpclient = new DefaultHttpClient(); HttpGet httpget = new HttpGet(url); HttpResponse response; response = httpclient.execute(httpget);
Однако для верификации такого нахождения необходимо отследить префикс переменной url и удостовериться, что он принимает значение http.
4.2. Хранение данных. При наличии некоторых условий (привилегированный доступ к устройству, физический доступ к устройству, эксплуатация уязвимости "Обход файлового пути" ) злоумышленник может получить доступ к данным, хранящимся в домашней директории приложения, на внешнем устройстве, в системном журнале событий, в системном буфере обмена. Сохранение конфиденциальных данных пользователей в перечисленных выше сущностях может привести к компрометации этих данных.
Обнаружение уязвимостей хранения данных предлагается проводить с помощью адаптации taint-анализа. В данном случае в роли "источников" выступают функции получения конфиденциальных данных, а в роли "стоков" — функции сохранения данных. Здесь в определении источника место функции может занимать некоторая эвристика, которая определяет, что данный фрагмент кода порождает конфиденциальные данные.
Например, в роли источников могут выступать функции класса TelephonyMaiiager, такие, как getDeviceldO (получает идентификатор устройства), getLinelNumber() (может получить номер телефона владельца), getSimSerialNumberO (получает уникальный идентификатор SIM-карты). Также в роли источников могут выступать переменные с именем token, password и т. д. В роли стоков могут выступать следующие функции:
• функции записи класса File в домашнюю директорию getFilesDir () или во внешнюю среду;
• функции записи в системный лог (класс Log, методы Log.vO, Log.iO, ... );
• запись в буфер обмена: ClipboardMaiiager clipboard =
(ClipoardMaiiager) getSystemService(CLIPBOARD_SERVICE); ClipData data = ClipData.newPlainText("label", "text"); Clipboard.setPrimaryClip(data);
4.3. Использование небезопасной криптографии. При шифровании или хешировании могут использоваться криптографические функции, обладающие рядом известных слабостей или уязвимостей, что может привести к компрометации конфиденциальных данных: DES/3DES-шифрование, режим шифрования ECB, MD4/MD5/SHA-l-xennipoBaHHe, использование фиксированного ключа шифрования, 1024-битный RSA.
Большинство таких уязвимостей можно обнаруживать с помощью методов поиска по шаблонам. Например, при использовании шифрования RSA с длиной ключа 1024 применяется следующий шаблон:
kpg = KeyPairGenerator.getlnstanceO'RSA", "ВС"); kpg.initialize(1024);
При поиске использования слабого режима шифрования может применяться следующий шаблон: Cipher.getlnstanceC'AES"), поскольку по умолчанию в таком случае будет использован режим шифрования ECB.
4.4. Небезопасное использование межпроцессного взаимодействия. Важнейшей технологией для платформы Android является технология межпроцессного взаимодействия. Элементами межпроцессного взаимодействия являются [14]: Activity (функциональность экрана приложения), Service (функциональность приложения), Intent (сообщения), ContentProvider (доступ к данным), BroadcastReceiver (прием широковещательных сообщений). Компоненты межпроцессного взаимодействия по ошибке разработчика могут быть открыты для взаимодействия с другими приложениями. Возможны следующие сценарии эксплуатации подобных уязвимостей.
• Через широковещательное сообщение передаются конфиденциальные данные. Приложение злоумышленника регистрирует приемщик сообщений определенного типа и осуществляет перехват передаваемых данных.
• С помощью открытого BroadcastReceiver или неявного вызова Activity через Intent приложение обрабатывает сообщения определенного типа. Приложение злоумышленника посылает сообщение данного типа, что может вызвать отказ в обслуживании, изменение поведения приложения или даже перехват управления приложением.
Компоненты, открытые для межпроцессного взаимодействия и не защищенные сигнатурой или параметром exported, установленным в значение false, могут быть обнаружены с помощью поиска по шаблонам в файле конфигурации AndroidManif est .xml или в исходном коде.
BroadcastReceiver, открытый для приема широковещательных сообщений от других приложений, можно обнаруживать с помощью следующего шаблона непосредственно в программном коде:
IntentFilter intentFilter = new IntentFilter("...");
MyReceiver myReceiver = new MyReceiver();
context.registerReceiver(myReceiver, intentFilter);
Наличие открытых к взаимодействию компонент не означает возможности их использования для нарушения информационной безопасности приложения. Для уменьшения числа ложных срабатываний является целесообразным поиск уязвимых сценариев использования таких компонент.
Например, регистрируется открытый приемщик широковещательных сообщений, обработчик которого получает параметры Intent с помощью функции getExtrasü и использует их без сравнения со значением null. Приложение злоумышленника может посылать сообщение данного типа без наличия соответствующего параметра, что может привести к отказу в обслуживании исходного приложения. Поиск таких сценариев предлагается проводить с помощью анализа потока данных.
4.5. Недостаточная проверка и обработка входных данных. Для мобильных приложений свойственны также общие уязвимости: внедрение кода (SQL Injection), проход файлового пути (Path Traversal), внедрение сущностей XML (ХХЕ), межсайтовый скриптинг (XSS). Поиск таких уязвимостей проводится с помощью taint-анализа с составлением базы источников, стоков и функций фильтрации.
5. Реализация и эксперименты. Разработанное нами инструментальное средство inCode реализовано в виде web-приложения, позволяющего загружать арк-файл для анализа по ссылке на Google Play Market. В web-интерфейсе осуществляется просмотр результатов анализа.
При анализе арк-файла переход к промежуточному представлению начинается с его распаковки. После распаковки происходит декодирование файла AndroidManifest.xml с помощью инструмента apktool [2]. Далее исполняемый код для DalvikVM транслируется в байткод JVM при помощи инструмента dex2jar [3]. Статическому анализу подвергается полученный байткод для JVM и файл AndroidManifest.xml.
Алгоритмы статического анализа реализованы на основе средства статического анализа findbugs [15]. При реализации используются встроенные реализации методов решения задач распространения констант, распространения типов, анализа синонимов. Нами реализован taint-анализ, взаимодействующий с анализом синонимов.
База правил представляется в виде конфигурационного файла, описывающего опасные конструкции, по которым происходит поиск уязвимостей. Структура файла позволяет описывать вызовы методов с набором условий: на анализируемый класс, на анализируемый метод, на класс, к которому принадлежит вызываемый метод, на значения аргументов, на флаги аргументов (рас-пространямые с помощью taint-анализа). На данный момент разработанная нами база правил включает в себя 54 правила, специфичных для Android-приложений, и более 100 правил, общих для языка Java.
Результат работы инструментального средства сравнивался с результатами ручного анализа приложений. В качестве тестового набора использовались 40 приложений, ранее проанализированных в ручном режиме: 34 банковских приложения, 2 мобильных кошелька, 3 приложения on-line торговли, 1 почтовое приложение. Результаты экспериментов показали, что средство обнаружило:
• 100% уязвимостей передачи данных при 16% ложных срабатываний. Ложные срабатывания в данном случае происходят из-за сложной реализации методов проверки цепочек сертификатов и из-за передачи по незащищенным протоколам неконфиденциальной информации, которая не может повлиять на выполнение приложения;
• 78% уязвимостей хранения данных при 11% ложных срабатываний. Большая доля уязвимостей не была обнаружена вследствие недостатков реализации taint-анализа. Ложные срабатывания происходили из-за сложности определения чувствительности данных в некоторых случаях;
• 100% уязвимостей криптографии при 9% ложных срабатываний, которые происходили из-за обнаружения слабого хеширования некритичных данных;
• 100% уязвимостей межпроцессного взаимодействия при 4% ложных срабатываний, которые также происходили из-за обнаружения утечки некритичных данных.
Кроме того, 98% уязвимостей были правильно отображены на декомпилированный исходный код с точностью до номера строки.
В рамках инструментального средства inCode на момент тестирования не обнаруживались уязвимости, связанные с неправильной проверкой входных данных, а также некоторые уязвимости, редко встречающиеся в приложениях и обладающие низким уровнем угрозы (например, отсутствие проверки целостности приложения, отсутствие обнаружения привилегированого доступа и отладчика). С помощью инструментального средства inCode удалось обнаружить более 70% уязвимостей в тестовых приложениях.
6. Заключение. В данной работе представлен подход к автоматическому анализу мобильных приложений для платформы Android по требованиям информационной безопасности. Анализ выполняется на исполняемых арк-файлах и не требует исходного кода приложения. Представлена технология восстановления байткода JVM и исходного кода на языке Java с сохранением связей между байткодом и исходным кодом для информативного отображения результатов анализа. Рассмотрено применение основных алгоритмов статического анализа для исследования защищенности байткода JVM. Приведены основные классы уязвимостей приложений для мобильной платформы Android и методы их автоматического поиска.
Описанные в статье алгоритмы и правила реализованы в рамках средства статического анализа inCode. С помощью данного средства проведен анализ набора из сорока приложений, который ранее тестировался вручную. Все приложения относятся к классу приложений с повышенными требованиями безопасности: банковские клиенты, почта, сервисы on-line торговли. Более 70% известных уязвимостей были найдены в автоматическом режиме, что позволяет говорить о применимости представленных методов.
СПИСОК ЛИТЕРАТУРЫ
1. Q1 2014 smartphone OS results: android dominates high growth developing markets. URL: https://www.abiresearch.com/press/ql-2014-smartphone-os-results-android-dominates-hi
2. A tool for reverse engineering Android apk files. URL: http://ibotpeaches.github.io/Apktool
3. Tools to work with android .dex and java .class files. URL: https://code.google.eom/p/dex2jar
4. MiecznikowskiJ., HendrenL. Decompiling Java bytecode: Problems, traps and pitfalls // Proc. of the 11th Intern. Conf. on Compiler Construction. Grenoble: Springer Berlin Heidelberg, 2002. P. 179-196.
5. Strobel procyon decompiler. URL: https://bitbucket.org/mstrobel/procyon
6. Wogerer W. A survey of static program analysis techniques. Vienna: Vienna University of Technology, 2005.
7. Aho A. V., Sethi R., Ullman J.D. Compilers: Principles, Techniques, and Tools. Boston: Addison-Wesley, 1985.
8. Muchnick S. S. Advanced Compiler Design Implementation. San Francisco: Morgan Kaufmann, 1997.
9. Arzt S., Rasthofer S., Fritz C., et al. Flowdroid: Precise context, flow, field, object-sensitive and lifecycle-aware taint analysis for android apps // Proc. of the 35th ACM SIGPLAN Conf. on Programming Language Design and Implementation. New York: ACM, 2014. P. 259-269.
10. HP Fortify Static Code Analyzer. URL: http://www8.hp.com/ru/ru/software-solutions/static-code-analysis-sast/index.html
11. IBM security AppScan source. URL: http://www-03.ibm.com/software/products/ru/appscan-source
12. Karnick M., MacBrideJ., McGinnisS., et al. A qualitative analysis of java obfuscation//Proc. of 10th IASTED Intern. Conf. on Software Engineering and Applications. Dallas: SEA, 2006. P. 166-171.
13. Man-in-the-middle attack. URL: https://www.owasp.org/index.php/Man-in-the-middle_attack
14. Enck W., Octeau D., McDaniel P., et al. A study of android application security // Proc. of the 20th USENIX Conf. on Security. Berkeley: USENIX Association, 2011. P. 21-21.
15. Find Bugs in Java Programs. URL: http://findbugs.sourceforge.net
Поступила в редакцию 29.05.15
INFORMATION SECURITY STATIC BINARY ANALYSIS FOR ANDROID APPLICATIONS Aleksandrov Y. A., Safin L. K., Troshina E. N., Chernov A. V.
This article presents an approach to automatic analysis of Android mobile applications for compliance with information security requirements without source code.
Keywords: static analysis, binary analysis, mobile security.