iOS-приложения: тестирование безопасности и устойчивости к взлому

Виктор Котов

Виктор Котов

IT-копирайтер

#Мобильная разработка

#Тестирование

3 Окт 2013

Время чтения: 15 минут

3 Окт 2013

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

Сегодня я поделюсь методикой тестирования безопасности iOS-приложений и проиллюстрирую теорию практикой. Конечно, договор с заказчиком не позволит мне использовать для этого приложение проекта, поэтому для примера я разберу и проанализирую другое приложение с похожими возможностями — «Плати картой» для оплаты услуг МегаФона.

Необходимый инструментарий

Инструмент для JailBreak

  • redsn0w, версия для Mac OS или Windows.

ПО для устройства

  • Cydia — программное приложение iOS, которое устанавливается вместе со специальной версией системы в процессе взлома; все перечисленное далее ПО устанавливается через Cydia.
  • OpenSSH — утилита для удаленного подключения к iOS-устройствам по SSH.
  • Adv-cmds — выполняет ps, kill, finger и другие полезные команды.
  • Sqlite3 — клиент баз данных.
  • Veency — VNC-сервер для iOS-устройств.
  • Tcpdump — утилита, позволяющая захватывать и анализировать интернет-трафик.
  • Grep — утилита для поиска.
  • GNU Debugger — инструмент отладки, анализа и обратной разработки.

ПО для декстопа

  • Burp Suite — инструменты анализа трафика; Java, multiplatform.
  • Wireshark — инструмент анализа трафика.
  • iExplorer — файловый менеджер.
  • Cyberduck — SFTP-клиент; SSH-доступ.
  • Screen Sharing — системная утилита для подключения к VNC-серверу; используется в связке с установленным на устройстве Veency, но может использоваться любой VNC-клиент.
  • 0xED — hex-редактор.

Подготовка устройства

JailBreak

Для анализа и аудита программного обеспечения необходимо установить специальные утилиты, что невозможно сделать без взлома устройства. Чтобы взломать Apple iPhone, iPad или iPod Touch, приведите его в режим «DFU», а затем просто следуйте указаниям мастера redsn0w.

В итоге, если все прошло успешно, устройство будет взломано, и на нем будет установлена специальная версия iOS с приложением Cydia. Если после запуска Cydia у вас появляется сообщение об ошибке «Ошибка загрузки. Недоверенный сертификат сервера» (Unable to Load. Untrusted Server Certificate), вам потребуется дополнительная настройка.

Установка программного обеспечения

Обязательный минимум для мобильного устройства:

  • OpenSSH
  • Adv-cmds
  • Tcpdump
  • Grep
  • GNU Debugger

Для десктопа:

  • Burp Suite
  • Wireshark
  • Cyberduck
  • 0xED

Пароль root и mobile: «alpine», будет нужен для подключения по SSH.

Пароль для удаленного доступа к устройству по VNC задается в настройках.

Аудит приложения

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

  • способы передачи данных через интернет;
  • конфиденциальность;
  • способы хранения данных;
  • устойчивость к взлому.

Рассмотрим эти задачи более подробно.

Анализ интернет-трафика

iOS-приложения могут использовать различные способы передачи и получения данных:

  • незащищенные протоколы, такие как http;
  • Что проверяем: используются ли они для передачи важных данных?
  • защищенные протоколы, такие как https;
  • что проверяем: делается ли проверка подлинность SSL-сертификата или приложение принимает любые SSL-сертификаты?
  • нестандартные протоколы и низкоуровневые способы передачи данных.

Конфиденциальность данных

Проверяем, не использует ли приложение какие-либо данные пользователя без его ведома.

Хранение данных

Во время стандартной установки приложения на iOS-устройстве, система создает папку с уникальным идентификатором внутри /var/mobile/Applications. Типичная структура папок внутри корневой папки приложения такова:

Смотрим и ищем:

  • Plist файлы — что содержат, нет ли скрытых опций?
  • Keychain — что и в каком виде хранится?
  • Cache — что кэшируется?
  • Logs — пишутся ли логи? что именно?

Устойчивость к взлому

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

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

Давайте рассмотрим, как можно проанализировать эти моменты на примере разбора безопасности приложения для оплаты мобильной связи.

Пример анализа приложения «Плати картой»

