Maria Skorik
325
Блоги

Как защитить данные в iOS-приложении

Поделиться

В избранное

В избранном

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

За годы работы над приложениями для компаний, которым миллионы людей доверяют свои деньги и данные, мы выработали свой набор принципов обеспечения безопасности данных. И каждый год с выходом новых технологий и версий iOS этот список пересматриваем. Ниже версия актуальная на начало 2018 года.

Ничего личного

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

Храните только те данные, без которых не обойтись. Если среди них есть персональная информация пользователя — отправляйте ее в Связку ключей. Если нужна полноценная база данных (Core Data или Realm, например) — зашифруйте ее. И все, что можно найти через Spotlight, также не должно содержать данные о пользователе.

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

Чтоб наверняка ничего не осталось, можно отключить еще и кэширование веб-запросов.

Есть запрос

До выхода iOS 9 приложения могли свободно делать запросы к любому адресу по протоколу HTTP. Данные передавались по сети в незашифрованном виде, и при желании отследить содержимое запросов не составляло труда. Начиная с iOS 9 Apple ввела жесткие требования к сетевым соединениям и разработала правила App Transport Security (ATS), согласно которым все запросы в Интернет должны производиться посредством протокола HTTPS и шифроваться. Операционная система сама по умолчанию следует этим требованиям, поэтому необходимо лишь их соблюдение со стороны сервера.

Разработчики также могут указывать параметры подключения для всех соединений в целом или для запросов к конкретным доменам. Все они прописываются в файле Info.plist приложения. Правила можно отключить, но во время ревью приложения в App Store придется найти этому убедительное объяснение. Эта функция может быть полезна, например, для просмотра веб-страниц в приложении, поскольку не все они могут соответствовать требованиям безопасности Apple.

Но даже при использовании HTTPS-соединений остается возможность просмотра данных при обмене с сервером, например, в публичных сетях есть возможность отслеживать трафик с помощью атаки Man-in-the-middle, когда между приложением и сервером появляется посредник. Бороться с этим можно с помощью SSL-пиннинга — в этом случае приложение знает SSL-сертификат сервера, используемый для HTTPS-соединения, и не доверяет другим сертификатам. При получении от сервера неизвестного сертификата (как в случае с атакой Man-in-the-middle) соединение обрывается. Для этого в приложении хранится публичный ключ сертификата — тогда при обновлении сертификата сервера не придется выпускать новую сборку приложения, так как публичный ключ останется прежним.

Вся соль

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

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

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

После авторизации на сервере, мы получаем токен, который со временем «протухает». Действие токена может закончиться на сервере (минут через 10-15) или в приложении (если оно было свернуто около 2 минут). В этом случае пользователь снова должен ввести пин-код, чтобы получить новый токен. Токен не хранится между сессиями приложения, и при каждом новом запуске приложения его необходимо получать заново после ввода пин-кода.

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

Чистая биометрия

Согласно данным, которые приводит Apple, шанс совпадения отпечатков пальцев разных людей равен 1:50 000, в то время как шанс совпадения параметров лиц — 1:1 000 000.

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

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

Проверка на Jailbreak

Можно по-разному относиться к политике Apple по поводу ограничения пользовательских прав на контроль над смартфоном, но факт остается фактом: если пользователь решил поставить Jailbreak, про большинство аспектов безопасности iOS можно забыть. Любое установленное приложение потенциально может получить доступ ко всей хранимой информации.

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

Бюро находок

Даже если смартфон потеряли или украли, можно запретить операции в приложении. Для этого при авторизации важно отправлять на сервер информацию об устройстве (идентификатор, модель, версию iOS), и если пользователь потерял доступ к своему телефону, устройство можно внести в черный список на сервере.

Также при использовании приложения можно отправлять на сервер данные о геолокации пользователя (при условии, что он дал к ней доступ). Если операции производятся из нетипичных мест, есть возможность приостановить обслуживание до тех пор, пока пользователь не подтвердит, что ему действительно нужно перевести 300 долларов в Лихтенштейн.

Все важные изменения настроек и операции обязательно должны подтверждаться с помощью СМС-кода с ограниченным числом попыток ввода.

Редактировать фото

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

В заключение

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

Подробнее о том, как обеспечить безопасность приложений — у нас на Хабре.

{ "author_name": "Maria Skorik", "author_type": "self", "tags": [], "comments": 5, "likes": 0, "favorites": 6, "is_advertisement": false, "section_name": "blog", "id": "33463", "is_wide": "" }
{ "is_needs_advanced_access": false }

Комментарии Комм.

Популярные

По порядку

0

Прямой эфир

Подписаться на push-уведомления
[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "240х200_mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "flbq" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Плашка на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } } ]