July 30, 2020

ВЗЛАМЫВАЕМ IOS

Сразу к делу. Для начала нам нужно узнать, как работает AirDrop:

AirDrop это протокол для передачи файлов внутри одноранговой сети. Он может работать как по обычной локальной сети, так и по воздуху между любыми устройствами Apple. Мы будем разбирать последний случай, когда два устройства не подключены в общую сеть, а просто находятся рядом, например два человека c телефонами едут в вагоне метро и не подключены к общему Wi-Fi.

Первый этап передачи через AirDrop — рассылка BLE пакета

Чтобы инициировать передачу данных через AirDrop, телефон инициатора посылает широковещательный BLE-пакет, в котором содержится захешированная информация об iCloud аккаунте и телефонном номере владельца устройств инициатора, с предложением установить подключение через протокол AWDL (Apple Wireless Direct Link), что-то вроде Wi-Fi Direct из мира Android. Структура этого BLE-пакета очень интересна, мы разберем ее дальше.

На стороне получателя AirDrop может быть в трех состояниях:

  • Выключен — не будет обнаруживаться вообще
  • Только для контактов — принимать файлы только от контактов из записной книжки. При этом контактом считается номер телефона или email, к которому привязан icloud аккаунт. Здесь работает та же логика привязки аккаунтов, что и с мессенджером iMessages.
  • Для всех — телефон будет обнаруживаться для всех

Настройки приватности AirDrop. Состояние по умолчанию установлено «Для контактов».

В зависимости от настроек приватности, телефон либо продолжит установку соединения через AWDL, либо просто проигнорирует BLE-пакет. Если для AirDrop установлена настройка «для всех», то на следующем шаге устройства соединятся друг с другом через AWDL, поднимут между собой IPv6-сеть, внутри которой AirDrop будет работать как обычный прикладной протокол с помощью mDNS через стандартный протокол IP.

Для экспериментов вы можете посмотреть за тем как работает AWDL на макбуке. Весь обмен по этому протоколу происходит через интерфейс awdl0, который можно легко снифать с помощью Wireshark или tcpdump.

На данном этапе мы знаем три сущности:

Bluetooth LowEnergy (BLE) пакет — этот пакет содержит данные, на основании которых телефон решает, есть ли инициатор в его списке контактов или нет.

Apple Wireless Direct Link (AWDL) — фирменная замена Wi-Fi Direct от Apple, включается если общение по BLE прошло успешно.

AirDrop — прикладной протокол, который работает внутри обычной IP-сети с использованием mDNS, HTTP и т.д. Может работать внутри любой Ethernet-сети.

Как сниффать траффик

Для начала запомним:

  • AirDrop сработает только если телефон разблокирован — лучше всего, если цель непрерывно смотрит в телефон. Чаще всего это происходит в местах где скучно, например в метро.

Способ классический — только телефон

Подходит всем у кого есть айфон, не требует особых навыков кроме социальных. Переводим AirDrop в режим Everyone и спускаемся в метро. В обычный день (до самоизоляции) в вагоне московского метро я наблюдал примерно такую картину:

List of targets

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

Пейлоад (отправляем любые изображения)

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

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

Автоматическая дикпик-машина

Если тебе лень генерировать и рассылать пейлоады вручную, и ты хочешь автоматизировать процесс, можно изготовить автоматическую дикпик-машину, которая в фоне будет рассылать картинки по AirDrop всем, кто находится в радиусе действия. В качестве аппаратной платформы будем использовать raspberry pi zero, но подойдет любой комп с линуксом, главное чтобы Wi-Fi карточка поддерживала мониторный режим и инъекции пакетов.

Рассылатель дикпиков по Airdrop на базе raspberry pi zero w + батарейный шилд UPS Lite

Есть программы AirDrop флудеров для Jailbreak айфонов, они работают стабильнее, чем открытые варианты на raspberry pi

Настройка OWL на raspberry pi подробно описана на сайте проекта, но я предпочитаю использовать сборку Kali Linux для Raspberry Pi Zero, потому что в ней уже установлены патчи nexmon, для активации мониторного режима Wi-Fi на rpi0.

Важно помнить, что Airdrop (вернее AWDL) у пациентов активируется только после получения BLE-пакета. Поэтому мы должны его посылать с интервалом в несколько секунд. Это можно сделать с помощью утилиты py-bluetooth-utils. Используя функцию start_le_advertising(), я посылаю строку данных из примеров apple bleee: 000000000000000001123412341234123400.

После того, как вы получили работающий OWL-демон, дальше можно запускать форк opendrop. В репозитории лежит скрипт flooder.py, который рассылает всем картинку kak_dela.jpeg.

По моим наблюдениям raspberry pi zero w работает нестабильно в мониторном режиме. Примерно через 20 минут активной работы флудера, вылетает подсистема Wi-Fi. Проблема описана у автора pwnagotchi, и предположительно вызвана перегревом. Нужно предусмотреть watchdog или использовать более стабильное железо

Структура BLE-пакета

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

Как телефон на принимающей стороне понимает, есть ли номер/email инициатора в его списке контактов или нет? Я очень удивился, когда узнал ответ: инициатор шлет свой номер и email в виде хеша sha256, но не целиком, а только первые 3 байта.

