Разбираем уязвимости проверки сертификатов SSL/TLS в небраузерном софте

Первоначально разработанный для браузеров, SSL/TLS-протокол позже стал стандартом де-факто вообще для всех защищенных интернет-коммуникаций. Сейчас он используется для удаленного администрирования виртуальной инфра­структуры, развернутой в облаке, для передачи платежных реквизитов покупателя от серверов электронной коммерции к платежным процессорам, таким как PayPal и Amazon, для пересылки локальных данных в облачное хранилище, сохранения переписки в мессенджерах и аутентификации серверов в мобильных приложениях iOS и Android.

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

qz-mflldhumqjvdsr5kmhxhwh_e.jpeg

В теории, защищённое SSL/TLS-протоколом соединение должно обеспечивать конфиденциальность, достоверность и целостность коммуникаций клиентского и серверного софта, — даже в условиях присутствия активного продвинутого злоумышленника из сети: когда сеть полностью захвачена врагом, DNS отравлен, а точки доступа и маршрутизаторы, коммутаторы и WiFi контролируются злоумышленником; злоумышленником, который помимо всего прочего контролирует SSL/TLS-бэкэнд. Кроме того, когда клиентский софт пытается подключиться к законному серверу, — злоумышленник может подменить сетевой адрес сервера (например, через отравление DNS), и вместо законного сервера, перенаправить клиента на свой злонамеренный сервер.

Безопасность коммуникаций в таких суровых условиях, как известно, целиком зависит от адекватности проверки криптографического сертификата, предоставленного сервером при установке соединения. В том числе от адекватности реализации набора шифров (ciphersuite), которыми клиент и сервер пользуются при обмене данными. Для того чтобы SSL/TLS-соединение было полностью безопасным, клиентский софт, в числе прочего, должен тщательно удостовериться, что:


  • сертификат выдан действующим органом сертификации;
  • срок его действия не истёк (или сертификат не был отозван);
  • в списке перечисленных в сертификате имён присутствует тот домен, к которому производится подключение.

Однако во многих приложениях и библиотеках, для которых безопасность коммуникаций очень критична, процедура проверки SSL/TLS-сертификата, — и даже EV-SSL, сертификата с расширенной проверкой [4], — полностью провальная. Во всех популярных операционных системах: Linux, Windows, Android и iOS. Среди уязвимого софта, библиотек и middleware-сервисов можно выделить следующие [1]:


  • Amazon«овская Java-библиотека EC2 и все облачные фронтэнд-клиенты построенные на её основе.
  • Amazon«овский и PayPal«овский торговый SDK, ответственный за доставку платёжных реквизитов от сайтов (на которых развёрнута инфраструктура онлайн-коммерции) к платёжным шлюзам.
  • Интегрированные «корзины», такие как osCommerce, ZenCart, Ubercart и PrestaShop, которые не проверяют сертификаты вообще.
  • AdMob-код используемый мобильным софтом для показа контекстной рекламы.
  • Интерфейсные фронтэнд-компоненты ElephantDrive и FilesAnywhere, ответственные за взаимодействие с облачным хранилищем.
  • Android«ная библиотека Pusher и весь софт, который использует Pusher API для управления обменом мгновенными сообщениями (например, GitHub«овский Gaug.es).
  • Apache HttpClient (версия 3.x); Apache Libcloud; и все клиентские подключения к серверам Apache ActiveMQ и т.п.
  • SOAP middleware-сервисы Java, в том числе Apache Axis, Axis 2, Codehaus XFire;, а также весь софт, который на базе этих middleware-сервисов построен.
  • API-инструменты Elastic Load Balancing.
  • Weberknecht-реализация WebSockets«ов.
  • А также весь мобильный софт, построенный на базе перечисленных выше библиотек и middleware-сервисов (чтобы понять, что такое middleware-сервисы, смотри рис. 1); в том числе iOS-клиент хостинг-провайдера Rackspace.

