DLL Hijacking — это популярный метод осуществления вредоносных полезных нагрузок. В этой статье перечислены около 300 исполняемых файлов, уязвимых для данной атаки в Windows 10, а также показано, как с помощью нескольких строк VBScript могут быть выполнены некоторые из вариантов DLL Hijacking с повышенными привилегиями, минуя UAC.
DLL Hijacking
Прежде всего, нужно разобраться с определением этого понятия. DLL Hijacking — это, в самом широком смысле, обман легитимного (доверенного) приложения для загрузки произвольной библиотеки DLL. Такие термины, как DLL Search Order Hijacking, DLL Load Order Hijacking, DLL Spoofing, DLL Injection и DLL Side-Loading часто ошибочно используются для того, чтобы дать определение этому понятию. В лучшем случае эти термины описывают какие-то конкретные случаи DLL Hijacking, но часто применяются взаимозаменяемо и, следовательно, не совсем верно. Как зонтичный термин, DLL Hijacking является более точным определением, так как он включает в себя захват DLL из легитимной DLL.
Стоит отметить, что злоумышленники используют эту атаку по-разному и по многим причинам. Выбор часто склоняется к ней, так как DLL Hijacking охватывает выполнение (выполнение вредоносного кода через доверенный исполняемый файл, что может с меньшей вероятностью вызвать сигналы тревоги системы, а в некоторых случаях даже обойти белый список приложения, такого как AppLocker), получение персистентности (если целевое приложение предварительно установлено и работает постоянно, то и вредоносный код тоже будет функционировать соответственно) и эскалацию привилегий (если целевое приложение работает с повышенными привилегиями, то и вредоносный код будет функционировать соответственно).
Существует множество подходов, успех которых зависит от того, какие настройки имеет приложение относительно загрузки необходимых библиотек DLL. Среди возможных вариантов выделяют:
- DLL replacement: нужно заменить законную DLL на вредоносную DLL. Это может быть осуществлено в сочетании с DLL проксированием, которое дает возможность всем свойствам оригинальных файлов остаться неизменными.
- DLL search order hijacking: библиотеки DLL, указанные приложением без пути, разыскиваются в указанных местах в определенном порядке. Процесс происходит путем размещения вредоносной библиотеки DLL в том месте, которое находится в поиске до фактической библиотеки DLL. Иногда оно содержит рабочий каталог целевого приложения.
- Phantom DLL hijacking: вредоносная DLL используется вместо несуществующей DLL, после этого нужно попытаться загрузить легитимное приложение.
- WinSxS DLL replacement: следует заменить легитимную DLL на вредоносные dll файлы в соответствующей папке winsxs целевых файлов. Этот способ часто называется еще DLL side-loading.
- Relative path DLL Hijacking: нужно скопировать (и необязательно переименовать) легитимное приложение в папку, доступную для осуществления записи пользователем, вместе с вредоносной DLL. В использовании этого способа есть сходство с (Signed) Binary Proxy Execution, разновидностью которого также является «bring your own LOLbin». В последнем же легитимное приложение перемещается вместе с вредоносной DLL, а не копируется из легитимного местоположения на машине жертвы.
Поиск уязвимых исполняемых файлов
Самой большой проблемой является поиск уязвимого исполняемого файла, который можно использовать с разрешениями пользователя по умолчанию. При таргетинге на предустановленные системные исполняемые файлы в Windows атака обычно исключает первый подход, в то время как любые папки, соответствующие 2 и 3 способу, должны быть доступны для записи пользователем, как и файлы и папки в вариантах 4 и 5. Однако, это все мимо.
Следует уделить внимание шестому, самому слабому методу, о котором и пойдет речь в данной статье, хотя обычно он не подходит для получения персистенции или эскалации привилегий. Нужно работать с OceanLotus / APT32, которые в конце 2019 года уже использовались для применения законного rekeywiz.exe вместе с вредоносным duser.dll. В этом случае программа внедряет законное программное обеспечение и сбросывает его на диск, применив подход «bring your own LOLbin» (другой способ достижения такого же результата заключается в копировании легитимного исполняемого файла из папки \system32\, предполагая, что исполняемый файл еще не был пропатчен).
Для того чтобы предотвратить осуществление других атак, стоит определить исполняемые файлы, которые уязвимы для такого рода DLL hijacking. Это даст «красным командирам» новые средства для проведения «казни», но, что более важно, позволит охотникам за потенциальными угрозами и защитникам принять соответствующие меры для обнаружения и предотвращения будущих нападений.
Подход
Для того чтобы не запутаться, надо ограничиться исполняемыми файлами, присутствующими по умолчанию в c:\windows\system32\. В тестируемом экземпляре Windows 10 v1909 это составляло в общей сложности 616 исполняемых файлов или 613, если рассматривать только подписанные приложения.
Для отслеживания того, какие библиотеки DLL загружаются с каждым процессом, нужно применить хорошо известный инструмент Procmon. Таким образом, используемый подход заключается в следующем: доверенный исполняемый файл копируется в место, доступное для записи пользователем; он запускается и применяется Procmon для идентификации библиотек DLL, которые разыскиваются в месте, доступном для записи пользователем.
На картинке видно, как это работает.
Такой подход позволяет идентифицировать все библиотеки DLL, запрашиваемые каждым приложением, которые станут потенциальными кандидатами для проведения атаки DLL Hijacking. Самый надежный способ узнать, какие библиотеки DLL правильно загружены, — это скомпилировать собственную версию библиотеки DLL и сделать ее запись в уникальный файл после успешной загрузки. Если затем повторить описанный выше подход для всех целевых исполняемых файлов и библиотек DLL, это приведет к созданию коллекции файлов, которая даст пользователю понимание того, какие библиотеки DLL уязвимыми для DLL Hijacking.
Компиляция пользовательских версий существующих библиотек DLL является более сложной задачей, чем может показаться, поскольку многие исполняемые файлы не будут загружать такие библиотеки DLL, если не выполняются нужные процессы или отсутствуют точки входа. Такие инструменты, как DLL Export Viewer, можно использовать для перечисления всех внешних имен функций и ординалов законных библиотек DLL. Это гарантирует, что скомпилированная библиотека DLL будет в том же формате, что увеличивает шансы на ее успешную загрузку.
Пример кода для версии dxgi.dll, которая появилась в записи Procmon winsat.exe.
Таким образом, принятый подход заключается в следующем:
Полный код с более подробным техническим объяснением можно найти на GitHub.
Подтвержденные файлы для проведения атаки DLL Hijacking
В таблице перечислены все исполняемые файлы в c:\windows\system32 в Windows 10 v1909, которые уязвимы для «относительного пути DLL Hijack». Рядом с каждым исполняемым файлом находится одна или несколько библиотек DLL, которые могут быть захвачены вместе с вызываемыми процедурами этой библиотеки. Как объяснялось в предыдущем разделе, это не просто теория, все проверено практическим путем. Список состоит из 287 исполняемых файлов и 263 уникальных DLL-файлов.
Несколько нюансов:
- Тестирование было выполнено простым запуском каждого исполняемого файла без указания каких-либо параметров и без дальнейшего взаимодействия с пользователем. Это объясняет тот факт, почему хорошо документированный xwizard.exe отсутствует в этом списке, потому что для его работы требуется два (произвольных) аргумента.
- Некоторые приложения поставляются с графическим интерфейсом или каким-то другим визуальным элементом, который выдает выполненный двоичный файл. Сюда также можно включить сообщения об ошибках: необходимые библиотеки DLL могут отсутствовать, а захваченная библиотека DLL не иметь оригинальной функциональности. Злоумышленники с меньшей вероятностью будут нацелены на такие приложения для захвата DLL.
- Библиотеки DLL, исходная версия которых была написана на языке C++, не берутся во внимание.
СVS-версия таблицы может быть найдена на GitHub.
Корреляция с обходом UAC
Найдя все эти исполняемые файлы, пользователь сможет выполнять код через доверенные программы. Однако также он имеет возможность получить привилегированные права, если использовать их в сочетании с методами обхода UAC.
Контроль учетных записей пользователей (UAC) появился в Windows Vista в качестве функции, связанной с безопасностью системы; он запрашивал у пользователей подтверждение через приглашение, прежде чем процесс, работающий с обычными привилегиями, будет повышен до более высокого уровня. После того как пользователи пожаловались на миллион подсказок UAC при выполнении произвольных задач, Microsoft ввела автоматическое повышение уровня привилегий в Windows 7, которое автоматически повышает уровень некоторых процессов, если они находятся в доверенных каталогах (например c:\windows\system32 ).
Имея это в виду, пользователь может попробовать запустить произвольный код с повышенными привилегиями, используя исполняемый файл, помеченный для автоматического повышения, который также уязвим для захвата DLL. Существует около 35 таких исполняемых файлов. Проблема, от которой нужно избавиться, содержится в доверенном каталоге: и исполняемый файл автоматического повышения уровня, и пользовательская библиотека DLL должны быть расположены в одном доверенном каталоге, но ни один из них не может быть записан пользователем.
Существует несколько превосходных исследований об обходе UAC: к примеру, вот этот. Желательно прочитать статью полностью, но все сводится к тому, что пользователи могут создавать c:\windows \system32\ (надо обратить внимание на пространство после первой папки) и автоматически повысить статус исполняемых файлов, помещенных в эту папку.
Спорно, является ли это настоящей уязвимостью для безопасности. Microsoft утверждает, что это не совсем так, но, по крайней мере, данный недостаток присущ большинству компьютеров, работающих на Windows.
В любом случае, это дает пользователю отличную возможность для захвата DLL. Стоит обратить свое внимание, что папки с конечными пробелами не могут быть созданы традиционными средствами в Windows. Пользователь способен скомпилировать некоторые строки C, чтобы создать их, как это делает оригинальный исследователь, но оказывается, что VBScript действительно может справиться сам. Данное доказательство всей концепции указывает на то, что с помощью всего нескольких строк кода пользователь добьется успеха без проблем:
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set wshshell = wscript.createobject("WScript.Shell")
' Get target binary and payload
WScript.StdOut.Write("System32 binary: ")
strBinary = WScript.StdIn.ReadLine()
WScript.StdOut.Write("Path to your DLL: ")
strDLL = WScript.StdIn.ReadLine()
' Create folders
Const target = "c:\windows \"
target_sys32 = (target & "system32\")
target_binary = (target_sys32 & strBinary)
If Not oFSO.FolderExists(target) Then oFSO.CreateFolder target End If
If Not oFSO.FolderExists(target_sys32) Then oFSO.CreateFolder target_sys32 End If
' Copy legit binary and evil DLL
oFSO.CopyFile ("c:\windows\system32\" & strBinary), target_binary
oFSO.CopyFile strDLL, target_sys32
' Run, Forrest, Run!
wshshell.Run("""" & target_binary & """")
' Clean files
WScript.StdOut.Write("Clean up? (press enter to continue)")
WScript.StdIn.ReadLine()
wshshell.Run("powershell /c ""rm -r """"\\?\" & target & """""""") 'Deletion using VBScript is problematic, use PowerShell instead
На скриншоте ниже показано, как может выглядеть выполнение скрипта.
Пример, на котором видно, что файл обладает повышенными привилегиями после того, как вредоносный DXGI.dll был загружен с помощью легитимного winsat.exe из нужного доверенного каталога, не получая никаких подсказок от UAC.
В приведенной таблице все комбинации исполняемых файлов и DLL, для которых автоматическое повышение уровня было успешным, помечены в первом столбце. Среди более чем 160 возможных комбинаций пользователь способен выбрать подходящую ему.
Профилактика и выявление
Простой способ предотвратить захват DLL-файлов заключается в том, чтобы приложения всегда использовали абсолютные пути вместо относительных. Хотя некоторые приложения (особенно портативные) не всегда смогут это сделать; программы, расположенные в \system32\ и полагающиеся на библиотеки DLL в той же папке, не имеют никаких оправданий для того, чтобы поступать иначе. Лучшим вариантом является проверка всех библиотек DLL перед их загрузкой (например, путем проверки их сигнатур), что в значительной степени предотвратит появление проблем.
Тем не менее, злоумышленники все еще смогут использовать более старые версии легитимных приложений. Поэтому, даже если каждое приложение начнет проверять свои библиотеки DLL перед загрузкой, вероятность возникновения проблем все еще существует.
Нужно сосредоточиться на обнаружении нападения. Пользователь может постоянно следить за созданием или загрузкой любой из упомянутых ранее библиотек DLL из неожиданных путей, особенно во временных местоположениях, таких как %appdata%. В конце концов, имя (законного) приложения, загружающего библиотеки DLL, может быть изменено, но имена файлов библиотек DLL всегда фиксированы. Доказательство этого утверждения можно найти здесь: успешно обнаруживается захват DLL, хотя, как видно, есть склонность к ложным срабатываниям. Пользователь способен использовать более общий подход, применяя поиск подписанных Microsoft двоичных файлов в неожиданных местах, загрузки библиотек DLL из неожиданных мест.
Наконец, продемонстрированный метод обхода UAC может быть легко обнаружен путем поиска любой активности в папке / windows / или в любых папках, заканчивающихся пространством. Как описано выше, папки Windows с конечными пробелами не могут быть созданы обычным способом и поэтому их создание всегда вызывает подозрение. Установка постоянных уведомление на UAC предотвратит этот и другие подобные методы обхода.
Автор переведенной статьи: Wietze