- PVSM.RU - https://www.pvsm.ru -
В отличие от некоторых предыдущих работ, данная уязвимость не требует прав администратора, не требует JIT-кода или повреждения памяти для обхода проверки подписи кода. Всё что нужно — правильно отформатированный файл Fat/Universal, и проверка подписи кода покажет валидный результат.
Подпись кода — это конструкция безопасности, которая использует инфраструктуру открытых ключей (PKI) для цифровой подписи скомпилированного кода или даже скриптов, чтобы удостоверить надёжное происхождение и гарантировать аутентичность кода. На Windows вы можете криптографически подписать почти что угодно: от бинарников .NET до скриптов PowerShell. На macOS/iOS подпись кода относится в основном к двоичным файлам Mach-O и пакетам приложений, чтобы допускать к выполнению в памяти только доверенного кода.
Антивирусы, системы безопасности и реагирования на инциденты, а также инструменты криминалистической экспертизы анализируют подписи, чтобы выявить доверенный код среди ненадёжного. Проверка подписи ускоряет анализ. Различные инструменты используют информацию о подписи кода для реализации мер безопасности: это белые списки, антивирусы, системы реагирования на инциденты и поиска угроз. Скомпрометировать подпись кода в одной из популярных ОС — значит подорвать основную конструкцию безопасности, от которой зависят многие рутинные операции в сфере ИБ.
В подписи кода уже находили проблемы (1 [1], 2 [2], 3 [3], 4 [4], 5 [5]). В отличие от некоторых предыдущих работ, данная уязвимость не требует прав администратора, не требует JIT-кода или повреждения памяти для обхода проверки подписи кода. Всё что нужно — правильно отформатированный файл Fat/Universal, и проверка подписи кода покажет валидный результат.
Суть уязвимости в неодинаковой проверке подписи кода загрузчиком Mach-O и Code Signing API, которые используются неправильно. Эту разницу можно эксплуатировать с помощью специально сформированного двоичного файла Universal/Fat.
Что такое файл Fat/Universal?
Fat/Universal — это двоичный формат, который содержит несколько файлов Mach-O (исполняемый файл, dyld или пакет), каждый из которых ориентирован на определенную архитектуру CPU (например, i386, x86_64 или PPC).
Без прохождения соответствующих SecRequirementRef [6] и SecCSFlags [7] программный интерфейс Code Signing API (SecCodeCheckValidity [8]) проверит первый бинарник в файле Fat/Universal на предмет происхождения подписи (например, Apple) и убедится в аутентичности подписи. Затем API проверит все остальные бинарники в файле Fat/Universal на соответствие Team Identifiers и аутентичность подписи, но без проверки корня доверия центра сертификации. Причина, почему вредоносный код или «неподписанный» код, должен быть i386, заключается в том, что Code Signing API по умолчанию настроен на проверку в первую очередь подписи кода для нативной архитектуры CPU (x86_64).
Одна из причин, почему самоподписанный код успешно проходит проверку — потому что даже в основных бинарниках Apple поле TeamIdentifier установлено как not set. На иллюстрации ниже показаны валидный бинарник Mach-O, подписанный Apple (python.х64), рядом с самоподписанным Mach-O (ncat.i386). У обоих указано `TeamIdentifier=not set`.

Например, я подписал бинарник с помощью ID разработчика и попытался в lipo объединить его с бинарником от Apple в один файл Fat/Universal. Такой вариант подписи кода не проходит.

Мой первоначальный PoC — это ncat (от nmap), который я назвал ncat.frankenstein. Здесь итоговый файл Fat содержит подписанный Apple двоичный файл python x86_64 и самоподписанный (adhoc) двоичный файл ncat i386. Самоподписанный бинарник легко создаётся командой codesign -s - target_mach-o_or_fat_binary. Вот как он выглядит в MachOView:

Если запустить этот файл, то запустится именно python x86_64:

А подпись кода проходит проверку:

Как я запустил самоподписанный двоичный файл ncat?
Это делается путём установки недопустимого типа CPU_Type или ненативного CPU (например, PPC). Тогда загрузчик Mach-O пропускает двоичный файл Mach-O с действительной подписью и выполнит вредоносный (не подписанный Apple) код:

