![](https://habrastorage.org/webt/81/it/yp/81ityp72a1gfradmmbpfonlhc5u.jpeg)
Недавняя история о бэкдоре в популярнейшей NPM-библиотеке заставила многих задуматься о том, насколько мы доверяем стороннему коду и как смело используем его в своих проектах (потенциально подставляя тем самым пользователей наших продуктов).
Но ещё за месяцы до того, как «гром грянул», Феликс Краус (известный мобильным разработчикам как создатель Fastlane) говорил на нашей конференции Mobius 2018 Piter о похожем: доверии мобильных разработчиков к сторонним SDK. Если мы скачиваем популярный SDK от известной компании, то вот там-то всё хорошо, или тоже что-то может пойти не так? Где тут есть вектор атаки и о чём нам стоит задумываться в связи с этим?
А теперь мы расшифровали и перевели его доклад — так что под катом можете хоть посмотреть оригинальное видео, хоть прочитать русскоязычную текстовую версию. Поскольку Краус занимается iOS-разработкой, все примеры приведены тоже из iOS, но Android-разработчики могут абстрагироваться от конкретных примеров и тоже задуматься.
Безопасность SDK
Посмотрев, какие SDK наиболее популярны в iOS-разработке сегодня, я решил исследовать, насколько они уязвимы по отношению к самым обыкновенным сетевым атакам. Целых 31% из них оказались потенциальными жертвами для простых атак man-in-the-middle, означающих, что хакер внедряет в SDK свой зловредный код.
Но в общем-то, стоит ли так пугаться? Что самое худшее он может сделать с вашим SDK? Настолько ли всё это серьёзно? Вы должны понимать, что SDK, включённый в bundle вашего приложения, запускается в его области видимости — то есть SDK получает доступ ко всему тому, чем оперирует ваше приложение. Если пользователь разрешает приложению доступ к геолокационным данным или, скажем, к фото, то эти данные также оказываются доступными и для SDK (не требуется никаких дополнительных разрешений). Другие данные, к которым возможен доступ из SDK: шифрованные данные iCloud, API-токены, а кроме того, все UIKit Views, содержащих массу разной информации. Если же хакер перехватывает SDK, имеющее доступ к такого рода данным, то последствия, как вы понимаете, могут быть достаточно серьёзными. При этом затронутыми окажутся одновременно все пользователи приложения.
Как именно это может произойти? Давайте сделаем шаг назад и поговорим о базовых сетевых вещах и о злоупотреблении ими.
Сеть
Предупрежу, что мои объяснения не будут на 100% точными и детальными. Моя цель — донести суть, поэтому я буду представлять всё в несколько упрощённом виде. Если вас заинтересуют подробности, то рекомендую вам заглянуть в мой блог либо исследовать тему самим.
Как вы помните, главное отличие протокола HTTPS от протокола HTTP — шифрование данных при передаче. Отсутствие шифрования у HTTP, по большому счёту, означает, что любой хост, находящийся внутри сети, при желании может свободно прослушивать и модифицировать любые передаваемые по ней пакеты; при этом проверить, была ли нарушена целостность пакета, не представляется возможным. Всё это справедливо и для публичных Wi-Fi сетей, и запароленных, и локальных Ethernet-сетей.
При использовании HTTPS хосты сети также могут прослушивать передаваемые пакеты, однако они не имеют возможности их вскрывать — видны только метаданные пакета, в частности, адреса хоста-отправителя и хоста-получателя. Кроме того, HTTPS предоставляет возможность верификации: получив пакет, вы можете проверить, подвергался ли он изменениям за время нахождения в пути.
Раньше всё работало следующим образом. Когда вы вводили в адресную строку «google.com» без указания протокола, браузер по умолчанию отсылал ваш запрос через протокол HTTP. Но поскольку сервер Google предпочитает взаимодействовать через HTTPS, в ответ от него вы получали новую ссылку (редирект) с префиксом «https://». Перед вами скрин Charles Proxy (инструмента мониторинга HTTP/HTTPS трафика), демонстрирующий это:
![](https://habrastorage.org/webt/vt/ih/la/vtihla4640ej2korymb2mjxnfze.jpeg)
Однако сама новая ссылка высылалась через протокол HTTP. Несложно понять, что тут может пойти не так: и запрос, и ответ передаются по HTTP, а значит, можно, к примеру, перехватить пакет ответа и заменить в нём адрес location URL обратно на «http://». Этот простой вид атаки носит название «SSL-стрип». На сегодняшний день браузеры уже научились работать несколько иначе. Но понимание, что такое SSL-стрип, нам далее пригодится.
По временам учёбы вы можете помнить сетевую модель OSI. Я её воспринимал как что-то невыносимо скучное. Но позже обнаружил, что, как ни странно, модель OSI существует не просто так и даже может быть полезной.
Рассматривать её в деталях мы не будем. Главное, что надо понимать: всё состоит из нескольких слоёв, отвечающих за разные вещи и при этом находящихся в постоянном взаимодействии друг с другом.
Один из слоёв пытается определить, какой MAC-адрес соответствует определённому IP-адресу. Для этого выполняется специальный широковещательный запрос, фиксируется первое отреагировавшее устройство, и впоследствии пакеты отправляются ему.
![](https://habrastorage.org/webt/wr/xr/og/wrxrogxnduhmpclao2gieuh_1du.jpeg)
Проблема в том, что хакер может откликаться на запрос быстрее: «да-да, шлите мне все пакеты». Это называют ARP-спуфингом или ARP cache poisoning. В таком случае схема вашего взаимодействия с интернетом превращается в такую:
![](https://habrastorage.org/webt/rx/tm/zz/rxtmzz0yzoqqzzqmqqqfoybanfo.jpeg)
Все пакеты теперь проходят через устройство хакера, и, если трафик не зашифрован, он сможет осуществлять и чтение, и запись. В случае с HTTPS возможности меньше, но можно проследить, к каким хостам вы обращаетесь.
Что интересно, фактически те же самые полномочия имеют интернет- и VPN-провайдеры. Они являются посредниками в вашем взаимодействии с интернетом и точно так же представляют потенциальную угрозу ARP-спуфинга.
В самом по себе подходе man-in-the-middle ничего нового нет. А вот как именно всё это применимо к мобильным SDK?
Мобильная специфика
CocoaPods — это стандартное средство управления зависимостями, применяемое в iOS-разработке. Использование CocoaPods для опенсорсного кода считается практически безопасным — обычно хостится на GitHub, обычно доступ по HTTPS или SSH. Тем не менее, мне удалось найти уязвимость, основанную на использовании HTTP-ссылок.
Дело в том, что CocoaPods даёт возможность установки SDK с закрытым исходным кодом, и от вас требуется просто указать URL. Нет проверки, что трафик будет зашифрованным, и многие SDK предлагают HTTP-адрес.
В связи с этим я направил разработчикам CocoaPods несколько пулл-реквестов, и вскоре они выполнили доработку. Теперь новые версии CocoaPods проверяют указываемую пользователем ссылку, и в случае, если она нешифрованная, отображают предупреждение. Так что мой совет: всегда обновляйте версии CocoaPods и не игнорируйте предупреждения.
Ещё интереснее рассмотреть то, как проходит установка неопенсорсных SDK не из CocoaPods. Возьмём, к примеру, платформу Localytics.
![](https://habrastorage.org/webt/sr/23/ia/sr23iakmm1buwyy2unns4bdurde.jpeg)
Страница docs.localytics.com не является шифрованной. Казалось бы, в данном случае этим можно и пренебречь, ведь это всего лишь документация. Но заметьте, что страница в числе прочего содержит ссылку на скачивание бинарников. Ссылка может быть и шифрованной, однако никакой безопасности в данном случае это не гарантирует: поскольку сама страница будет передаваться через HTTP, её можно перехватить и заменить в ней ссылку на нешифрованную. Об этой уязвимости разработчики localytics были поставлены в известность, и она уже устранена.
Можно поступить и иначе: не менять ссылку на HTTP, а оставить HTTPS, но подменить сам адрес. Обнаружить такое будет очень непросто. Посмотрите на данные две ссылки:
![](https://habrastorage.org/webt/yn/dg/bh/yndgbhc4smvrrd8-zlz4perb2ue.jpeg)
Одна из них принадлежит мне. Какая из них — от настоящих разработчиков, а какая нет? Попробуй пойми.
Практическая проверка
Дальше я решил проверить свои предположения, попробовав в реальности подменить содержимое SDK с помощью MITM-атаки. Оказалось, что и это не так сложно. Для построения и приведения в действие своей схемы мне потребовалось буквально несколько часов настройки простейших общедоступных инструментов.
![](https://habrastorage.org/webt/dt/jg/bn/dtjgbnfnqhzoijhjgnwor03kphw.jpeg)
Осуществлять перехват я поручил обычному Raspberry Pi. Включённый в локальную сеть, он мог прослушивать в ней трафик. В перехваченных же пакетах он должен был, во-первых, заменять все ссылки HTTPS на ссылки HTTP, а затем заменять все .zip-файлы Localytics iOS на файл hack.zip. Всё это оказалось просто и сработало на ура.
![](https://habrastorage.org/webt/eh/23/qo/eh23qohlb7tenaz3oqjm4rvvaak.jpeg)
В полученном архиве появлялся файл trollface.jpg, а в файле Info.plist — строка «Modified by KrauseFx». Много ли требовалось для такой атаки? Всего лишь два условия:
- В вашу сеть сумели получить доступ (помните, что для интернет- и VPN-провайдеров это и вовсе не вопрос). К скольки сетям кофеен и гостиниц мы подключаемся?
- Инициируемая загрузка — нешифруемая.
Вы скажете «но я просто смотрю на значок Secure в браузере, значит, у меня всё будет ОК». И если находишься на сайте Amazon, уж там-то всё должно быть в порядке, так?
Предлагаю рассмотреть сайт Amazon. AWS Mobile SDK — их личный SDK, который они предоставляют разработчикам для взаимодействия с сервисом.
![](https://habrastorage.org/webt/q7/0m/r_/q70mr_tag60jo35qv7jvwqkiti4.jpeg)
Значок «secure», известный сайт — ничего вроде бы не предвещает беды. Но увы — только на первый взгляд. Ссылка на скачивание SDK указана без префикса вообще (ни https://, ни http://). И при этом она должна увести пользователя на другой хост. Поэтому браузер переключится с HTTPS на HTTP. Как видите, и здесь загрузка SDK — нешифрованная! На данный момент уязвимость уже исправлена разработчиками Amazon, однако она действительно имела место быть.
Надо сказать, что разработка современных браузеров тоже ведётся не без внимания к вопросам безопасности. Например, если вы грузите страницу, используя HTTPS, и какая-нибудь одна картинка указана через ссылку-HTTP, то Google Chrome уведомит вас о так называемом «смешанном контенте». Но для загрузок такая мера безопасности не предусмотрена: браузеры не отслеживают, какой протокол срабатывает для указанной на странице ссылки на скачивание. Поэтому в рамках этого проекта я писал разработчикам браузеров с просьбой предусмотреть отслеживание смешанного контента и уведомление о нём пользователей.
Кража данных Apple ID
Теперь посмотрим на другую проблему. Пользователям iPhone должно быть знакомо такое регулярно всплывающее окно:
![](https://habrastorage.org/webt/wu/1n/ag/wu1nagr8xm6_ancma_ehch9kmr8.jpeg)
Слева вы видите оригинальный вариант iOS, справа — мою копию. О том, как несложно сымитировать подобное окно, я писал в своём блоге несколько месяцев назад. На то, чтобы воссоздать вид, ушло 20 минут.
iPhone достаточно часто запрашивает аутентификационные данные iCloud, причём для пользователя обычно остаётся неясным повод для запроса. Пользователи так привыкли к этому, что вводят пароль автоматически. Вопрос о том, кто запрашивает пароль — операционная система или приложение — просто не приходит в голову.
Если вы думаете, что есть сложность в том, чтобы получить адрес почты, к которому привязан Apple ID, то вы преувеличиваете: это можно сделать и через книгу контактов, и через контейнеры iCloud (при наличии доступа приложения к iCloud, о котором вы можете узнать из UserDefaults данного приложения). А самый простой вариант — попросить пользователя лично ввести свой имейл: по идее, это даже не должно вызвать у него удивления, ведь в iOS действительно существует разновидность окошка, запрашивающего не только пароль, но и имейл.
Я подумал: «Что, если взять этот имеющийся у меня код формы запроса и при помощи подмены SDK проникнуть с ним во много разных приложений, чтобы похищать с помощью них всех пароли от iCloud?» Насколько сложна эта задача?
![](https://habrastorage.org/webt/nc/pm/th/ncpmthvedngxf9jr0gghuucsdfo.jpeg)
Предположим, у нас есть совершенно чистый Mac, без каких-либо установленных на него VPN или прокси, но в той же сети есть наш Raspberry Pi. На Mac в Xcode у нас открыт проект iOS-приложения, содержащего абсолютный минимум кода — простое отображение карты местности и не более того.
Теперь открываем браузер, заходим на Amazon Web Services. Находим страничку AWS Mobile SDK и переходим по ссылке на скачивание. Распаковываем скачанный бинарник и перетаскиваем все фреймворки внутрь нашего проекта в Xcode. Затем импортируем библиотеки. От нас даже не требуется вызывать какой-то код — достаточно того, что он будет загружен. Замечу, что в ходе всего процесса Xcode не выдал никаких предупреждений.
Что же происходит при перекомпиляции приложения? На экране появляется та самая копия окошка, предлагающая мне авторизоваться в iTunes Store. Я ввожу пароль, окошко исчезает. Параллельно наблюдая за логом приложения, я вижу как в нём моментально отображается введённый мной пароль — перехват данных Apple ID выполнен. Несложно было бы отправить эти данные куда-то на сервер.
Тут вы можете сказать «Ну, я при разработке сразу заметил бы эту форму ввода и понял, что что-то не так». Но если у тебя аудитория в миллионы пользователей, можно сделать так, чтобы она вылезала только один раз на тысячу, и при тестировании осталась незамеченной.
И опять-таки, много ли нам понадобилось, чтобы осуществить атаку? Нужно было, чтобы в сети находился наш компьютер (и Raspberry Pi оказалось достаточно). HTTP или HTTPs — в данном случае не имело значения, шифрование бы не спасло ситуацию. Все использованные мной программные средства — самые простые, были взяты мной из публичного доступа. При этом я — обыкновенный разработчик, без особого знания и опыта взломов.
Перехват управления
Предыдущий пример внедрял зловредный код в iOS-приложение. А что, если бы нам удалось заполучить контроль над компьютером разработчика вообще? Возможность запустить код на вашем устройстве, как вы понимаете, даёт хакеру огромную власть. Он сможет активировать удалённый доступ через SSH, установить кейлоггер и т.д. Он сможет в любое время наблюдать за вами, фиксировать ваши действия, пользоваться файловой системой. Также он сможет устанавливать новые сертификаты SSL и с помощью них перехватывать все запросы, производимые вами в сеть. Словом, у кого-то есть возможность запустить код на вашем компьютере — и вы полностью скомпрометированы.
Я подумал: «что из iOS SDK я могу использовать для этого?» Есть сервис, предоставляющий SDK посредством команды curl и ссылки HTTP с перенаправлением вывода команде sh. То есть ваш терминал скачает и запустит shell-скрипт.
![](https://habrastorage.org/webt/rs/qn/-q/rsqn-qfhxfgnnd7gmlydtgscjd4.jpeg)
Сам по себе такой способ установки уже подвергает вас риску, не делайте так. Но в данном случае ещё и использовался протокол HTTP. Что в таком случае возможно сделать?
![](https://habrastorage.org/webt/_q/sz/e7/_qsze7du6xwdlkwvu9xlez_3x_k.jpeg)
Предположим, вы — пользователь. Вы заходите на официальную страницу документации. Обращаете внимание на то, что страница шифрована протоколом HTTPS — здорово! Вы копируете команду, запускаете её у себя. Команда выполняется в течение нескольких секунд. Что же успело произойти за это время?
А за это время успел сработать несложный механизм атаки с участием моего Raspberry Pi. Загруженный пользователем shell-скрипт «UpdateSDK» содержал небольшое вкрапление моего собственного кода. И теперь мне разрешён удалённый доступ к вашему компьютеру через SSH, а также у вас был установлен кейлоггер.
![](https://habrastorage.org/webt/gi/rm/zg/girmzgyhbxc089efo9xq-qjtbto.png)
Слева вы видите «ваш» терминал, а справа — мой Raspberry Pi, который в режиме реального времени уже показывает всё, что вы вводите на клавиатуре. Запустив с Raspberry Pi SSH, я авторизуюсь, используя логин и пароль, только что прописанные при помощи кейлоггера, и таким образом получаю полный доступ к управлению вашим Mac и к его файловой системе. А также, вероятно, доступ ко многому у вашей компании-работодателя.
В заключение
Насколько вероятно, что такое может произойти с вами? Ведь разработчики всё же стараются использовать безопасный Wi-Fi, покупают себе VPN.
Лично я тоже думал, что осторожен, пока однажды не открыл настройки своего Mac и не обнаружил в истории более 200 подключений к небезопасным сетям Wi-Fi. Каждое такое подключение — это потенциальная угроза. И даже пользуясь проверенной сетью, вы не можете быть на 100% уверенными в своей безопасности, так как не можете знать, не было ли скомпрометировано какое-нибудь из устройств этой сети (как мы только что увидели).
Атаки через небезопасные сети Wi-Fi происходят очень часто. Их легко проводить в публичных местах, таких как гостиницы, кафе, аэропорты и, кстати, конференции :) Представьте, спикер рассказывает о каком-нибудь SDK, и, как водится, параллельно часть зрителей пробует его установить, подключившись к раздаваемому здесь Wi-Fi. А как я уже говорил, злоупотребить своими правами сетевому провайдеру очень легко.
Точно так же и с VPN — вы просто передаёте себя в руки провайдера. И кому лучше довериться — VPN-провайдеру или своей локальной сети и её пользователям? Неясно.
В ноябре 2017 года я провёл своё исследование и проанализировал на наличия в них перечисленных уязвимостей топ 41 самых популярных SDK для iOS (не считая SDK от Google и Facebook, они все надёжно защищены).
![](https://habrastorage.org/webt/kt/jr/4s/ktjr4sc3rvflmum-9izfgnb1aua.jpeg)
Как видите, 31.7% SDK не прошли тестов. Об имеющихся проблемах я сумел сообщить почти всем поставщикам. От одного я получил ответ буквально сразу же, проблема была решена в течение трёх дней. Пятеро команд тоже отреагировали, но потратили на доработку чуть больше времени — около месяца. Семеро же не потрудились ответить на мой репорт вообще и так и не исправили ничего по сей день. Напомню, речь не о каких-то малоизвестных проектах. Все они входят в число самых известных SDK и имеют десятки тысяч пользователей, разрабатывающих с помощью этих SDK iOS-приложения, которые, в свою очередь, используют миллионы пользователей iPhone.
Важно понимать, что пользователи закрытых приложений всегда подвержены большим рискам, пользовали опенсорсных — меньшим. Вы не можете проверить, как работает закрытое приложение. Крайне сложно судить о наличии в нём безопасных решений. Вы можете сравнивать хеши и хеш-суммы, но этим вы, максимум, сумеете проверить успешность загрузки. Опенсорсные продукты, напротив, вы можете исследовать основательно, вдоль и поперёк, а значит, сможете обеспечить себе больше защиты.
Помимо атак man-in-the-middle, существуют и другие. Хакер может атаковать сервер, с которого осуществляется загрузка SDK. Бывает также, что компания, поставляющая SDK, намеренно включает в код так называемые бэкдоры, через которые она впоследствии сможет осуществлять несанкционированный доступ к устройствам пользователей (возможно, местное правительство требует устанавливать бэкдоры, а возможно, это инициатива самой компании).
А мы несём ответственность за продукт, который поставляем. Мы должны быть уверены, что не подводим пользователя и соблюдаем GDPR. Атаки через SDK серьёзны в первую очередь потому, что они массовы — направлены не на одного разработчика, а на миллион пользовательских устройств за раз. Эти атаки могут проходить почти незаметно для вас. Открытый исходный код помогает вам защититься от такого, с закрытым всё гораздо сложнее — используйте его только когда можете смело ему доверять. Спасибо за внимание.
Если вам понравился этот доклад, обратите внимание: следующий петербургский Mobius состоится 22-23 мая, билеты уже в продаже, и постепенно они дорожают.