Описание приложения на AppStore: Платите за мобильный легко и просто, не отрываясь от дел! Без комиссий. Без очередей. Загрузите приложение «Плати картой» и используйте возможность пополнить свой мобильный счет или счет другого абонента МегаФон путем списания средств с Вашей банковской карты VISA и MasterCard.

Дополнительная информация: в качестве логина/пароля в приложении используются данные аккаунта МегаФон «Сервис-Гид». Адрес сервиса зависит от конкретного региона; пример для Новосибирской области.

Устройство для тестирования и анализа: iPhone 3G.

Предварительный анализ

МегаФон «Сервис-Гид» — это система, позволяющая абонентам сотового оператора МегаФон управлять своим аккаунтом: менять тариф, управлять дополнительным опциями, получать отчеты по оказанным услугам (звонки, SMS), тратить бонусные баллы и т. д.

Соответственно, главный вопрос по безопасности:

  • каким образом в приложении обеспечивается сохранность данных аккаунта, предотвращающая несанкционированный доступ к «Сервис-Гид»?

Дополнительные вопросы:

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

Application traffic analysis

HTTP

Все ок. Во время авторизации не используется.

HTTPS

Все ок. Подлинность сертификата проверяется.

Установить PortSwiggerCA.crt на устройство не получилось — устройство перезагружалось. Поэтому пришлось проводить авторизацию не через прокси, а напрямую.

Каналы передачи данных о карте

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

Конфиденциальность

В ходе проведения исследования признаков несанкционированного доступа к данным пользователя обнаружено не было.

Хранение данных

Авторизация

  • Изучив особенности хранения данных, мы выявили несколько слабых моментов, ставящих безопасность данных пользователя под угрозу.
  • Угроза безопасности! При авторизации в папке Documents создается файл authData.xml, где в незашифрованном виде указывается логин и пароль к сервису МегаФон «Сервис-гид».
  • Чтобы начать работу, необходимо принять пользовательское соглашение. Соглашение можно не принимать, тогда просто попадаешь в основное окно программы.
  • Угроза безопасности! После перезапуска приложение логинится автоматически.
  • Угроза безопасности! После закрытия приложения, файл authData.xml с незашифрованным паролем остается в папке Documents, остается он и в случае, когда пользователь выходит из своей учетной записи, т. к. опция «Запомнить» по умолчанию включена. Если нажать «Выход», отключить опцию и закрыть приложение, то после перезапуска приложение все равно залогинится автоматически. Возможно, опция «Запомнить» не сохраняется, если не была нажата кнопка «Войти». При попытке входа с неверными данными выдается сообщение об ошибке, но опция «Запомнить» не учитывается, и при перезапуске приложения пользователь снова авторизуется с сохраненными данными.
  • Если во время авторизации отключить опцию «Запомнить», то файл authData.xml не создается.
Данные банковской карты
  • Приложение не приняло старую карту, выдало сообщение, что срок действия карты истек.
  • При попытке отправить данные с неправильным сроком действия появилось сообщение, что банк не смог провести тестовый платеж.

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

Попробуем выяснить это с помощью tcpdump.

Важно! Добавьте «-s 0», чтобы не обрезались пакеты и можно было использовать опцию «Follow TCP Stream Wireshark» остановка записи «Ctrl+C».

iPhone-Viktor-Kotov:~ root# tcpdump -w /FILENAME.pcap -s 0
tcpdump: listening on en0, link-type EN10MB (Ethernet), capture size 68 bytes
^C1506 packets captured
1509 packets received by filter
0 packets dropped by kernel
iPhone-Viktor-Kotov:~ root#

Анализ трафика в Wireshark ничего криминального не выявил:есть запросы к ispay.megafon.ru/ по https.

Проверка на устойчивость к взлому

Disclaimer: Анализ приложения на уязвимость ко взлому проводится формально, т. к. никаких препятствий к доступу в приложение нет.

Ищем путь для приложения (можно посмотреть и через Cyberduck):

iPhone-Viktor-Kotov:~ root# ls -ld /var/mobile/Applications/*/UPS.app
drwxr-xr-x 4 mobile mobile 7310 Apr 19 10:13 /var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app
iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# plutil Info.plist | grep Executable
    CFBundleExecutable = UPS;
