July 22, 2021

Как работал эксплойт Kaseya VSA Zero Day

В этой статье описывается эксплойт для удаленного выполнения кода с предварительной авторизацией против Kaseya VSA Server, который использовался во время массовой атаки вымогателя Revil 2 июля 2021 года . 5 июля, после первоначального расследования затронутых организаций, Truesec связался с Kaseya и предоставил подробное техническое описание этих уязвимостей вместе с судебно-медицинскими доказательствами эксплуатации. Kaseya выпустила исправление 9.5.7a (9.5.7.2994), устраняющее проблемы безопасности 11 июля.

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

Обзор

Эксплойт использовал четыре уязвимости в приложении Kaseya, которые были связаны, как показано на рисунке ниже.

  1. Получен сеанс с аутентификацией путем злоупотребления ошибкой в логике аутентификации [ CWE-304 ] в /dl.asp.
  2. Загрузил программу-вымогатель revil (agent.crt) через уязвимость неограниченной загрузки [ CWE-434 ], а также обошел защиту от подделки запросов [ CWE-352 ] в /cgi-bin/KUpload.dll.
  3. Загрузили полезную нагрузку ASP (screenshot.jpg) таким же образом, как описано в 2.
  4. Вызвал полезную нагрузку в screenshot.jpg через уязвимость локального внедрения кода [ CWE-94 ] в userFilterTableRpt.asp.
  5. Созданы процедуры Kaseya для копирования файла и запуска программы-вымогателя.
  6. Выполнил процедуры.
  7. Удалены журналы и другие доказательства судебной экспертизы.

В этой статье основное внимание будет уделено эксплойту и, следовательно, подробно описаны шаги с 1 по 4. Полезные данные не рассматриваются в этой статье.

Шаг 1. Обход аутентификации [CWE-304]

Злоумышленник сначала отправил POST-запрос на ресурс /dl.asp с данными POST userAgentGuid = guid .

Первый запрос эксплойта: обход аутентификации

В dl.asp userAgentGuid используется в запросе SELECT для поиска строки базы данных агента. AgentGuid должен существовать из-за последующего оператора if . Злоумышленник использовал agentGuid агента на самом сервере VSA (подробнее об этом ниже).

После поиска dl.asp пытается проверить, соответствует ли предоставленный пароль значениям, хранящимся в базе данных для этого агента. Затем предоставленный пароль сравнивается несколькими способами. Процесс входа в систему показан в псевдокоде ниже:

if password == hash(row[nextAgentPassword] + row[agentGuidStr])

login ok

elseif password == hash(row[curAgentPassword] + row[agentGuidStr])

login ok

elseif password == hash(row[nextAgentPassword] + row[displayName])

login ok

elseif password == hash(row[curAgentPassword] + row[displayName])

login ok

elseif password == row[password]

login failed

else

login ok

В последних двух утверждениях происходит самое интересное. В случае, если пароль равен строке [пароль], войти в систему не удастся. Однако в случае, если все проверки завершились неудачно , по умолчанию будет использоваться предложение else , которое устанавливает для «loginOK» значение true .

Поскольку в запросе не был указан пароль, переменная «пароль» будет иметь значение NULL и loginOK окажется истинным . Если для параметра loginOK установлено значение true , приложение отправляет файл cookie сеанса входа в систему и в конечном итоге (если не указаны другие параметры, как в запросе злоумышленника) попадет в предложение if , которое возвращает 302 редирект на userPortal.

Ответ на запрос обхода аутентификации

Как актер получил AgentGuid?

Остается нерешенным вопрос, как злоумышленник получил около 60 (предполагаемое количество жертв VSA) уникальных действительных агентских гидов. Похоже, они просто знали агента Гидов до начала атаки.

Truesec обнаружил несколько методов, с помощью которых атака могла быть проведена без предварительного знания действующего agentGuid. Примером, который также был исправлен в 9.5.7a, является то, что параметр userAgentGuid мог быть <vsa_server_hostname> .root.kserver вместо фактического agentGuid. Из-за того, что было описано как устаревший код, в случае, если agentGuid не является числом, он автоматически найдет agentGuid из таблицы machNameTab.

Truesec не обнаружил и не знает каких-либо публичных свидетельств, показывающих, как именно были получены эти агент-гиды. Возможно, именно эти случайные гиды агентов могли ограничить воздействие атаки менее чем на 60 из примерно 35 000 клиентов Kaseya VSA.