h69qu6qopmj-_h8pcexpzcuzth0.pngРисунок 1. Что такое middleware-сервисы

Кроме того, в [2] перечислено ещё больше сотни уязвимых мобильных приложений (см. рис. 2). В том числе: Android’s Google Cloud Messaging, Angie’s List Business Center Passwords, AT&T Global Network Client, CapitalOne Spark Pay, Cisco OnPlus (remote access), Cisco Technical Support, Cisco Webex, Cisco WebEx Passwords, Dominos Pizza, E-Trade, Freelancer, Google Earth, Huntington Mobile (Bank), Intuit Tax Online Accountant, iTunes Connect, Microsoft Skype, Oracle Now, Pinterest, SafeNet (VPN client), SouthWest Airlines, Uber, US Bank — Access Online, WesternUnion, WordPress, Yahoo! Finance, Yahoo! Mail.

u4qzrdgik4ygb_j1jalyckamwmo.pngРисунок 2. Небольшая выборка из списка уязвимых мобильных приложений

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

Поставщики мобильного софта, которые берут за основу сэмпл-код AdMob для связи своих приложений с AdMob-аккаунтом, тоже уязвимы, — они позволяют атакующему захватывать учётные данные, и получать доступ ко всем его Google-сервисам. К примеру, из-за некорректной проверки сертификатов в таких мессенджерах как Trillian и AIM, MiTM-злоумышленник может похитить учётные данные для входа ко всем сервисам Google (включая Gmail), Yahoo!; и также к сервисам Windows Live (в т.ч. SkyDrive). Среди других уязвимостей, которыми страдает современный небраузерный веб-софт: использование неправильных регулярных выражений при сравнении имени хоста; игнорирование результатов проверки корректности сертификата; случайное или преднамеренное отключение проверки. [1]

Ну и конечно же нельзя забывать о том, что даже если в реализации SSL/TLS-протокола нет логических ошибок (если конечно кто-то в это ещё верит), то защиту можно обойти посредством похищения приватного ключа [12], посредством применения 0day-эксплойтов к таким вещам как клавиатуры, браузеры, операционные системы, утилиты и прошивки [3]; посредством компрометации BGP-маршрутизации [10]; или атаковать SSL/TLS по аппаратным (см. рис. 3) [8] и/или программным [9] обходным каналам.

iaftcxtvwltpvjrjsrl1kveoeoe.pngРисунок 3. Атака на SSL по аппаратным обходным каналам

Кроме того, злоумышленники могут выполнять практически невидимые MiTM-атаки, злоупотребляя механизмом кэширования SSL/TLS-сеансов, реализованным в классе SSLSessionCache. Этот механизм проверяет достоверность сертификатов только при первоначальном соединении; и при этом не способен должным образом аннулировать сеанс связи после удаления сертификатов с устройства. Кроме того, после перезагрузки Android-устройства (через опции «Перезапуск» или «Отключить питание») можно продолжать видеть зашифрованный трафик некоторых приложений, которые после перезагрузки не запускались, но до перезагрузки работали. Так например с Google Maps происходит. В [2] описано, как благодаря этим недочётам кэширования, злоумышленник может совершенно прозрачно для пользователя устанавливать и удалять «невидимые сертификаты», и затем устанавливать сетевое соединение с любым приложением.

ugjcnltgragwjfsa3uqtswrwkoe.pngРисунок 4. Ретроспектива уязвимого шифрования

Среди других распространённых уязвимостей реализации SSL/TLS-протокола можно отметить уязвимое шифрование (см. рис. 4) [5], повторное использования GCM (Galois/Counter Mode; счётчик с аутентификацией Галуа) [6], хитрость с CNG (CryptoAPI-NG) в Schannel (см. рис. 5) [7], некорректную проверку цепочки доверия [2], некорректную проверка имени хоста [11].