iPhone-Viktor-Kotov:~ root# cd /var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D
iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D root# cd UPS.app

Находим имя исполняемого файла:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# plutil Info.plist | grep Executable
    CFBundleExecutable = UPS;

Вытаскиваем исполняемый файл с устройства при помощи Cyberduck или с десктопа (из папки iTines):

Далее уже на десктопе в терминале смотрим информацию о файле:

Kotov-Mac-mini-3:PayWithCard qwerty$ file UPS
UPS: Mach-O universal binary with 2 architectures
UPS (for architecture armv6):	Mach-O executable arm
UPS (for architecture armv7):	Mach-O executable arm

Видим, что внутри две версии: с поддержкой архитектуры armv6 (<=iPhone 3G, <=iPod Touch 2nd gen) и armv7 (более новые iPhone и iPod Touch, все версии iPad).

Дополнительно делаем запрос с otool:

Kotov-Mac-mini-3:PayWithCard qwerty$ otool -f UPS
Fat headers
fat_magic 0xcafebabe
nfat_arch 2
architecture 0
    cputype 12
    cpusubtype 6
    capabilities 0x0
    offset 4096
    size 241456
    align 2^12 (4096)
architecture 1
    cputype 12
    cpusubtype 9
    capabilities 0x0
    offset 245760
    size 244816
    align 2^12 (4096)

В результатах запроса здесь и далее жирным выделена важная информация. Делаем запрос на команды загрузки, также при помощи otool:

Kotov-Mac-mini-3:PayWithCard qwerty$ otool -arch armv6 -l UPS | grep crypt
    cryptoff  4096
    cryptsize 163840
    cryptid   1

Подключаемся к устройству по SSH:

Kotov-Mac-mini-3:~ qwerty$ ssh -l root 192.168.0.109
root@192.168.0.109's password:

Получаем копию незашифрованного исполняемого файла (на устройстве):

Для этого нам нужно рассчитать стартовый и конечные адреса:

стартовый: cryptoff + 0x1000 в нашем случаем это будет 4096 + 0x1000 = 0x2000

