Привет, Хабр!
Меня зовут Илья Ефимов, я аналитик-исследователь угроз кибербезопасности в компании R-Vision. Моя статья будет посвящена разбору уязвимости CVE-2023-38831 в архиваторе WinRAR. Эта уязвимость активно используется хакерами в атаках на отечественные компании. В отчете компании BI.ZONE фиксируется информация, что злоумышленники из групп Cobalt Werewolf, Mysterious Werewolf использовали данную уязвимость для доставки вредоносной полезной нагрузки. В этом случае уязвимость эксплуатировала вредоносный архив при доставке фишингового письма. Схожую информацию предоставляют исследователи из Positive Technologies, связав активность группировки ExCobalt с эксплуатацией CVE-2023-38831. Также фиксировались случаи эксплуатации данной уязвимости ВПО Agent Tesla и DarkMe. Стоит отметить, что по данным компании Kaspersky в 2024 году данная уязвимость занимает третье место по частоте эксплуатации атакующими в России и странах СНГ.
В своей статье я опишу, в чем заключается суть уязвимости, продемонстрирую её эксплуатацию, а также генерируемые события по активности. Затем я подробно опишу процесс детектирования уязвимости и определю основные артефакты с помощью R-Vision SIEM.
Описание уязвимости
В ОС Windows нельзя иметь два файла с одинаковым именем в одной директории. Также невозможно иметь файл и директорию с совпадающим именем (файл test.txt
и директория test.txt
). Но в архиваторах по типу WinRAR/7zip это возможно. В сжатом файле, несмотря на то, что есть файлы с одинаковым именем, они записываются в специальной структуре. Таким образом, в ZIP/RAR-файле может быть два объекта (файла/каталога) с одинаковым именем.
В этом и кроется CVE-2023-38831? Отчасти да, но есть еще один нюанс.
Итак, когда есть файл и каталог с одинаковым именем в архивном файле, и происходит открытие файла, дважды щелкнув по нему (целевому файлу), осуществляется извлечение всех файлов с тем же именем, что и целевой файл (в том числе, и файлы внутри директории с тем же именем). Все извлеченные файлы записываются во временный каталог по пути %tmp%
. Это поведение WinRAR кажется странным, так как 7Zip не ведет себя подобным образом.
Проверка бреши в системе
На практике нельзя поместить два объекта с одинаковым именем в один архивный файл в WinRAR. В данном случае был использован 7Zip, чтобы создать zip-файл.
Для этого у нас есть директория, в которой содержатся файлы text1.txt
и text2.txt
. Размер и содержимое файлов разное:
Далее используется CLI 7Zip для создания и добавления файлов в архив test.zip
:
Теперь у нас есть архив, содержащий два добавленных нами файла.
Далее переименуем файл text2.txt
в text1.txt
. Сделать это можно при помощи флага rn
у 7Zip.
В итоге у нас получаются два файла с одинаковым именем в одном архиве. Этот архив можно открыть в т.ч. через WinRAR. Также можно заметить, что несмотря на одинаковое название, один файл пустой, второй имеет содержимое:
Теперь давайте откроем файл размером 4 байта внутри архива двойным нажатием мыши и посмотрим какой файл будет открыт:
Можно заметить, что WinRAR предлагает нам заменить существующий файл. Это означает, что там уже есть файл с таким именем, размер которого 0 байт (пустой файл). В случае если согласиться на замену файла, то пустой файл будет заменен на не пустой, и мы увидим содержимое файла:
Что произошло?
WinRAR сначала создает временную папку в директории %tmp%
, а затем извлекает первый файл text1.txt
. Теперь во временной директории у нас есть первый text1
. Но после этого WinRAR также пытается извлечь второй text1.txt
. Поскольку в Windows нельзя иметь два файла с одинаковым именем в одной директории, то WinRAR предлагает выбрать действие для этого нового файла. Если вы нажмете "Да", то второй файл перезапишет первый, и вы увидите содержимое второго файла. В WinRAR проверяются все имена файлов и каталогов в архиве с целевым файлом. Если одно из них имеет имя, совпадающее с именем файла, который нужно извлечь (целевой файл), функция возвращает 1, т.е. извлекает его тоже. При этом 7-Zip просто извлекает файл, который вы хотите открыть.
Функция на рисунке выше посимвольно сравнивает имена двух файлов, чтобы определить, равны ли они или нет. У нас есть два файла с одинаковым именем, оба называются text1.txt
. Когда необходимо извлечь файл из архива, WinRAR проверяет имя целевого файла с именами всех объектов, существующих в архиве. Например, если у нас есть пять файлов в архиве, и мы хотим извлечь один из них, WinRAR проверяет имя этого файла с именами остальных четырех файлов.
Теперь, если имена этих файлов были одинаковыми, то функция проверяет еще одну вещь.
Предположим, что мы хотим извлечь fileA, и у нас есть еще один файл в архиве - fileB (имя которого совпадает с именем fileA). Также в архиве есть каталог dirA с именем, совпадающим с fileA в котором находится fileB (таким образом, имена dirA, fileA и fileB совпадают). Когда происходит нажатие на fileA, чтобы извлечь его, WinRAR проверяет, равно ли имя fileA какому-либо другому файлу или каталогу. Если имя файла совпадает с именем fileA, то оно добавляется в список извлечения. Также, если имя каталога dirA совпадает с именем fileA, то WinRAR проверяет файлы в этом каталоге с именем fileA. Если какой-либо из них совпадает, он также добавляется в список извлечения. Схема наглядно показана на рисунке:
Функция сначала проверяет имена файлов, а затем проверяет, содержит ли имя fileB символы \\
(является каталогом) или /
(является концом файла). Если имена файлов совпадают или fileB является каталогом, функция возвращает 1, то есть продолжает извлечение. Таким образом, если у нас есть файл или каталог с именем, равным имени файла, который нужно извлечь, функция возвращает 1, и затем WinRAR также извлекает эти файлы.
Эксплуатация уязвимости
У нас есть файл, который является основным файлом, с пробелом " "
в конце его имени. Также у нас есть каталог с тем же именем, что и у основного файла, и пробелом в конце его имени " "
. Внутри каталога у нас есть еще один файл с тем же именем, что и у основного файла, и пробелом в конце его имени " "
, а затем с расширением .cmd
. Этот файл содержит полезную нагрузку.
Структура архива выглядит таким образом:
text.txt (D)
--text.txt .cmd (F)
text.txt (F)
Файл CMD вызывает калькулятор:
Теперь, при открытии архивного файла text1.txt (F)
, WinRAR сравнивает все файлы в архиве, чтобы найти файлы/каталоги с таким же именем, как text1.txt (F)
.
Поправка: в процессе тестирования можно заметить разные директории %tmp%, это связано с тем, что активность фиксировалась в рамках разных тестов.
Когда WinRAR сравнивает имя файла text1.txt (F)
с именем каталога text1.txt (D)
, то выясняется, что они равны. Поэтому WinRAR продолжает проверять файлы внутри каталога и обнаруживает, что файл text1.txt. cmd (F)
совпадает с целевым файлом, поэтому он добавляет его в список для извлечения.
Пример эксплуатации выглядит следующим образом:
При этом можно увидеть как происходит создание файлов, процесс WinRAR использует CreateFile API вызов для записи файлов во временную директорию.
Теперь наш список файлов из архива для извлечения выглядит следующим образом:
Также можно обратить внимание на сгенерированные события создания извлечённых файлов в %tmp%
директории в Sysmon/Operational EventID 11(FileCreate):
Так как после открытия легитимного файла text1.txt
за счет уязвимости также происходит открытие файла командной строки text1.txt .cmd
, то в результате генерируются события Security EventID 4688(Process Creation) и Sysmon/Operational EventID 1(Process Creation):
Почему так происходит?
Для того чтобы понять, почему так происходит, обратимся к документации Microsoft:
Если файл сохраняется как
Foo.txt
, где первым символом является пустое пространство (пробел) ASCII (0x20), он будет сохранен в файловой системе какFoo.txt
(без пробела).Если файл сохраняется как
Foo.txt
, где конечные символы являются пространством ASCII (0x20), он будет сохранен в файловой системе какFoo.txt
.
Исходя из описанного выше, можно сделать вывод, что при сохранении файла все лишние пробелы в конце имени файла должны убираться. Но теперь пойдем дальше и вспомним, что было после того как мы запустили файлы из архива.
WinRAR попытается открыть файл "text1.txt "
, но WinRAR не знает как это сделать. Например, если наш целевой файл был файлом PDF, то WinRAR не знает с помощью какой программы это сделать или какое приложение используется для открытия текстовых файлов на конкретной системе Windows. В таких случаях приложения используют API Windows, такие как ShellExecuteExW.
Из документации Microsoft:
Функция ShellExecuteExW - выполняет операцию с указанным файлом.
ShellExecute
— это функция Windows API, которая используется для выполнения различных операций, связанных с манипуляциями с файлами или взаимодействием с системой. Она выполняет указанный файл или операцию с помощью ассоциированного по умолчанию действия для конкретного расширения файла или приложения.
Функция принимает на вход аргумент SHELLEXECUTEINFO
, которая обладает следующей структурой:
В данной структуре нас интересуют параметры lpVerb и lpFile. Из документации Microsoft на параметр IpVerb:
Тип: LPCTSTR
Строка, называемая глаголом, которая указывает выполняемое действие. Набор доступных команд зависит от конкретного файла или папки. Как правило, действия, доступные в контекстном меню объекта, являются доступными командами. Этот параметр может иметь значение NULL. В этом случае используется команда по умолчанию, если она доступна. В противном случае используется команда "open". Если глаголы не доступны, система использует первую команду, указанную в реестре. Если нет причин для ограничения действия определенной командой, передайте значение NULL, чтобы использовать вычисленное значение по умолчанию. Это необходимо в некоторых случаях, например при указании SEE_MASK_FLAG_NO_UI и создании пользовательского интерфейса "Открыть с помощью", если приложения не установлены.
Обычно используются следующие команды:
edit: запускает редактор и открывает документ для редактирования. Если lpFile не является файлом документа, функция завершится ошибкой.
explore: просматривает папку, указанную в lpFile.
find: инициирует поиск, начиная с указанного каталога.
open: открывает файл, указанный параметром lpFile . Файл может быть исполняемым файлом, файлом документа или папкой.
print: печатает файл документа, заданный lpFile. Если lpFile не является файлом документа, функция завершится ошибкой.
properties: отображает свойства файла или папки.
runas: запускает приложение от имени администратора. Контроль учетных записей (UAC) запрашивает у пользователя согласие на запуск приложения с повышенными привилегиями или ввод учетных данных учетной записи администратора, используемой для запуска приложения.
Описанный выше параметр очень важен. Он говорит, что если IpVerb параметр имеет значение NULL, то используется команда по умолчанию, если она доступна. В противном случае используется команда open
.
Из документации Microsoft на параметр IpFile:
Адрес строки, заканчивающейся null, которая указывает имя файла или объекта, для которого ShellExecuteEx будет выполнять действие, указанное параметром lpVerb.
То есть параметр IpFile - это путь к файлу, используемый функцией ShellExecuteExW для осуществления действия из параметра IpVerb.
При этом если обратить внимание на параметры в WinRAR, то в функции ShellExecuteExW IpVerb равен NULL, при этом в параметре lpFile, где содержится путь к открываемому файлу, будет символ пробела (0x20) "text1.txt "
, хотя ранее говорилось об обработке Windows пробелов в файлах. По сути вызов функции ShellExecuteExW с lpFile равным "text1.txt "
и является уязвимостью, приводящей к запуску файла "text1.txt .cmd"
. На рисунке показаны содержимое переменных lpFile и lpVerb, можно увидеть, что идет обращение к "text1.txt "
:
Как же происходит, что при вызове "text1.txt "
запускается "text1.txt .cmd"
? Как мы узнали ранее, из-за уязвимости в WinRAR, извлекается не только файл, который мы хотим извлечь, но и файлы, совпадающие по названию. Помимо этого, когда файлы попадают во временную директорию, механизмы Windows и WinRAR преобразуют файлы, убирая пробелы из конца их названия. Ниже приведена таблица преобразования:
Имя файла в архиве | Имя файла в |
---|---|
"text.txt " | "text.txt" |
"text.txt .cmd" | "text.txt .cmd" |
Уязвимость кроется в том, что когда мы дважды нажимаем на файлы и они передаются в %tmp%
директорию, при вызове ShellExecuteExW WinRAR передает туда неизмененные названия файлов. И, получается, что вызов идет к ShellExecuteExW("text.txt "
), но так как файл в %tmp%
был преобразован ("text.txt"
), как было описано в документации, то обращение идет к подходящему по названию файлу - "text.txt .cmd"
. В этом и кроется уязвимость.
Более наглядный пример можно увидеть ниже, где мы запускаем "text.txt .cmd"
без указания расширения .cmd:
Вывод по уязвимости
Исходя из анализа активности можно выделить две уязвимости:
Первая уязвимость:
По умолчанию, при распаковке файла из архива, WinRAR проходится по всему архиву в поисках совпадающих имен файлов/директорий. Например, если мы открываем файл
"text.txt "
, а при этом у нас есть директория"text.txt "
, в которой находится файл"text.txt .cmd"
, то WinRAR будет воспринимать файлы"text.txt "
и"text.txt .cmd"
как идентичные.После этого все файлы, которые прошли валидацию помещаются в
%tmp%
директорию, откуда будет производиться запуск.
Вторая уязвимость:
WinRAR осуществляет проверку на наличие пробелов в конце файла, преобразуя их в нулевые символы (0x00) ("text.txt "
-> "text.txt"
, "text.txt .cmd"
-> "text.txt .cmd"
).
В
%tmp%
архив передаются преобразованные файлы"text.txt"
,"text.txt .cmd"
.Уязвимость заключается в том, что после того как файлы оказываются в
%tmp%
директории при помощи API вызова ShellExecuteExW() происходит обращение к распакованному файлу"text.txt "
(на который мы дважды нажимали изначально в архиве), но проблема в том, что после преобразований в%tmp%
директории файл поменялся на"text.txt"
(без пробела), а файлом с пробелом остается"text.txt .cmd"
.В результате чего происходит обращение функции ShellExecuteExW() к вредоносному файлу
"text.txt .cmd"
Детектирование активности
В пакете экспертизы для R-Vision SIEM уже есть правило детектирующее эту активность при помощи правила «Запуск интерпретатора командной строки от WinRAR»
. Далее мы разберем его логику работы.
Часть детектирующей логики правила, где сработка происходит при создании процесса cmd.exe
от родительского процесса winrar.exe
:
filter: !vrl |
.dvendor == "Microsoft" &&
includes(["1", "4688"], .externalId)
aliases:
cmd_exec:
filter: !vrl |
flag = false
sproc = downcase(to_string(.sproc) ?? "-")
dproc = downcase(to_string(.dproc) ?? "-")
if ends_with(sproc, "\\winrar.exe") && ends_with(dproc, "\\cmd.exe"){
flag = true
}
flag
Если описанный ранее детект является более общим, то правило R-Vision SIEM Эксплуатация уязвимости в WinRAR - CVE-2023-38831
позволяет выявить именно эксплуатацию CVE-2023-38831:
Часть детектирующей логики правила, где фильтруется событие создания файла во временной директории. При этом важно, чтобы файл имел два расширения и имел пробел между этими расширениями:
filter: !vrl |
.dvendor == "Microsoft" &&
.externalId == "11"
aliases:
mal_file_create:
filter: !vrl |
flag = false
filePath = downcase(to_string(.filePath) ?? "-")
fileName = to_string(split(filePath, "\\\\")[-1])
dproc = downcase(to_string(.dproc) ?? "-")
if ends_with(dproc, "\\winrar.exe") &&
contains(filePath, "\\\\appdata\\\\local\\\\temp\\\\rar$") &&
match(fileName, r'\.[a-zA-Z0-9]{1,4}\s+\.(cmd|bat)$'){
flag = true
}
flag
Заключение
Исходя из разбора, описанного выше можно выделить следующие рекомендации по защите от уязвимости CVE-2023-38831:
Установите обновление.
Эта уязвимость затрагивает версию WinRAR до 6.23. Рекомендуется обновить WinRAR до последней версии. Регулярное обновление программного обеспечения, браузеров и устройств является важной практикой безопасности, которая поможет защитить ваши системы от известных уязвимостей и киберугроз.Будьте внимательны.
Всегда будьте осторожны при получении сообщений, которые просят вас перейти по ссылке или открыть вложение.Скорректируйте настройки.
Настройте технологии безопасности электронной почты, такие как SPF, DKIM и DMARC, чтобы аутентифицировать и проверять происхождение входящих сообщений.Проводите мониторинг и анализ.
Наличие правильного журналирования, видимости активов и мониторинга систем является важными компонентами надежной стратегии кибербезопасности. Эти меры предоставляют обзор сети и помогают выявлять аномалии, которые могут указывать на угрозу безопасности.Следите за новыми трендами атак.
Будьте в курсе новых тенденций, которые используют атакующие. Это поможет вам своевременно выявлять потенциальные риски.
Кроме того, использование таких решений безопасности, как R-Vision SIEM, поможет своевременно обнаружить эту активность и предотвратить дальнейшее развитие атаки, если будет эксплуатироваться уязвимость CVE-2023-38831.
Так, детектирующая логика в правилах R-Vision SIEM направлена на мониторинг событий создания процесса cmd.exe
от процесса winrar.exe
по событиям EventID 1 журнала Sysmon и EventID 4688 журнала Security (для правила «Запуск интерпретатора командной строки от WinRAR»
) и по событиям создания файла во временной директории с двойным расширением, где между расширениями будет пробел, эту активность можно отслеживать по событиям EventID 11 журнала Sysmon (для правила «Эксплуатация уязвимости в WinRAR — CVE-2023-38831»
). Использование данных событий в правилах корреляции позволяет нам своевременно выявить эксплуатацию уязвимости.
Если у вас остались вопросы, я с радостью отвечу на них в комментариях!
Автор: Илья Ефимов, аналитик-исследователь угроз кибербезопасности R-Vision.