Шаг 2 и 3. Загрузка файлов [CWE-434] [CWE-352]

Все запросы с этого момента использовали аутентифицированный сеанс, полученный на шаге 1.

Злоумышленник начал загрузку, отправив запрос GET в /done.asp без каких-либо параметров. При получении запроса приложение создает строку в таблице tempData, размещает папку загрузки и, наконец, возвращает так называемое значение loadKey . Для загрузки файла требуется действующий ключ загрузки.

Запрос и ответ для получения действительного loadKey

Для загрузки файлов злоумышленник отправил POST-запрос с множественными данными на ресурс /cgi-bin/KUpload.dll. Запрос содержал следующие параметры:

  • FileName (имя файла)
  • FileData (содержимое файла для загрузки)
  • LoadKey (значение, полученное GETting done.asp)
  • RedirectPath (путь, на который приложение будет перенаправлять после успешной загрузки)
  • PathData (папка, в которой будет сохранен файл)
  • __RequestValidationToken (обходной токен CSRF)

Обход защиты CSRF

__RequestValidationToken не был правильно проверен. Например, значение «xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx» было принято как допустимый токен.

Загрузка программы-вымогателя (Agent.crt)

Первой загрузкой, выполненной злоумышленником, был файл с именем agent.crt. Этот файл представлял собой закодированную версию программы-вымогателя, которая позже была отправлена всем агентам со взломанного сервера VSA.

Загрузка agent.crt.

После успешной загрузки сервер возвращает HTTP 200 OK с телом, содержащим ссылку, указывающую на / <redirectPath>? FileName = <filename> & PathData = <relative path> & originalName = <filename> & FileSize = <size> & TimeElapsed = <time>.

В этом случае, поскольку загрузка файла прошла успешно, возвращенная ссылка была /done.asp?FileName=agent.crt&PathData=WebPages\ManagedFiles\VSATicketFiles\&originalName=agent.crt&FileSize=1221630&TimeElapsed=00:00:00.828

Загрузка полезной нагрузки ASP (Screenshot.jpg)

Злоумышленник загрузил еще один файл с именем Screenshot.jpg. Это был не файл jpg, а текстовый файл, содержащий код ASP. После получения другого значения loadKey из /done.asp злоумышленник загрузил файл. Частичное содержимое запроса можно увидеть на рисунке ниже (к сожалению, был получен только частичный захват, а средняя часть screenshot.jpg отсутствовала).

Первая часть загруженного файла screenshot.jpg.
Последняя часть загруженного файла screenshot.jpg.

Ссылка в теле ответа в этом случае была /done.asp?FileName=Screenshot.jpg&PathData=WebPages\ManagedFiles\VSATicketFiles\&originalName=Screenshot.jpg&FileSize=6188&TimeElapsed=00:00:00.016, что означает, что файл был успешно загружен.

Шаг 4 – Выполнение полезной нагрузки на сервере [ CWE-94 ]

Наконец, злоумышленник отправил POST-запрос в /userFilterTableRpt.asp с аргументом pageFilterSQLFile.

Использование уязвимости внедрения кода.

Из-за ошибки в userFilterTableRpt.asp содержимое указанного файла будет интерпретироваться как код ASP, поскольку он был передан функции eval. В данном случае ManagedFiles / VSATicketFiles / Screenshot.jpg, текстовый файл ASP-кода, только что загруженный злоумышленником.

Сначала userFilterTableRpt.asp устанавливает переменную из параметра POST. Затем он считывает содержимое указанного файла и передает его eval, который по определению интерпретирует значение аргумента как код. Поток показан в псевдокоде ниже:

f = open (pageFilterSQLFile)

c = read (f)

eval (c)

Вот и все. Полезная нагрузка ASP была выполнена и начала вытеснять программу-вымогатель, и все мы знаем историю оттуда.

Заключительные слова

После того, как патч стал доступным для клиентов Kaseya VSA, и после того, как мы проверили патч, чтобы убедиться, что вектор атаки больше не присутствует, мы считаем, что пришло время поделиться этими деталями в интересах сообщества . Мы твердо верим, что эта информация поможет сообществу специалистов по безопасности в их реакции на атаку, а в более широкой перспективе она поможет отрасли понять, что произошло, чтобы мы могли решить основные проблемы и, в конечном итоге, расширить наши возможности для предотвращения будущих нарушений.

Источник