конечный: стартовый + cryptsize в нашем случае это будет 0x2000 + 163840 = 172032 или 0x2A000

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# gdb -e ./UPS
GNU gdb 6.3.50.20050815-cvs (Fri May 20 08:08:42 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=arm-apple-darwin9 --target=".Reading symbols for shared libraries . done

(gdb) set sharedlibrary load-rules ".*" ".*" none
(gdb) set inferior-auto-start-dyld off
(gdb) set sharedlibrary preload-libraries off
(gdb) rb doModInitFunctions
Breakpoint 1 at 0x2fe0c1fa

Проверяем, что исполняемый файл получился правильного размера:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# ls -l upsarmv6.bin
-rw-r--r-- 1 root mobile 163840 Apr 19 14:41 upsarmv6.bin

Теперь нужно скопировать дешифрованную копию исполняемого файла в оригинальный. Для этого необходимо посчитать адрес по формуле:

Architecture offset (architecture 0 offset — так как устройство iPhone 3G) + Encryption offset (cryptoff)

4096 + 4096 = 8192

Kotov-Mac-mini-3:PayWithCard qwerty$ dd seek=8192 bs=1 conv=notrunc if=./upsarmv6.bin of=./UPS
163840+0 records in
163840+0 records out
163840 bytes transferred in 0.434001 secs (377511 bytes/sec)

Далее при помощи hex-редактора 0xED убираем флаг, что исполняемый файл зашифрован:

Открываем перезаписанный исполняемый файл UPS. Дальше в зависимости от нужной нам архитектуры ищем либо первое вхождение (в начале файла) “/usr/lib/dyld”, либо второе — примерно после половины.

Дальше идем последовательно и ищем байт со значением 0x01 (01). Меняем каждый на 0x00 (00) поочередно! Каждый раз сохраняем файл и проверяем в терминале, поменялся ли флаг шифрования для исполняемого файла:

Kotov-Mac-mini-3:PayWithCard qwerty$ otool -arch armv6 -l UPS | grep crypt
    cryptoff  4096
    cryptsize 163840
    cryptid   0

Если флаг не поменялся, отменяем изменение и ищем следующий байт, повторяем пока не будет найден нужный, обычно это какой-то из промежутка между /usr/lib/dyld и /System/Library/Frameworks/

Foundation.framework/Foundation

После того как нужный байт найден, делаем дамп классов:

Kotov-Mac-mini-3:PayWithCard qwerty$ class-dump-z -u armv6 UPS

Полученное в логах данные сохраняем в файл UPSClassesDumpLog.txt и изучаем.

Например, поверхностный анализ для UPC показал что у UPSAppDelegate есть свойство/объект @property(retain, nonatomic) DataManager* dataManager;

а у этого класса есть следующий интерфейс:

@interface DataManager : NSObject {
...
}

@property(assign) BOOL isRemember;
@property(assign) BOOL pinLocked;
@property(retain, nonatomic) NSString* cardInRegistration;
@property(retain, nonatomic) NSMutableArray* payments;
@property(retain, nonatomic) NSString* temppass;
@property(retain, nonatomic) Card* oldestCard;
@property(retain, nonatomic) Card* defaultCard;
@property(retain, nonatomic) NSMutableArray* aps;
@property(retain, nonatomic) NSMutableArray* whiteList;
@property(retain, nonatomic) NSMutableArray* cards;
@property(retain, nonatomic) NSString* password;
@property(retain, nonatomic) NSString* balance;
@property(retain, nonatomic) NSString* login;
@property(retain, nonatomic) MSISDN* userMSISDN;
-(BOOL)containInWhiteList:(id)whiteList;
-(BOOL)isBelongToUser:(id)user;
-(id)getCard:(long)card;
-(id)getWgiteListRec:(long)rec;
-(id)getAps:(long)aps;
-(id)getPayment:(long)payment;
-(id)getPayments:(id)payments;
-(id)getPayments;
-(id)getWhiteList;
-(BOOL)isWhiteListAddingAlowed;
-(id)getAPS;
-(id)getCards;
-(id)getOldestCard;
-(id)getDefaultCard;
-(id)getCardInRegistraiton;
-(id)getUsersToPayMsisdn;
-(id)getUserMSISDN;
-(void)saveAuthData;
-(void)cleanAuthdata;
-(BOOL)loadStoredAuthData;
-(BOOL)isAuthdataStored;
-(void)dealloc;
-(id)init;

Попробуем получить список карт находящихся в процессе регистрации.

Узнаем идентификатор процесса:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# ps aux | grep UPS
root      1590   0.0  0.3   273044    360 s000  R+    3:40PM   0:00.02 grep UPS
mobile    1579   0.0  8.3   320816   9880   ??  Ss    3:39PM   0:03.22 /var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app/UPS

Подключаемся к процессу при помощи Cycript:

iPhone-Viktor-Kotov:/var/mobile/Applications/006C94AD-C409-44FD-8980-40D004E6188D/UPS.app root# cycript -p 1579
cy#

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

cy# var app = [UIApplication sharedApplication]
@"

Узнаем указатель AppDelegate:

cy# app.delegate
@"

Присваиваем указатель своей переменной:

cy# var delegate = new Instance(0x1652a0)
@"

Получаем указатель на менеджер данных:

cy# delegate.dataManager
@"

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

Пока не понятно для чего используется temppass, возможно, это токен:

cy# dataman.temppass
@"AAACOwAaAsrLlGli2mHqImF4l9BbUmWG"

Дальнейший анализ нужно проводить после подтверждения карты — смотреть в каком виде будет доступны данные по карте, можно ли провести оплату на произвольный номер. Хотя, интерфейс и так не лочится.

cy# datMan.cards
@["

После обращения к серверу приложение выдало сообщение о невозможности выполнить операцию, т.к. сумма платежа не может быть меньше 100 р.

Резюме

К сожалению, рассматриваемая программа «Плати картой» только частично отвечает требованиям безопасности. Злоумышленник может без особого труда получить доступ к данным аккаунта МегаФон «Сервис-Гид», после чего нанести вред пользователю, изменив параметры его профиля (тариф, услуги) на стороне оператора сотовой связи и получить несанкционированный доступ к конфиденциальной информации (звонки, SMS). Это предварительное заключение, полное резюме будет составлено после окончания исследования.

Комментарии

Фильтр

Закрыть

Технологии

Индустрии