erybsnnakygfotqkha9beavus-g.pngРисунок 5. Хитрость с CNG: вытягиваем секреты из Schannel

Некорректная проверка цепочки доверия представляет собой ситуацию, когда веб-приложение принимает абсолютно любой сертификат, в котором указано корректное имя хоста, не проверяя при этом каким центром сертификации он был подписан. Это позволяет перехватывать и дешифровывать пароли и/или номера кредитных карт. А в некоторых случаях даже делать инъекцию вредоносного кода. В Android-софт данная уязвимость проникает, например когда создаётся кастомизированный X509TrustManger-интерфейс, который игнорирует исключения CertificateException. Или когда разработчик софта вставляет в код WebViews-компонента вызов метода SslErrorHandler.proceed (). [2]

Некорректная проверка имени хоста представляет собой ситуацию, когда веб-приложение принимает сертификат, не удостоверившись в том, что хост, с которого этот сертификат пришёл, присутствует в списке доверенных хостов. В Android-софт данная уязвимость проникает, например когда создаётся HostnameVerifier-интерфейс, который при любых условиях возвращает TRUE. Или когда разработчик софта в вставляет в код WebViews-компонента вызов метода SslErrorHandler.proceed (). [2]

Коренная причина существования подавляющего большинства перечисленных уязвимостей — ужасный API-дизайн SSL/TLS-библиотек (в том числе JSSE, OpenSSL, и GnuTLS). А также не менее ужасный дизайн библиотек передачи данных (таких как cURL, Apache HttpClient и urllib), каждая из которых представляет собой высокоуровневую обёртку для SSL/TLS-библиотек. Не говоря уже о middleware-сервисах (таких как Apache Axis, Axis 2, или Codehaus XFire), которые ещё более высокоуровневой обёрткой являются, и которые увеличивают «снежный ком» ужасного дизайна ещё больше. Вместо того чтобы вести с прикладным разработчиком (зачастую далёким от системного программирования) диалог на понятном ему языке (в терминах конфиденциальности и аутентификации), абстрагировано от низкоуровневых подробностей реализации SSL/TLS-протокола, эти API вываливают на бедолагу кучу низкоуровневых SSL/TLS-параметров, непонятных ему. Требуют от высокоуровневого софта, чтобы он правильно выставлял низкоуровневые опции; реализовывал функции проверки имени хоста и заботился об интерпретации возвращаемых низкоуровневыми операциями значений.

В результате, прикладные разработчики используют SSL/TLS API неправильно: ошибочно интерпретируют многообразие их параметров, опций, побочных эффектов и возвращаемых значений. Например [1]:


  • Amazon«овская PHP-библиотека Flexible Payments Service пытается включить проверку имени хоста — посредством установки параметра CURLOPT_SSL_VERIFYHOST в значение TRUE (в cURL-библиотеке). Однако корректное значение по умолчанию для этого параметра — 2; если же присвоить ему значение TRUE, то этому параметру незаметно для разработчика присваивается значение 1, и т.о. проверка сертификата отключается.
  • PHP-библиотека PayPal Payments Standard — приобрела ту же самую ошибку; причём в тот момент, когда предыдущая, уязвимая, реализация обновлялась (т.е. одну ошибку убрали, другую добавили).
  • Другой пример — это Lynx, тексто-ориентированный браузер. Он проверяет самоподписанные сертификаты, –, но только в том случае, если GnuTLS«ная функция проверки сертификата возвращает отрицательное значение. Однако эта самая функция для некоторых ошибок возвращает 0; в том числе в тех случаях, когда сертификаты подписаны недоверенным органом. Из-за этого цепочка проверки доверия в Lynx — нарушена.

