Эта статья посвящена тому, как я обнаружил уязвимость в конечной точке восстановления пароля Apple, которая позволила мне захватить аккаунт iCloud. Уязвимость полностью пропатчена отделом безопасности Apple и больше не работает. В рамках баунти-программы Apple Security Team вознаградила меня 18 тысячами долларов, но я отказался их получать. В статье я расскажу о том, почему отказался от вознаграждения.
После обнаружения уязвимости захвата аккаунта Instagram я осознал, что многие другие сервисы подвержены брутфорсу на основе условий гонки. Поэтому я продолжил сообщать о подобных проблемах других поставщиков услуг, подверженных уязвимости, например Microsoft, Apple и некоторых других.
Многие люди путают эту уязвимость с обычной атакой брутфорсом, но это не так. В ней мы отправляем множество параллельных запросов серверу, чтобы воспользоваться уязвимостью условий гонки, присутствующей в ограничениях частоты запросов, позволяющих обойти защиту.
Теперь я расскажу о том, что обнаружил у Apple.
Опция забытого пароля Apple ID позволяет пользователям менять пароль при помощи 6-символьного цифрового OTP, отправленного на номер мобильного телефона или адрес электронной почты. После ввода правильного OTP пользователь может изменить пароль.
Страница забытого пароля Apple предлагает после ввода адреса электронной почты ввести номер мобильного телефона
Из соображений безопасности Apple для запроса OTP предлагает ввести доверенный телефонный номер вместе с адресом электронной почты.
То есть для эксплуатации этой уязвимости нам нужно знать доверенный телефонный номер, а также адрес электронной почты, чтобы запросить OTP, после чего мы можем попробовать перебрать все варианты кода из шести цифр, что потребует примерно 1 миллион попыток (10 ^ 6).
При тестировании выяснилось, что конечная точка восстановления пароля имеет довольно строгие ограничения частоты запросов. Если ввести больше 5 попыток, то аккаунт на следующие несколько часов будет заблокирован, и не поможет даже смена IP-адреса.
POST-запрос HTTP, отправленный конечной точке восстановления пароля, и её ответ
Затем я попробовал использовать брутфорс созданием условий гонки, отправляя одновременные POST-запросы серверу Apple, и обнаружил другие ограничения.
К моему удивлению, у Apple есть ограничения на частоту параллельных POST-запросов с одного IP-адреса, не только в конечной точке восстанолвения пароля, но и у всего сервера. Мы не можем отправить больше шести параллельных POST-запросов, они будут пропущены. При этом наш IP-адрес будет занесён в чёрный список для будущих POST-запросов с ошибкой 503.
Поэтому я решил, что сервер неуязвим к подобному типу атак, но у меня ещё оставалась надежда, так как это общие ограничения частоты запросов для всего сервера, не относящиеся конкретно к конечной точке проверки кода.
Проведя тестирование, я выяснил следующее:
- iforgot.apple.com резолвится в 6 IP-адресов по всему миру (17.141.5.112, 17.32.194.36, 17.151.240.33, 17.151.240.1, 17.32.194.5, 17.111.105.243).
- Существует два ограничения на частоту запросов, о которых мы уже говорили, одно срабатывает, если мы отправим больше 5 запросов конечной точке восстановления пароля (http://iforgot.apple.com/password/verify/smscode), второе относится к серверу Apple и срабатывает, когда мы отправляем больше 6 параллельных POST-запросов.
- Оба эти ограничения на частоту связаны с IP-адресом конкретного сервера Apple, то есть мы всё равно можем отправлять запросы (хоть и в пределах ограничений) на другой IP-адрес сервера Apple.
- Мы можем отправлять до 6 параллельных запросов IP-адресу сервера Apple (привязав iforgot.apple.com к IP-адресу) с одного клиентского IP-адреса в соответствии с их ограничениями. Как сказано выше, резолвится 6 IP-адресов Apple. То есть с одного IP-адреса мы можем отправлять до 36 запросов на 6 IP-адресов Apple (6 x 6 = 36).
- Следовательно, атакующему потребуется 28 тысяч IP-адресов для отправки до 1 миллиона запросов для успешной верификации кода из 6 цифр.
Кажется, что можно легко получить 28 тысяч IP-адресов при помощи поставщиков облачных сервисов, но здесь начинается самое сложное — сервер Apple демонстрирует странное поведение, когда мы пытаемся отправлять POST-запросы с поставщиков облачных услуг наподобие AWS, Google Cloud и т.п.
Ответ на любой POST-запрос от AWS и Google Cloud
Серверы отклоняют POST-запрос с ошибкой 502 Bad gateway, даже не проверяя URI и тело запроса. Я попробовал менять IP, но все они возвращали один и тот же код ответа, то есть сервер занёс в чёрный список все ASN каких-то поставщиков облачных сервисов, если я понял правильно.
Это усложняет атаку для тех, кто использует только облачные сервисы с хорошей репутацией, например AWS. Я попробовал разных поставщиков и наконец нашёл несколько провайдеров, IP-адреса в сетях которых не занесены в чёрный список.
Затем я попытался отправлять множество параллельных POST-запросов с разных IP-адресов, чтобы проверить возможность обхода защиты.
Сработало! Теперь я могу менять пароль любого Apple ID при помощи только доверенного телефонного номера.
Разумеется, эту атаку непросто провести, для успешной эксплуатации уязвимости требуется соответствующая система. Сначала нам нужно обойти SMS с кодом из 6 цифр, после код из 6 цифр, полученный на адрес электронной почты. Оба обхода основаны на одной методике и используют одну среду, поэтому нам не нужно ничего менять, пытаясь выполнить второй обход защиты. Даже если у пользователя включена двухфакторная аутентификация, мы всё равно сможем получить доступ к его аккаунту, потому что конечная точка 2FA имеет такое же ограничение по частоте и уязвима. Та же уязвимость присутствует и в конечной точке подтверждения пароля.
1 июля 2020 года я передал эту информацию с подробным описанием воссоздания эксплойта и видео отделу безопасности. Отдел безопасности Apple подтвердил и признал проблему спустя несколько минут после отправки отчёта.
С момента подтверждения я не получал от Apple никакой информации, поэтому продолжал отправлять просьбы об обновлении статуса. 9 сентября 2020 года мне сказали, что работают над исправлением.
Потом опять в течение пяти месяцев я не получал никакой информации, а когда я спросил о статусе, мне прислали это письмо
Мне сказали, что планируют устранить проблему в ближайшем обновлении безопасности. Мне стало любопытно, почему реакция на критическую уязвимость занимает так много времени.
Я продолжал тестировать уязвимость, чтобы проверить, устранена ли она, уже не полагаясь на них. Я протестировал её 1 апреля 2021 года и понял, что патч уязвимости был выпущен в продакшен, но Apple снова меня никак не проинформировала. Я спросил их, пропатчена ли проблема, и они ответили так же — что не могут поделиться никакой информацией о состоянии.
Я терпеливо ждал обновления статуса. Спустя месяц я сам написал, что проблема была пропатчена 1 апреля и спросил, почему мне об этом не сообщили. Также я написал, что хочу опубликовать отчёт в своём блоге.
Отдел безопасности Apple спросил меня, смогу ли я показать им черновик статьи перед публикацией. После этого дело приняло неожиданный оборот.
После отправки черновика они опровергли моё заявление, сказав, что эта уязвимость не позволяет захватывать большинство аккаунтов iCloud. Вот их ответ:
Как вы видите на показанном скриншоте письма, их анализ показал, что уязвимость сработает только против аккаунтов iCloud, не защищённых кодом/паролем устройств Apple.
Я возразил, что даже если вместо отправляемого на электронную почту кода из 6 цифр запрашивается код устройства (4 или 6 цифр), то к нему всё равно применяются те же ограничения частоты запросов и он будет уязвим к атакам брутфорсом на основе условия гонки. Мы сможем определить код соответствующего устройства Apple.
Также я заметил некоторые изменения на их странице поддержки, относящейся к восстановлению забытого пароля.
Ссылка: https://support.apple.com/en-in/HT201487.
На скриншоте выше показано, как выглядит страница сейчас, но до моего отчёта она выглядела иначе.
В октябре 2020 года эта страница выглядела так:
Ссылка из веб-архива: http://web.archive.org/web/20201005172245/https://support.apple.com/en-in/HT201487.
«In some cases» («в некоторых случаях») было добавлено в параграф в октябре 2020, то есть как раз после того, как мне сказали в сентябре 2020 года, что работают над исправлением.
Похоже, что всё было запланировано, страница была обновлена, чтобы подтвердить их заявление о том, что уязвимо только ограниченное число пользователей. Эта страница не обновлялась годами, но немного изменилась после моего отчёта. Это непохоже на совпадение.
Когда я спросил об этом, мне сказали, что страница обновлена из-за изменений в iOS 14. Я спросил, как связан сброс пароля при помощи доверенного адреса электронной почты/телефонного номера с iOS 14. Если это правда, то доверенный телефонный номер и адрес электронной почты использовался для сброса пароля до iOS 14? Если это так, то мой отчёт применим ко всем аккаунтам Apple. Ответа я не получил.
Я был разочарован и сообщил им, что опубликую пост в блоге со всеми подробностями, не дожидаясь их одобрения. Вот какой ответ они мне прислали:
Они согласовали звонок с инженерами Apple, чтобы те объяснили, что они выяснили с процессе своего анализа и чтобы ответить на вопросы, которые у меня могут возникнуть.
Во время звонка я спросил, почему это отличается от найденной мной уязвимости. Они сказали, что код устройства не отправляется ни в какую конечную точку сервера и проверяется самим устройством. Я возразил, что произвольное устройство Apple не сможет узнать код другого устройства без связи с сервером Apple. Они сказали, что данные действительно передаются на сервер, но они проверяются при помощи криптографической операции, и что большего они рассказать не могут из соображений безопасности.
Я спросил, что будет, если разобраться в процессе шифрования при помощи реверс-инжиниринга и воссоздать его, а затем забрутфорсить сервер Apple параллельными запросами. Какого-то конкретного ответа я не получил. Они пришли к выводу, что единственный способ подобрать код устройства брутфорсом — это брутфорс устройства Apple, который невозможен из-за локальных ограничений частоты запросов в системе.
Я не мог согласиться с инженерами Apple: логично, что должна существовать возможность воссоздания действий устройства Apple при отправке данных кода устройства на сервер.
Чтобы проверить их слова, я решил убедиться в этом сам. Если они сказали правду, конечная точка проверки кода устройства должна быть уязвима к брутфорсу на основе условий гонки. Спустя несколько часов тестирования я выяснил, что у них есть SSL pinning, специфичный для конечной точки проверки кода устройства, поэтому передаваемый на сервер трафик невозможно считать при помощи MITM-прокси наподобие burp/charles.
Благодаря checkra1n я воспользовался инструментом SSL Kill Switch и смог обойти pinning и считать передаваемый на сервер трафик.
Я разобрался, что Apple использует SRP (Secure Remote Password) — PAKE-протокол, позволяющий проверить, действительно ли пользователь знает нужный пароль, не отправляя его на сервер. То есть инженеры сказали правду, устройство не отправляет код непосредственно на сервер. Вместо этого сервер и клиент выполняют математические вычисления на основе ранее известных данных для получения ключа (это больше похоже на обмен ключами по протоколу Диффи-Хеллмана).
Я не буду вдаваться в специфику SRP и сразу перейду к тому, что важно в нашем контексте.
- На сервере Apple хранятся два значения, verifier и salt, связанные с каждым пользователем, они создаются в момент задания или обновления кода устройства.
- Когда пользователь инициирует SRP-аутентификацию с именем пользователя и динамическим значением A, сервер Apple отвечает ему отправкой соли этого пользователя и динамическим значением B.
- Клиент использует полученную от сервера соль для вычисления ключа в соответствии с SRP-6a.
- Сервер использует salt и verifier для вычисления ключа в соответствии с SRP-6a.
- В конце они подтверждают друг другу, что вычисленный ключ одинаков.
Подробнее о вычислениях SRP-6a можно здесь.
SRP известен тем, что предотвращает атаки брутфорсом, поскольку для каждого пользователя имеет salt и verifier, поэтому даже если кто-то украдёт нашу базу данных, ему придётся выполнять вычислительно затратный брутфорс для выявления один за одним пароля каждого пользователя. Это даёт владельцу базы данных достаточно времени, чтобы прореагировать на кражу.
Но в нашем случае не нужно брутфорсить большое количество аккаунтов. Для входа в аккаунт iCloud и определения кода устройства достаточно брутфорса одного пользователя.
Брутфорс возможен, только если у нас есть и salt, и verifier конкретного пользователя. Обойдя SMS-код, мы можем легко выдать себя за этого пользователя и получить salt. Однако проблема заключается в verifier. Нам нужно или как-то получить verifier с сервера, или обойти ограничение частоты в конечной точке проверки ключа.
Если мы обойдём ограничение частоты запросов, то можно будет пробовать различные комбинации полученного ключа на заранее вычисленных значениях кода устройства, пока мы не подберём совпадающий ключ. Очевидно, для получения ключа каждого из кодов устройств из 4 или 6 цифр (от 0000/000000 до 9999/999999) требуется много вычислений.
При вводе кода устройства в iPhone/iPad во время сброса пароля устойство инициирует SRP-аутентификацию, отправляя пользователю токен сессии, полученный из успешной SMS-верификации. Сервер отвечает, отправляя соль соответствующего пользователя. Код устройства и соль хэшируются для последующего вычисления ключа, который отправляется на p50-escrowproxy.icloud.com/escrowproxy/api/recover для проверки, соответствует ли он ключу, вычисленному на сервере (с помощью динамического значения, salt и verifier).
Отправляемый для проверки ключа POST-запрос выглядит так:
Строковая метка содержит все описанные выше данные, но она отправляется в формате блоба данных. До того, как начинать расшифровку блоба, первым делом я захотел проверить ограничение частоты запросов. Я отправил запрос параллельно 30 раз, чтобы проверить, уязвима ли конечная точка.
К моему потрясению, она не была уязвимой. Из 30 запросов 29 было отклонено с внутренней ошибкой сервера.
Ограничение частоты запросов должно выполняться или на самом сервере Apple, или в HSM (hardware security module). В любом случае, логика ограничения должна быть запрограммирована так, чтобы предотвращать угрозу гонки. Существовала очень маленькая вероятность, что эта конечная точка не была уязвимой к угрозе гонки, потому что все протестированные мной конечные точки были к ней уязвимы — валидация по SMS-коду, валидация по коду в электронном письме, двухфакторная авторизация, проверка пароля.
Если они пропатчили её после моего отчёта, уязвимость стала гораздо более серьёзной, чем я изначально думал. Благодаря брутфорсу кода устройства можно обнаружить правильный код по различию ответов. То есть мы не только можем захватить любой аккаунт iCloud, но и определить связанный с ним код устройства Apple. Даже несмотря на то, что такая атака сложна, если моё предположение верно, эта уязвимость могла хакнуть любой iPhone/iPad, имеющий код устройства из 4 или 6 цифр.
Так как теперь параллельные запросы обрабатываются правильно, я никак не смогу проверить свою догадку. Единственное, что я мог сделать — написать Apple, но по этой теме мне ничего не ответили.
4 июня 2021 года я получил от Apple электронное письмо о вознаграждении.
На веб-сайте Apple написано, что награда за захват аккаунта равна 100 тысячам долларов. За извлечение конфиденциальных данных с заблокированного устройства Apple — 250 тысячам долларов. Мой отчёт соответствовал обоим случаям (если предположить, что конечная точка проверки кода устройства была пропатчена после отправки отчёта), поэтому моё вознаграждение должно было равняться 350 тысячам долларов. Даже если бы они решили наградить за самый важный из двух случаев, она всё равно должна быть равной 250 тысячам.
Продажа подобных уязвимостей государству или частным баунти-программам наподобие zerodium могло принести гораздо больше денег. Но я выбрал этичный путь и не ожидал ничего другого, кроме как указанных Apple сумм наград.
https://developer.apple.com/security-bounty/payouts/
Однако 18000 долларов даже не близки к истинной награде. Предположим, что мои допущения неверны и конечная точка проверки кода устройства Apple не была уязвимой до моего отчёта. Но даже и в этом случае назначенная награда несправедлива, если взглянуть на серьёзность уязвимости:
- Обход двухфакторной аутентификации. По сути, благодаря обходу 2FA как будто и не существует. Люди, полагающиеся на 2FA, уязвимы. Само по себе это является крупной уязвимостью.
- Обход ограничений частоты запросов проверки пароля. Все аккаунты Apple ID, имеющие распространённые/слабые/хакнутые пароли, уязвимы даже при включенной двухфакторной аутентификации. После взлома атакующий может отслеживать местоположение устройства, а также удалённо стирать с него данные. Хак iCloud знаменитостей в 2014 году был вызван в основном слабыми паролями.
- Обход верификации по SMS. Если мы знаем код или пароль устройства, связанного с аккаунтом iCloud. Допустим, кто-то из ваших друзей или родственников знает код вашего устройства, тогда при помощи этой уязвимости он может захватить ваш аккаунт iCloud и полностью стереть все данные с устройства через Интернет, без необходимости физического доступа.
- Мы можем захватить все Apple ID, не связанные с защищённым кодом устройством Apple благодаря обходу кода верификации по SMS и электронной почте, то есть
- Любое устройство Apple без кода или пароля, например, у пользователей, которые отключили или не задали код/пароль.
- Любой Apple ID, созданный без устройства Apple, например, в браузерах или в приложении для Android и не используемый в защищённых паролем устройствах Apple
- Например больше 50 миллионов пользователей Android скачало приложение Apple Music. Большинство из них, вероятно, не использовало устройства Apple. Однако они всё равно являются пользователями Apple и их информация (кредитные карты, платёжные адреса, подробности подписки и т.п.) может быть раскрыта.
Компания могла и не выплачивать максимальную сумму награды за захват аккаунта iCloud (100 тысяч долларов), но должна была хотя бы выплатить близкую сумму, учитывая важность уязвимости.
Проделав всю эту работу и прождав целый год, я так и не получил заслуженного мной из-за несправедливого решения Apple. Поэтому я отказался получать награду и сообщил им, что это было несправедливо. Я попросил пересмотреть решение о сумме награды или позволить мне опубликовать отчёт со всей информацией. Ответа на мои письма не было. Поэтому я решил опубликовать свою статью, не дожидаясь бесконечно их ответа.
То есть я передал свои исследования Apple бесплатно, чтобы не брать несправедливо назначенную награду.
Я призываю отдел безопасности Apple быть более открытым и справедливым, хотя бы в будущем. Также я бы хотел поблагодарить Apple за пропатченную уязвимость.
Повторюсь — уязвимость полностью устранена и описанные в статье сценарии больше не работают. Благодарю за чтение статьи!
Автор:
PatientZero