Структура BLE-пакета от инициатора AirDrop. По хешам от телефонного номера и email ответчик понимает, есть ли инициатор в его списке контактов.

Например, если ваш Apple-аккаунт (он же iCloud, он же iMessages) привязан к номеру +79251234567, хеш от него будет считаться так:

echo -n "+79251234567" | shasum -a 256
07de58621e5d274f5844b6663a918a94cfd0502222ec2adee0ae1aed148def36

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

Важно также помнить, что настройка приватности AirDrop не влияет на данные в BLE-пакете. Хеш от телефонного номера будет содержаться в нем, даже если установлена настройка «Для всех». Также BLE-пакет с хешем телефонного номера посылается в случае открытия окна Share (Поделиться) и при вводе пароля к Wi-Fi сети.

Подробный разбор структуры BLE-пакетов и возможных атак на него читайте в исследовании Apple Bleee.

В исследовании Apple Bleee опубликованы готовые скрипты на python для автоматизации анализа данных в BLE-пакетах. Я очень рекомендую изучить исследование и попробовать программы, там много чего интересного.

AWDL (Apple Wireless Direct Link)

AWDL — это такая проприетарная надстройка Apple над обычным Wi-Fi, реализующая что-то вроде Wi-Fi Direct. Я до конца не знаю как она работает, там особый способ анонсирования и согласования каналов, и работает это только на проприетарных драйверах Apple. То есть только макбуки/айфоны могут соединяться через AWDL.

Грустные владельцы телефонов Android пока еще только мечтают о нормально работающей функции Wi-Fi Direct.

Но не так давно ребята из seemoo-lab написали полностью открытую реализацию AWDL и назвали ее Open Wireless Link (OWL). Для запуска OWL, адаптер Wi-Fi должен поддерживать мониторный режим и инъекции пакетов, поэтому запускается не на каждом железе. На сайте есть примеры настройки на raspberry pi. Работает это существенно хуже оригинального AWDL, например время установки подключения растягивается на ~10 секунд вместо пары секунд у оригинала, но работает.

Также эти ребята написали с нуля реализацию протокола AirDrop на питоне, называется OpenDrop. Его можно использовать как в связке с OWL, для запуска AirDrop на линуксе так и с оригинальным AWDL на macOS.

Режим маньячелло — я знаю твой номер

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

Как мы уже узнали ранее, в BLE-пакетах, которые посылает инициатор, содержатся первые три байта от sha256 телефонного номера. Этот хеш можно поймать в момент, когда жертва нажмет кнопку «поделиться» и запустит сканирование airdrop устройств или тапнет в поле ввода Wi-Fi пароля от новой сети (таким образом apple ищет друзей в радиусе действия, у которых можно запросить пароль от сети).

Тебе потребуется каким-либо образом тригернуть посылку хеша от жертвы, и поймать его. Я использую утилиты из репозитория Apple Bleee. Так как Bluetooth MAC-адреса устройств рандомные и постоянно меняются, тебе придется найти другой способ определить нужное устройство в этом списке. Задача упрощается тем, что iOS транслирует текущее состояние телефона вроде: выключен экран, включен экран, lock screen, разблокирован и т.д. Поэтому просто наблюдая за действиями жертвы можно сопоставить текущее состояние устройства с устройством в таблице. Проще всего поймать момент, когда юзер достал телефон из кармана, включил экран и разблокировал телефон пальцем или лицом. Все это будет видно в сниффере.

Значок Х означает, что пойман пакет с хешами телефона.

Их парсер иногда ломается, но чаще всего работает. Я не буду полностью пересказывать суть уязвимости, так как это подробно разобрано авторами Apple Blee, опишу лишь свой опыт. Скажу только, что я использую USB Bluetooth-адаптер на чипе CSR 8510, так как у меня он работает сильно стабильнее, чем встроенный в макбук Bluetooth-адаптер, проброшенный в виртуальную машину.

Итак мы поймали хеш от телефона жертвы и получили заветные три байта от хеша номера телефона.

Перехваченный BLE-пакет с хешем номера телефона, с помощью утилиты read_ble_state.py

Мы знаем, что в России все мобильные номера начинаются с кода +79 и, скорее всего, у нашей жертвы телефон имеет такой же код. Получается, мы имеем диапазон номеров от +79000000000 до +79999999999, около миллиарда номеров.

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

Дальше генерируем sha256 от всех номеров и сохраняем от каждого хеша только первые 3 байта. Заносим этот список в Sqlite базу, для ускорения поиска строим индекс.

Так выглядят данные в базе:

Все российские телефонные номера и первые три байта хеша

Дальше, имея хеш жертвы, мы можем поискать все совпадения в базе. Обычно на один хеш выходит 15-30 совпадений.

Все номера, совпавшие с хешем жертвы

Очевидно, что не все эти номера реально используются. Мы можем отсечь лишние с помощью HLR-запроса или невидимой SMS. Из 30 номеров в сети оказалось 5.

Результат выполнения HLR-запроса. Зеленым выделены номера в сети.

Я бы мог продолжать просеивать номера, например, добавить их все в Telegram/Whatsapp и посмотреть аватарки, проверить через базы вроде Getcontact и так далее. Но проще оказалось просто позвонить поочередно на все пять номеров и смотреть когда у жертвы зазвонит телефон