Потом выполняется ncat.frankenstein, и результатом проверки будет valid:

Мы опубликовали [9] ncat.frankenstein и четыре других примера, чтобы разработчики могли проверить наличие уязвимости в своих продуктах.
В командной строке
Зависит от того, как вы проверяете подписанный код. Если используете codesign, то наверное знакомы со следующими командами:
codesign –dvvvv — дамп центра сертификации и TeamIdentifier (ID разработчика)codesign –vv — строгая проверка всех архитектурНо для правильной проверки этого типа злоупотреблений нужно добавить требование anchor-сертификата следующими командами [10]:
codesign -vv -R='anchor apple' ./some_application_or_mach-o # для кода, подписанного Applecodesign -vv -R='anchor apple generic' ./some_application_or_mach-o # для кода, подписанного Apple и разработчиком AppleТакая команда покажет ошибку при проверке кода с чужой подписью:

Можно использовать команду spctl, но она требует тщательного анализа вывода команды. Например, бинарник Mach-O с подписью Apple (/bin/ls) и Safari возвращает следующее:

А вот результат приложения, подписанного Apple:

Обратите внимание на строку “(the code is valid but does not seem to be an app)” для /bin/ls, который не проходит проверку. Для сравнения, вот результат файла Fat/Universal ncat.frankenstein:

Для файла ncat.frankenstein Fat/Universal не отображается, что код действителен. Таким образом, я не могу рекомендовать spctl для ручной проверки автономных двоичных файлов Mach-O. Просто используйте codesign с соответствующими флагами.
Для разработчиков
Как правило, разработчики проверяют бинарники Mach-O или Fat/Universal с помощью API SecStaticCodeCheckValidityWithErrors() [11] или SecStaticCodeCheckValidity() [12] со следующими флагами:
Эти флаги должны гарантировать, что весь загруженный в память код в файле Mach-O или Fat/Universal криптографически подписан. Тем не менее, эти API по умолчанию не обеспечивают должную проверку, так что сторонним разработчикам требуется вычленять каждую архитектуру в файле Fat/Universal и проверять, что identities совпадают и криптографически надёжны.
Лучший способ проверить каждую вложенную архитектуру в файле Fat/Universal — это сначала вызвать SecRequirementCreateWithString [15] с требованием “anchor apple”, затем SecStaticCodeCheckValidity [16] с флагами kSecCSDefaultFlags | kSecCSCheckNestedCode | kSecCSCheckAllArchitectures | kSecCSEnforceRevocationChecks [17] со ссылкой на требование; как показано в пропатченном исходном кодеWhatsYourSign [18].
Передавая “anchor apple”, в функцию SecRequirmentCreateWithString, такой вызов действует аналогично команде codesign -vv -R=’anchor apple’ , требуя наличия цепочки доверия Apple Software Signing для всех вложенных бинарников в файле Fat/Universal. Кроме того, передавая флаги и требование к SecStaticCodeCheckValidity, все архитектуры проверяются на это требование, и применяются проверки отзыва.
Инструмент codesign от Apple и необходимость использовать флаг -R.

LittleSnitch — проверка файла Fat/Universal на диске не проходит, но LittleSnitch корректно проверяет процесс в памяти.


LittleFlocker — F-Secure купила LittleFlocker, и теперь он называется xFence.

F-Secure xFence (бывший LittleFlocker)

Инструменты Objective-See
TaskExplorer


WhatsYourSign

Facebook OSquery — результат проверки вредоносных образцов и /bin/ls в качестве валидного примера.

Выдача Google Santa – Fileinfo показывает, что ncat.frankenstein в белом списке:

Запрет выполнения ncat (неподписанного) и разрешение выполнения ncat.frankenstein:

Журнал santa.log с демонстрацией событий из предыдущего примера:

Carbon Black Response

VirusTotal — пример bash_ppc_adhoc до установки патча в VirusTotal:

22.02.2018: в Apple отправлен отчёт и PoC для обхода сторонних систем безопасности.
01.03.2018: Apple ответила, что сторонние разработчики должны использовать kSecCSCheckAllArchitectures и kSecCSStrictValidate с SecStaticCodeCheckValidity API, и документация для разработчиков будет соответствующим образом обновлена.
06.03.2018: в Apple отправлен отчёт и PoC для обхода флагов и строгой проверки codesign.
16.03.2018: отправлена дополнительная информация в Apple.
20.03.2018: Apple заявила, что не рассматривает это как проблему безопасности, которую следует решать напрямую.
29.03.2018: Apple заявила, что документация может быть обновлена, но «[...] сторонним разработчикам следует выполнить дополнительную работу для проверки, что все identities в универсальном двоичном файле одинаковы, если они хотят представить осмысленный результат».
02.04.2018: первый контакт с CERT/CC и последующее сотрудничество для уточнения масштабов и влияния уязвимости.
09.04.2018: все известные сторонние разработчики, которых затронула уязвимость, уведомлены в координации с CERT/CC.
18.04.2018: последний контакт с CERT/CC с рекомендацией, что публичное раскрытие информации в блоге лучше всего подходит для уведомления остальных сторонних разработчиков, которые используют API подписи кода от Apple в частном порядке.
05.06.2018: окончательный контакт с разработчиками перед публикацией.
12.06.2018: раскрытие информации.
Спасибо всем сторонним разработчикам за их кропотливую работу и профессионализм в решении этого вопроса. Уязвимости подписи кода — это особенно деморализующие баги, тем более для компаний, которые пытаются обеспечить безопасность лучше, чем по умолчанию в операционной системе.
Автор: GlobalSign_admin
Источник [19]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/informatsionnaya-bezopasnost/282789
Ссылки в тексте:
[1] 1: https://specterops.io/assets/resources/SpecterOps_Subverting_Trust_in_Windows.pdf
[2] 2: https://github.com/secretsquirrel/SigThief
[3] 3: https://github.com/secretsquirrel/Shmoocon2016/blob/master/preso_shmoocon_2016.pdf
[4] 4: https://www.usenix.org/system/files/conference/usenixsecurity13/sec13-paper_wang-updated-8-23-13.pdf
[5] 5: https://github.com/kpwn/935csbypass
[6] SecRequirementRef: https://developer.apple.com/documentation/security/secrequirementref?language=objc
[7] SecCSFlags: https://developer.apple.com/documentation/security/seccsflags?language=objc
[8] SecCodeCheckValidity: https://developer.apple.com/documentation/security/1396726-seccodecheckvalidity?language=objc
[9] опубликовали: https://github.com/OktaSecurityLabs/CodeSigningSamples
[10] командами: https://developer.apple.com/library/content/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html
[11] SecStaticCodeCheckValidityWithErrors(): https://developer.apple.com/documentation/security/1395272-seccodecheckvaliditywitherrors?language=objc
[12] SecStaticCodeCheckValidity(): https://developer.apple.com/documentation/security/1395784-secstaticcodecheckvalidity?language=objc
[13] kSecCSStrictValidate: https://developer.apple.com/documentation/security/kseccsstrictvalidate
[14] KSecCSCheckAllArchitectures: https://developer.apple.com/documentation/security/kseccscheckallarchitectures
[15] SecRequirementCreateWithString: https://github.com/objective-see/WhatsYourSign/blob/29aec698696d58cb1d1d6f0cc9dbeb0340d6bd78/WhatsYourSignExt/FinderSync/Signing.m#L324
[16] SecStaticCodeCheckValidity: https://github.com/objective-see/WhatsYourSign/blob/29aec698696d58cb1d1d6f0cc9dbeb0340d6bd78/WhatsYourSignExt/FinderSync/Signing.m#L334
[17] kSecCSDefaultFlags | kSecCSCheckNestedCode | kSecCSCheckAllArchitectures | kSecCSEnforceRevocationChecks: https://github.com/objective-see/WhatsYourSign/blob/29aec698696d58cb1d1d6f0cc9dbeb0340d6bd78/WhatsYourSignExt/FinderSync/Item.m#L338
[18] WhatsYourSign: https://objective-see.com/products/whatsyoursign.html
[19] Источник: https://habr.com/post/414011/?utm_campaign=414011
Нажмите здесь для печати.