Знакомство с уязвимостью
Компания Citrix выпустила уведомление об уязвимости удаленного выполнения кода CVE-2022-27518 с оценкой CVSS 9,8 в декабре 2022 г. С тех пор прошло более двух месяцев Из-за сложности среды уязвимости не было опубликовано соответствующих аналитических статей. После периода анализа и проверки различий было обнаружено, что причина уязвимости заключалась в том, что Citrix netscaler не проверял строго поле SignatureValue при анализе SAML XML, что приводило к переполнению стека.
Версии, затронутые уязвимостью:
Создание среды уязвимости
Создание среды уязвимостей очень сложным делом (даже более трудоемким, чем анализ уязвимостей), и после изучения большого количества информации я создал среду единой регистрации SAML, используя Citrix Gateway в качестве SAML SP и Microsoft Azure в качестве SAML IDP (может потребоваться расширенная учетная запись) .Если вы используете виртуальные машины для построения служб Citrix SAML, вам нужно три виртуальные машины, в то время как более хлопотным моментом является то, что службы Citrix SAML доступны только в Platinum и Enterprise Edition подписках, поэтому вам нужен соответствующий код, активации. Который можно найти на Xianyu, благо, мастера 404 смогли взломать процесс активации.
Детали конфигурации
Настроенная топология сети выглядит следующим образом [3], с тремя виртуальными машинами в одной среде интрасети, соответствующими NSIP, MIP (SNIP) и VIP, где NSIP - это собственный IP-адрес устройства Citrix ADC/Gateway, используемый для управления, общего доступа к самому NetScaler и межустройственного взаимодействия в конфигурациях высокой доступности.
MIP - это сопоставленный IP, который является адресом источника в пакетах запросов, отправляемых устройством на реальные серверы.
VIP — это IP-адрес виртуального сервера, к которому клиенты могут напрямую обращаться, а реальный ответ направляется на множество реальных серверов на задней панели.
Устройство, которое управляет несколькими потоками трафика, может быть настроено с несколькими виртуальными IP-адресами.
Сервер управления доменом также необходим для выдачи сертификатов серверам Citrix. (Теоретически самозаверяющий сертификат также возможен. Я напрямую создал подстановочный сертификат DNS. Вы можете обратиться к разделу Create a Wildcard Certificate using MMC in Windows Server 2019 - YouTube)
Список конфигурации в моей среде выглядит следующим образом:
Поскольку доступ к службе SAML должен осуществляться с использованием доменного имени, в локальный файл hosts также необходимо добавить новую запись разрешения DNS
Метод доступа
Когда мы посещаем сайт https://gateway.nstest.local, браузер автоматически переходит к интерфейсу аутентификации Microsoft.
После ввода имени пользователя и пароля он будет перенаправлен на интерфейс управления шлюзом, и здесь он будет успешно установлен.
Метод тестирования
Для тестирования на проникновение рекомендуется использовать плагин SAMLRaider: SAML2 Burp Extension от BurpSuite [4], который может легко кодировать декодировать и изменять пакеты запроса аутентификации и пакеты ответа аутентификации. Мы можем установить параметры фильтрации только для перехвата пакетов SAMLResponse в процессе аутентификации SAML, которые представляют собой пакеты ответа аутентификации, отправленные в службу входа после аутентификации IDP. Пакет ответа аутентификации, отправленный браузером в службу входа, содержит ключевую информацию об аутентификации.
Как показано ниже, этот плагин позволяет легко изменять информацию об утверждениях SAML, а также позволяет осуществлять распространенные атаки SAML. (Я протестировал все эти атаки в среде Citrix, и все они были отфильтрованы Citrix)
Поиск уязвимых программ
Когда уведомление об уязвимости было впервые выпущено, официальный сайт Citrix удалил ссылку для скачивания предыдущей версии версии, затронутой уязвимостью, что вызвало некоторые трудности при анализе различий уязвимостей.Недавно официальный сайт Citrix опубликовал версия 12.1-64.17, которая ближе к версии, затронутой уязвимостью, поэтому проанализируйте ее еще раз с уровня diff.
Загрузите образы виртуальных машин, соответствующие Citrix-Gateway-KVM-12.1-64.17 (уязвимая версия) и Citrix-Gateway-KVM-12.1-65.25 (исправленная версия), и попробуйте извлечь файлы путем монтирования после запуска.Из-за разных файловых систем, этот способ более сложный. К счастью, Gateway поддерживает ssh-соединение, и соответствующие файлы можно извлечь через ssh.
Когда уведомление об уязвимости было впервые выпущено, официальный сайт Citrix удалил ссылку для скачивания предыдущей версии версии, затронутой уязвимостью, что вызвало некоторые трудности при анализе различий уязвимостей.Недавно официальный сайт Citrix опубликовал версия 12.1-64.17, которая ближе к версии, затронутой уязвимостью, поэтому проанализируйте ее еще раз с уровня diff. Загрузите образы виртуальных машин, соответствующие Citrix-Gateway-KVM-12.1-64.17 (уязвимая версия) и Citrix-Gateway-KVM-12.1-65.25 (исправленная версия), и попробуйте извлечь файлы путем монтирования после запуска.Из-за разных файловых систем, этот способ более сложный. К счастью, Gateway поддерживает ssh-соединение, и соответствующие файлы можно извлечь через ssh.
Анализ уязвимостей
Обход сторожевого процесса pitboss
Citrix Gateway VM поставляется с инструментом gdb, версия которого немного низка и не имеет многих команд, но он работает просто отлично. Когда я попытался присоединить процесс nsppe с помощью gdb, я обнаружил, что после присоединения процесса он автоматически перезапускается, так что, похоже, существует антиотладка.
Проверив системные журналы dmesg, я узнал, что существует процесс pitboss, который получает пакеты heartbeat от процесса nsppe, и если потеря пакетов heartbeat превышает определенный порог, процесс pitboss подает сигнал процессу nsppe завершить процесс и перезапустить его. Когда gdb подключается к процессу nsppe, процесс nsppe будет виснуть, а процесс pitboss перезапустит процесс nsppe, если он не сможет получить пакет heartbeat, что делает невозможным правильную отладку процесса nsppe.
Предположительно в системе должны быть встроенные инструменты для изменения этих политик. Осмотревшись, я обнаружил, что программа pb_policy в каталоге netscaler может устанавливать эти политики, а команда для игнорирования зависаний процесса выглядит следующим образом.
После выполнения команды можно радостно отлаживать процесс nsppe.Я не знаком с механизмом взаимодействия ядра freebsd, поэтому подробно разбирать этот механизм watchdog не буду, у меня будет время изучить, как его реализовать позже.
diff-анализ
Программы nsppe из Gateway-12.1-64.17 и Gateway-12.1-65.25 были импортированы в IDA для анализа с помощью плагина bindiff, который является большой программой и занимает много времени для анализа. После завершения сравнения они сортируются по сходству.Видно, что в новой версии изменены некоторые функции, связанные с SAML.Также в этой версии исправлена более ранняя уязвимость обхода аутентификации CVE-2022-27510.
Анализируйте различия в коде одно за другим, уделяя особое внимание функциям, измененным граничными условиями. После быстрого анализа я обнаружил, что функция ns_aaa_saml_entity_encode_decode является более подозрительной. Эта функция была переименована в ns_aaa_entity_encode_decode в новой версии, и различия между двумя диаграммами потока управления следующие, и очевидно, что в новой версии есть дополнительный путь условного суждения.
Конкретно упрощенный дизассемблированный код этой функции в старой версии 12.1-64.17:
Новая версия 12.1-65.25 дизассемблированный код:
Можно обнаружить, что новая версия функции ns_aaa_entity_encode_decode имеет дополнительный параметр a4.Только когда переменная v15 меньше, чем значение переданного параметра a4, может быть выполнена следующая функция копирования памяти ns_bcopy_, и структура, возвращаемая функция astr_canonicalize должна быть смещена к памяти, на которую указывает параметр 0x8.Для памяти, на которую указывает параметр a2, длина копии равна элементу со смещением 0x10 структуры, возвращаемой вышеупомянутой функцией astr_canonicalize. При сравнении двух версий функции astr_canonicalize ниже не обнаружено существенной разницы. Поэтому, продолжая анализ верхней функции, посмотрим на перекрестные ссылки на функцию ns_aa_entity_encode_decode, там есть ряд мест, где эта функция вызывается.
Давайте попробуем поставить точку останова в этой функции ns_aa_entity_encode_decode, посетив https://gateway.nstest.local, и посмотрим, сможем ли мы ее сломать.
Он был успешно разобран, из стека вызовов видно, что это процесс обработки ответа SAML.Отсюда в принципе можно определить, что это и есть точка уязвимости.
Продолжая анализировать новую версию функции верхнего уровня ns_aaa_saml_verify_signature, мы видим, что четвертый передаваемый параметр (т.е. параметр, используемый для сравнения длины) равен 0x800, а второй параметр v78 (т.е. параметр места назначения копии памяти) является стековой переменной с пространством стека размером ровно 0x800.
В старой версии, напротив, стековая переменная v78 передавалась напрямую, и к этому моменту переполнение стека уже было вызвано.
Путем обратного анализа мы узнаем, что функция проверяет подпись SAMLResponse, мы ставим точку останова в месте вызова ns_bcopy_, чтобы посмотреть, какие данные копируются из исходной памяти.
Скопированные исходные данные - это строка, и мы переходим в burp и смотрим на пакет трафика, который оказывается данными в поле <SignatureValue>.
Поэтому естественной идеей было создать сверхдлинную строку для замены содержимого тега <SignatureValue>.
Ранее мы видели, что переменная v78 находится в 0x890 байтах от нижней части стека, поэтому в тег <SignatureValue> встройте следующее: 'A'*0x890 + 'B'*8 + 'C'*8, а затем разбейте последнюю инструкцию ret в функции ns_aa_saml_verify_signature
Успешно проверено наличие уязвимости переполнения стека.
Эксплуатация уязвимостей
Проверьте механизм защиты процесса nsppe, нет канарейки, стек исполняемый, у программы нет aslr нет необходимости сливать базовый адрес, контролируемое пространство стека большое и кажется легко эксплуатируемым.
Однако вскоре выяснилось, что не все так просто. Citrix получает ответ SAMLResponse в формате html, декодирует его в base64 и преобразует в текст xml, а согласно стандарту W3C, следующие \x00-\x08?\x0b-\x0c?\x0e-\x1f шестнадцатеричные символы не могут появляться в файлах XML, даже если они помещены в <![CDATA[]]>, не исключаются.
Другими словами, мы можем управлять только пространством стека между переменной стека и адресом возврата, а контролируемое содержимое стека не может содержать вышеуказанные символы, поэтому мы можем поместить только закодированный шеллкод. Однако старший адрес нашей программы \x00, и в стеке невозможно построить ROP-цепочку, есть только один шанс перезаписать младшие 3 байта адреса возврата.
Можно найти подходящий gadget для передачи потока управления в контролируемое стековое пространство для реализации RCE, или для контроля адреса возврата в произвольные функции для вредоносных операций.
Справочные статьи
Компания Citrix выпустила уведомление об уязвимости удаленного выполнения кода CVE-2022-27518 с оценкой CVSS 9,8 в декабре 2022 г. С тех пор прошло более двух месяцев Из-за сложности среды уязвимости не было опубликовано соответствующих аналитических статей. После периода анализа и проверки различий было обнаружено, что причина уязвимости заключалась в том, что Citrix netscaler не проверял строго поле SignatureValue при анализе SAML XML, что приводило к переполнению стека.
Версии, затронутые уязвимостью:
- Citrix ADC and Citrix Gateway 13.0 before 13.0-58.32
- Citrix ADC and Citrix Gateway 12.1 before 12.1-65.25
- Citrix ADC 12.1-FIPS before 12.1-55.291
- Citrix ADC 12.1-NDcPP before 12.1-55.291
Создание среды уязвимости
Создание среды уязвимостей очень сложным делом (даже более трудоемким, чем анализ уязвимостей), и после изучения большого количества информации я создал среду единой регистрации SAML, используя Citrix Gateway в качестве SAML SP и Microsoft Azure в качестве SAML IDP (может потребоваться расширенная учетная запись) .Если вы используете виртуальные машины для построения служб Citrix SAML, вам нужно три виртуальные машины, в то время как более хлопотным моментом является то, что службы Citrix SAML доступны только в Platinum и Enterprise Edition подписках, поэтому вам нужен соответствующий код, активации. Который можно найти на Xianyu, благо, мастера 404 смогли взломать процесс активации.
Детали конфигурации
Настроенная топология сети выглядит следующим образом [3], с тремя виртуальными машинами в одной среде интрасети, соответствующими NSIP, MIP (SNIP) и VIP, где NSIP - это собственный IP-адрес устройства Citrix ADC/Gateway, используемый для управления, общего доступа к самому NetScaler и межустройственного взаимодействия в конфигурациях высокой доступности.
MIP - это сопоставленный IP, который является адресом источника в пакетах запросов, отправляемых устройством на реальные серверы.
VIP — это IP-адрес виртуального сервера, к которому клиенты могут напрямую обращаться, а реальный ответ направляется на множество реальных серверов на задней панели.
Устройство, которое управляет несколькими потоками трафика, может быть настроено с несколькими виртуальными IP-адресами.
Сервер управления доменом также необходим для выдачи сертификатов серверам Citrix. (Теоретически самозаверяющий сертификат также возможен. Я напрямую создал подстановочный сертификат DNS. Вы можете обратиться к разделу Create a Wildcard Certificate using MMC in Windows Server 2019 - YouTube)
Список конфигурации в моей среде выглядит следующим образом:
| Доменное имя | Используется | |||
|---|---|---|---|---|---|
| Citrix Gateway13.0-52.24 | 10.0.25.171 |
| |||
| Citrix Gateway13.0-52.24 | 10.0.25.172 |
| |||
| Citrix Gateway13.0-52.24 | 10.0.25.173 | gateway.nstest.local |
| ||
| Windows Server 2019 | 10.0.25.174 | ad.nstest.local | Сервер управления доменом, используемый для выдачи сертификатов серверам Citrix. | ||
| Windows 11 | 10.x.x.x | Локальный клиентский компьютер может получить доступ к Citrix VIP |
Поскольку доступ к службе SAML должен осуществляться с использованием доменного имени, в локальный файл hosts также необходимо добавить новую запись разрешения DNS
Метод доступа
Когда мы посещаем сайт https://gateway.nstest.local, браузер автоматически переходит к интерфейсу аутентификации Microsoft.
После ввода имени пользователя и пароля он будет перенаправлен на интерфейс управления шлюзом, и здесь он будет успешно установлен.
Метод тестирования
Для тестирования на проникновение рекомендуется использовать плагин SAMLRaider: SAML2 Burp Extension от BurpSuite [4], который может легко кодировать декодировать и изменять пакеты запроса аутентификации и пакеты ответа аутентификации. Мы можем установить параметры фильтрации только для перехвата пакетов SAMLResponse в процессе аутентификации SAML, которые представляют собой пакеты ответа аутентификации, отправленные в службу входа после аутентификации IDP. Пакет ответа аутентификации, отправленный браузером в службу входа, содержит ключевую информацию об аутентификации.
Как показано ниже, этот плагин позволяет легко изменять информацию об утверждениях SAML, а также позволяет осуществлять распространенные атаки SAML. (Я протестировал все эти атаки в среде Citrix, и все они были отфильтрованы Citrix)
Поиск уязвимых программ
Когда уведомление об уязвимости было впервые выпущено, официальный сайт Citrix удалил ссылку для скачивания предыдущей версии версии, затронутой уязвимостью, что вызвало некоторые трудности при анализе различий уязвимостей.Недавно официальный сайт Citrix опубликовал версия 12.1-64.17, которая ближе к версии, затронутой уязвимостью, поэтому проанализируйте ее еще раз с уровня diff.
Загрузите образы виртуальных машин, соответствующие Citrix-Gateway-KVM-12.1-64.17 (уязвимая версия) и Citrix-Gateway-KVM-12.1-65.25 (исправленная версия), и попробуйте извлечь файлы путем монтирования после запуска.Из-за разных файловых систем, этот способ более сложный. К счастью, Gateway поддерживает ssh-соединение, и соответствующие файлы можно извлечь через ssh.
Когда уведомление об уязвимости было впервые выпущено, официальный сайт Citrix удалил ссылку для скачивания предыдущей версии версии, затронутой уязвимостью, что вызвало некоторые трудности при анализе различий уязвимостей.Недавно официальный сайт Citrix опубликовал версия 12.1-64.17, которая ближе к версии, затронутой уязвимостью, поэтому проанализируйте ее еще раз с уровня diff. Загрузите образы виртуальных машин, соответствующие Citrix-Gateway-KVM-12.1-64.17 (уязвимая версия) и Citrix-Gateway-KVM-12.1-65.25 (исправленная версия), и попробуйте извлечь файлы путем монтирования после запуска.Из-за разных файловых систем, этот способ более сложный. К счастью, Gateway поддерживает ssh-соединение, и соответствующие файлы можно извлечь через ssh.
Анализ уязвимостей
Обход сторожевого процесса pitboss
Citrix Gateway VM поставляется с инструментом gdb, версия которого немного низка и не имеет многих команд, но он работает просто отлично. Когда я попытался присоединить процесс nsppe с помощью gdb, я обнаружил, что после присоединения процесса он автоматически перезапускается, так что, похоже, существует антиотладка.
Проверив системные журналы dmesg, я узнал, что существует процесс pitboss, который получает пакеты heartbeat от процесса nsppe, и если потеря пакетов heartbeat превышает определенный порог, процесс pitboss подает сигнал процессу nsppe завершить процесс и перезапустить его. Когда gdb подключается к процессу nsppe, процесс nsppe будет виснуть, а процесс pitboss перезапустит процесс nsppe, если он не сможет получить пакет heartbeat, что делает невозможным правильную отладку процесса nsppe.
Предположительно в системе должны быть встроенные инструменты для изменения этих политик. Осмотревшись, я обнаружил, что программа pb_policy в каталоге netscaler может устанавливать эти политики, а команда для игнорирования зависаний процесса выглядит следующим образом.
Код:
root@ns# /netscaler/pb_policy -h nothing
Current pitboss policy is 0x29b4 (10676):
PB_ABRT_CULPRIT | PB_RESTART_CULPRIT | PB_RESTART_SYSTEM | PB_KILL_USER_PROCS | PB_WAIT_CORES | PB_REBOOT_ON_SLOW_WARMSTART | PB_REBOOT_ON_INCOMPLETE_REG
Hung processes will be sent a SIGABRT (PB_ABRT_CULPRIT).
Monitored processes which exit will be restarted up to 5 times, except for
packet engines (PB_RESTART_CULPRIT).
If pitboss decides not to restart some failing process(es) all non-failing
processes will be sent a SIGKILL (PB_KILL_USER_PROCS).
Pitboss will then wait for all core dumps to complete (PB_WAIT_CORES) and then
do a warm restart (if a packet engine failed) and otherwise reboot the system (PB_RESTART_SYSTEM).
If startup failure is detected do nothing.
If warmstart takes too long pitboss will reboot the system (PB_REBOOT_ON_SLOW_WARMSTART).
On incomplete registration of mandatory processes after warmstart pitboss will
reboot the system (PB_REBOOT_ON_INCOMPLETE_REG).
Log messages from pitboss will take the default path.
New pitboss policy is 0x29b0 (10672):
PB_RESTART_CULPRIT | PB_RESTART_SYSTEM | PB_KILL_USER_PROCS | PB_WAIT_CORES | PB_REBOOT_ON_SLOW_WARMSTART | PB_REBOOT_ON_INCOMPLETE_REG
Hung processes will be ignored.
Monitored processes which exit will be restarted up to 5 times, except for
packet engines (PB_RESTART_CULPRIT).
If pitboss decides not to restart some failing process(es) all non-failing
processes will be sent a SIGKILL (PB_KILL_USER_PROCS).
Pitboss will then wait for all core dumps to complete (PB_WAIT_CORES) and then
do a warm restart (if a packet engine failed) and otherwise reboot the system (PB_RESTART_SYSTEM).
If startup failure is detected do nothing.
If warmstart takes too long pitboss will reboot the system (PB_REBOOT_ON_SLOW_WARMSTART).
On incomplete registration of mandatory processes after warmstart pitboss will
reboot the system (PB_REBOOT_ON_INCOMPLETE_REG).
Log messages from pitboss will take the default path.
После выполнения команды можно радостно отлаживать процесс nsppe.Я не знаком с механизмом взаимодействия ядра freebsd, поэтому подробно разбирать этот механизм watchdog не буду, у меня будет время изучить, как его реализовать позже.
diff-анализ
Программы nsppe из Gateway-12.1-64.17 и Gateway-12.1-65.25 были импортированы в IDA для анализа с помощью плагина bindiff, который является большой программой и занимает много времени для анализа. После завершения сравнения они сортируются по сходству.Видно, что в новой версии изменены некоторые функции, связанные с SAML.Также в этой версии исправлена более ранняя уязвимость обхода аутентификации CVE-2022-27510.
Анализируйте различия в коде одно за другим, уделяя особое внимание функциям, измененным граничными условиями. После быстрого анализа я обнаружил, что функция ns_aaa_saml_entity_encode_decode является более подозрительной. Эта функция была переименована в ns_aaa_entity_encode_decode в новой версии, и различия между двумя диаграммами потока управления следующие, и очевидно, что в новой версии есть дополнительный путь условного суждения.
Конкретно упрощенный дизассемблированный код этой функции в старой версии 12.1-64.17:
Код:
__int64 __fastcall ns_aaa_saml_entity_encode_decode(__int64 a1, __int64 a2, int a3, __int64 a4)
{
__int64 v5; // rax
__int64 v6; // rbx
__int64 v7; // rbx
int v8; // r9d
int v9; // r9d
unsigned __int16 v10; // ax
unsigned int v11; // eax
unsigned int v12; // r12d
__int64 v14; // [rsp+18h] [rbp-58h] BYREF
__int64 v15[2]; // [rsp+20h] [rbp-50h] BYREF
int v16; // [rsp+30h] [rbp-40h]
int v17; // [rsp+34h] [rbp-3Ch]
int v18; // [rsp+38h] [rbp-38h]
int v19; // [rsp+3Ch] [rbp-34h]
int v20; // [rsp+40h] [rbp-30h]
v15[0] = 0LL;
v15[1] = a1;
v16 = a3;
v17 = a3;
v18 = 4;
v19 = 22;
LOBYTE(v20) = v20 & 0xE0;
v20 = (32 * ASTR_NOT_REF_COUNTED) | v20 & 0x1F;
v5 = astr_canonicalize(*(_QWORD *)(*((_QWORD *)cur_as_partition + 2) + 8LL), 5LL, v15, a4, 0LL, 0LL);
v6 = v5;
if ( v5 )
{
ns_bcopy_(*(_QWORD *)(v5 + 8), a2, *(unsigned int *)(v5 + 16));
v12 = *(_DWORD *)(v6 + 16);
astr_destroy(*(_QWORD *)(*((_QWORD *)cur_as_partition + 2) + 8LL), 5LL, v6);
}
else
{
......// 日志记录
return 0;
}
return v12;
}
Новая версия 12.1-65.25 дизассемблированный код:
Код:
__int64 __fastcall ns_aaa_entity_encode_decode(__int64 a1, __int64 a2, int a3, unsigned int a4, unsigned int a5)
{
__int64 v7; // rax
__int64 v8; // r12
__int64 v9; // rbx
int v10; // r9d
int v11; // r9d
unsigned __int16 v12; // ax
unsigned int v13; // eax
unsigned int v14; // ebx
unsigned int v15; // eax
__int64 v16; // rbx
int v17; // r8d
int v18; // r9d
int v19; // r8d
int v20; // r9d
unsigned __int16 v21; // ax
unsigned int v22; // eax
char v24; // [rsp+0h] [rbp-80h]
char v25; // [rsp+0h] [rbp-80h]
char v26; // [rsp+0h] [rbp-80h]
char v27; // [rsp+0h] [rbp-80h]
__int64 v28; // [rsp+18h] [rbp-68h] BYREF
__int64 v29[2]; // [rsp+20h] [rbp-60h] BYREF
int v30; // [rsp+30h] [rbp-50h]
int v31; // [rsp+34h] [rbp-4Ch]
int v32; // [rsp+38h] [rbp-48h]
int v33; // [rsp+3Ch] [rbp-44h]
int v34; // [rsp+40h] [rbp-40h]
v29[0] = 0LL;
v29[1] = a1;
v30 = a3;
v31 = a3;
v32 = 4;
v33 = 22;
LOBYTE(v34) = v34 & 0xE0;
v34 = (32 * ASTR_NOT_REF_COUNTED) | v34 & 0x1F;
v7 = astr_canonicalize(*(_QWORD *)(*((_QWORD *)cur_as_partition + 2) + 8LL), 5LL, v29, a5, 0LL, 0LL);
v8 = v7;
if ( v7 )
{
v15 = *(_DWORD *)(v7 + 16);
if ( v15 <= a4 )
{
ns_bcopy_(*(_QWORD *)(v8 + 8), a2, v15);
v14 = *(_DWORD *)(v8 + 16);
astr_destroy(*(_QWORD *)(*((_QWORD *)cur_as_partition + 2) + 8LL), 5LL, v8);
}
else
{
...... //日志记录
astr_destroy(*(_QWORD *)(*((_QWORD *)cur_as_partition + 2) + 8LL), 5LL, v8);
return 0;
}
}
else
{
...... //日志记录
return 0;
}
return v14;
}
Можно обнаружить, что новая версия функции ns_aaa_entity_encode_decode имеет дополнительный параметр a4.Только когда переменная v15 меньше, чем значение переданного параметра a4, может быть выполнена следующая функция копирования памяти ns_bcopy_, и структура, возвращаемая функция astr_canonicalize должна быть смещена к памяти, на которую указывает параметр 0x8.Для памяти, на которую указывает параметр a2, длина копии равна элементу со смещением 0x10 структуры, возвращаемой вышеупомянутой функцией astr_canonicalize. При сравнении двух версий функции astr_canonicalize ниже не обнаружено существенной разницы. Поэтому, продолжая анализ верхней функции, посмотрим на перекрестные ссылки на функцию ns_aa_entity_encode_decode, там есть ряд мест, где эта функция вызывается.
Давайте попробуем поставить точку останова в этой функции ns_aa_entity_encode_decode, посетив https://gateway.nstest.local, и посмотрим, сможем ли мы ее сломать.
Код:
(gdb) b ns_aaa_saml_entity_encode_decode
Breakpoint 1 at 0xbebfb4
(gdb) c
Continuing.
Breakpoint 1, 0x0000000000bebfb4 in ns_aaa_saml_entity_encode_decode ()
(gdb) bt
#0 0x0000000000bebfb4 in ns_aaa_saml_entity_encode_decode ()
#1 0x0000000000bf8356 in ns_aaa_saml_verify_signature ()
#2 0x0000000000c216ca in ns_aaa_saml_process_data ()
#3 0x0000000000c25577 in ns_aaa_process_saml_req ()
#4 0x0000000000c25842 in ns_aaa_saml_auth ()
#5 0x00000000007c6a45 in ns_vpn_process_unauthenticated_request ()
#6 0x000000000080a326 in ns_aaa_cookie_valid ()
#7 0x000000000081ca31 in ns_aaa_client_handler ()
#8 0x0000000001c2e6a1 in nshttp_input ()
#9 0x0000000001c2433b in nshttp_handler ()
#10 0x00000000016e495e in ns_async_restart_http ()
#11 0x0000000000bfaf40 in ns_aaa_saml_canon_resp_handler ()
#12 0x000000000079ab48 in nsaaa_handler ()
#13 0x0000000001c6d149 in nstcp_input ()
#14 0x0000000001c59e0a in handleL4Session ()
#15 0x0000000001c5724f in dispatch_tcp ()
#16 0x00000000010cf0eb in vmpe_intf_loop_rx_proc ()
#17 0x0000000001c55472 in vc_poll ()
#18 0x00000000015b5ae3 in ns_netio ()
#19 0x00000000015baf4b in packet_engine ()
#20 0x00000000019bd9a3 in ns_enter_main ()
#21 0x00000000019c1fe9 in main ()
Он был успешно разобран, из стека вызовов видно, что это процесс обработки ответа SAML.Отсюда в принципе можно определить, что это и есть точка уязвимости.
Продолжая анализировать новую версию функции верхнего уровня ns_aaa_saml_verify_signature, мы видим, что четвертый передаваемый параметр (т.е. параметр, используемый для сравнения длины) равен 0x800, а второй параметр v78 (т.е. параметр места назначения копии памяти) является стековой переменной с пространством стека размером ровно 0x800.
В старой версии, напротив, стековая переменная v78 передавалась напрямую, и к этому моменту переполнение стека уже было вызвано.
Путем обратного анализа мы узнаем, что функция проверяет подпись SAMLResponse, мы ставим точку останова в месте вызова ns_bcopy_, чтобы посмотреть, какие данные копируются из исходной памяти.
Код:
(gdb) b *0xBEC15A
Breakpoint 1 at 0xbec15a
(gdb) c
Continuing.
Breakpoint 1, 0x0000000000bec15a in ns_aaa_saml_entity_encode_decode ()
(gdb) x/10i $rip
0xbec15a <ns_aaa_saml_entity_encode_decode+426>:
callq 0x1c5e390 <ns_bcopy_>
0xbec15f <ns_aaa_saml_entity_encode_decode+431>: mov 0x10(%rbx),%r12d
0xbec163 <ns_aaa_saml_entity_encode_decode+435>:
mov 27378486(%rip),%rax # 0x26084a0 <cur_as_partition>
0xbec16a <ns_aaa_saml_entity_encode_decode+442>: mov 0x10(%rax),%rax
0xbec16e <ns_aaa_saml_entity_encode_decode+446>: mov 0x8(%rax),%rdi
0xbec172 <ns_aaa_saml_entity_encode_decode+450>: mov %rbx,%rdx
0xbec175 <ns_aaa_saml_entity_encode_decode+453>: mov $0x5,%esi
0xbec17a <ns_aaa_saml_entity_encode_decode+458>:
callq 0x1b4b2a0 <astr_destroy>
0xbec17f <ns_aaa_saml_entity_encode_decode+463>:
jmp 0xbec187 <ns_aaa_saml_entity_encode_decode+471>
0xbec181 <ns_aaa_saml_entity_encode_decode+465>: mov $0x0,%r12d
(gdb) x/10gx $rdi
0x1115fe018: 0x5057344157596753 0x356e674e66623269
0x1115fe028: 0x7155336a5a465335 0x2f5a6c7272483653
0x1115fe038: 0x544247674f624d77 0x337a446e39775850
0x1115fe048: 0x654765743451734b 0x30756d4e5a536b4c
0x1115fe058: 0x3461474947764668 0x5a38303835356d64
(gdb) set print elements 0
(gdb) x/s $rdi
0x1115fe018: "SgYWA4WPi2bfNgn55SFZj3UqS6HrrlZ/wMbOgGBTPXw9nDz3KsQ4teGeLkSZNmu0hFvGIGa4dm55808Zuikx4s1rIbTiuyw1z5VkZGuXLl31mObPvrbowtqoBgaeTfAwImtJrw4g2kQoe35b/Z0AgSlu9/LxKRKTaG1jYk6chGNJpKTBCmEqRWKFtJsPjnB9xkAiYspO1T2AsgR9KAq9+cV93X/ZtPkfutRj4IaI3LcMnDxQ+9Pb75HYBZ9LYVqOPGowGVf/Opz40VU6xyWzRlg45ouEHTFS45xCPCe/eQe3mPjsp/kMGsM2e6611stx3Isu+GMgwDGd5hlRp4lFdQ=="
Поэтому естественной идеей было создать сверхдлинную строку для замены содержимого тега <SignatureValue>.
Ранее мы видели, что переменная v78 находится в 0x890 байтах от нижней части стека, поэтому в тег <SignatureValue> встройте следующее: 'A'*0x890 + 'B'*8 + 'C'*8, а затем разбейте последнюю инструкцию ret в функции ns_aa_saml_verify_signature
Успешно проверено наличие уязвимости переполнения стека.
Эксплуатация уязвимостей
Проверьте механизм защиты процесса nsppe, нет канарейки, стек исполняемый, у программы нет aslr нет необходимости сливать базовый адрес, контролируемое пространство стека большое и кажется легко эксплуатируемым.
Однако вскоре выяснилось, что не все так просто. Citrix получает ответ SAMLResponse в формате html, декодирует его в base64 и преобразует в текст xml, а согласно стандарту W3C, следующие \x00-\x08?\x0b-\x0c?\x0e-\x1f шестнадцатеричные символы не могут появляться в файлах XML, даже если они помещены в <![CDATA[]]>, не исключаются.
Другими словами, мы можем управлять только пространством стека между переменной стека и адресом возврата, а контролируемое содержимое стека не может содержать вышеуказанные символы, поэтому мы можем поместить только закодированный шеллкод. Однако старший адрес нашей программы \x00, и в стеке невозможно построить ROP-цепочку, есть только один шанс перезаписать младшие 3 байта адреса возврата.
Можно найти подходящий gadget для передачи потока управления в контролируемое стековое пространство для реализации RCE, или для контроля адреса возврата в произвольные функции для вредоносных операций.
Справочные статьи
Источник : https://paper.seebug.org/2049/ (hanwang@知道创宇404实验室)