Кроме того, прикладные разработчики зачастую неправильно понимают, какие именно гарантии безопасности предоставляет та или иная SSL/TLS-библиотека. Поэтому в дикой природе можно встретить клинические случаи, когда в приложениях, принципиально нуждающихся в защищённых коммуникациях (например, взаимодействующих с платёжным процессором), используется SSL/TLS-библиотека, которая не проверяет SSL/TLS-сертификаты вообще. Более прозаичные, но ещё более убийственные случаи — это когда разработчик какого-нибудь из промежуточных слоёв софта молча отключает процедуру проверки SSL/TLS-сертификатов (он это может сделать, например, для тестирования системы, а после тестирования — забыть вновь включить её). При этом высокоуровневый программный код, использующий этот промежуточный слой, уверен, что проверка сертификатов производится. Т.о. ошибки SSL/TLS часто бывают скрыты в глубине одного или сразу нескольких промежуточных слоёв-библиотек — из-за чего обнаружить данную проблему становится практически невозможно.

Например, в JSSE (Java Secure Socket Extension) расширенный интерфейс SSLSocketFactory API — молча пропускает проверку имени хоста, если поле «algorithm» в SSL-клиенте установлено в NULL или в пустую строку, –, а не в HTTPS. Хотя данное обстоятельство упоминается в справочном руководстве JSSE, многие Java-реализации SSL-протоколов используют SSLSocketFactory без выполнения проверки имени хоста…

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

qczmpr2oacz3cprgolpbb4ryhxm.pngРисунок 6. Классификация актуальных для SSL/TLS уязвимостей

Ну и чтобы добавить ложку мёда в бочку дёгтя, стоит отметить, что в [1] подробно/понятно/популярно/грамотно описано, как SSL реализовываться должен, со ссылкой на RFC. Лучшего описания, которое бы технически точным и одновременно понятным было, мы не встречали. Также в [1] разбираются самые распространённые SSL-библиотеки, с классификацией по уровню абстрагирования (низкоуровневые/высокоуровневые). Всё с диаграммами и лаконичными алгоритмами в псевдокоде. Подробно уязвимости конкретных продуктов описаны, с приведением программного кода некорректного, и указанием ошибок. Так что если вдруг у кого-то в очередной раз возникнет желание создать такую реализацию SSL/TLS-фреймворка, которая станет исключением из поговорки «хотели как лучше, а получилось как всегда», то [1] — идеальное для этого начало.


Библиография

1. Martin Georgiev, Rishita Anubhai, Subodh Iyengar. The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software // Proceedings of the 2012 ACM conference on computer and communications security. 2012. pp. 38–49.
2. Tony Trummer. Mobile SSL Failures // Proceedings of the HITB Security Conference. 2015.
3. Kellen Evan Person. How Ciphersuites Work: TLS in Pieces // 2017.
4. Catalin Cimpanu. Extended Validation (EV) Certificates Abused to Create Insanely Believable Phishing Sites // BleepingComputer. 2017.
5. David Adrian. A Retrospective on the Use of Export Cryptography // Black Hat. 2016.
6. Sean Devlin. Nonce-Disrespecting Adversaries: Practical Forgery Attacks on GCM in TLS // Black Hat. 2016.
7. Jake Kambic. Cunning with CNG: Soliciting Secrets from Schannel // Black Hat. 2016.
8. Valeria Bertacco. Torturing OpenSSL // Black Hat. 2012.
9. Tom van Goethem. HEIST: HTTP Encrypted Information Can Be Stolen Through TCP-Windows // Black Hat. 2016.
10. Artyom Gavrichenkov. Breaking Https With BGP Hijacking // Black Hat. 2016.
11. Chris Stone, Tom Chothia. Spinner: Semi-Automatic Detection of Pinning without Hostname Verification // Proceedings of the Annual Computer Security Applications Conference (ACSAC) 2017.
12. Marco Ortisi. Recover a RSA Private Key from a TLS Session with Perfect Forward Secrecy // Black Hat. 2016.

PS. Первоначально статья была опубликована на «Хакере».

© Habrahabr.ru