Как не дать злоумышленникам повысить привилегии в системе после успешного заражения

Как не дать злоумышленникам повысить привилегии в системе после успешного заражения

Всем привет! Этой статьей мы открываем цикл материалов от экспертного центра безопасности Positive Technologies ( PT Expert Security Center ). Мы расскажем о том, какие техники применяют злоумышленники при разработке инструментов для целевых и массовых атак и какие технологии есть «под капотом» нашей песочницы PT Sandbox для их детектирования.

Из первой статьи вы узнаете про самые интересные и распространенные у злоумышленников техники получения полного контроля над системой в целевых атаках. Рассмотрим, какие приемы используют киберпреступники для выдачи себя за другого пользователя, техники обхода UAC и выполнения произвольного кода с максимальными правами, а также разберем, как обнаружить все эти действия злоумышленников в PT Sandbox. Подробнее читайте под катом.

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

Как хакеры используют токен безопасности в своих целях

Токен, или маркер доступа — это некий объект, который формируется LSA (Local Security Authority) при авторизации пользователя в системе, когда вводится пароль, логин и появляется рабочий стол. В этот момент создается новый процесс explorer.exe, в рамках которого уже есть токен. Токен доступа является объектом, обеспечивающим получение пользователем необходимых прав, принадлежности к группам и привилегий, позволяющих открывать новые приложения, файлы и совершать другие действия. Он находится в EPROCESS, структуре в ядре OC Windows, описывающей любой объект процесса. Давайте разберемся, какие зловредные действия можно произвести в системе с токеном.

Имперсонация

Суть имперсонации, или перевоплощения, заключается в том, что процесс одного пользователя выполняет действия в системе не от своего имени, а от имени какой-то другой учетной записи. Алгоритм выдачи себя за другого пользователя следующий: из процесса-жертвы получают описатель целевого процесса → извлекают описатель токена безопасности → происходит имперсонация с помощью вызова API — функции ImpersonateLoggedOnUser, и дублируются свойства токена → полученный токен назначается потоку исполнения.

Чтобы зарегистрировать подобную активность, необходимо среди нескольких поставщиков событий выявить с помощью syscall системный вызов NtOpenProcessToken. В ходе легитимных действий модули процессов часто манипулируют токеном собственного процесса, поэтому следует дополнительно проверить, действительно ли наш процесс — сторонний, изучив такие параметры, как DesiredAccess и описатель процесса. Если процесс собственный, то значение ProcessHandle будет 0xFFFF… (для 32-битной версии, и соответствующее число F для 64-битной версии).

Далее мы попадаем на функцию ImpersonateLoggedOnUser, которая, в свою очередь, раскладывается на несколько системных вызовов: вызов для получения информации о токене NtQueryInformationToken, вызов NtDuplicateToken для создания дубликата токена, и вызов NtSetInformationThread для присвоения полученного нового токена действующему потоку нашего процесса. Ниже можно детальнее рассмотреть два последних вызова.

Создание нового процесса с контекстом безопасности указанного токена

Иначе говоря, получив копию первого токена, можно передать в качестве параметра уже новый токен, таким способом создав новый процесс с правами и уровнем доступа первого токена.

Кроме того, давайте попытаемся как можно глубже перехватить вызов CreateProcessWithTokenW из библиотеки advapi32. В конце концов мы доберемся до межпроцессного вызова взаимодействия NdrClientCall4, где интерес для нас представляют лишь два параметра: с кем мы взаимодействуем и что мы хотим вызвать на другой стороне.

Параметр № 1: проходим по указателю → смотрим на структуру данных (первое поле — это размер этой структуры, а затем — идентификатор интерфейса) → находим в интернете информацию, что это Secondary logon service.

Параметр № 2: номер вызываемой процедуры на эндпойнте, в нашем случае — 0.

Ниже — как это выглядит в продукте. Событие поставляется от плагина rpcmon.

У внимательно следящих за тем, какие события из сообщения мы выбираем для отслеживания, может возникнуть вопрос: «Почему не фиксируем NdrClientCall4?» Для нас важен только конечный эндпойнт интерфейса и номер вызываемой процедуры, а какой именно вызов происходит — не имеет значения. Вдобавок, если вызывается 32-битный процесс в 64-битной системе, то будет как раз NdrClientCall4. Повторив то же самое в рамках 64-битного процесса, получим NdrClientCall3.

Создание пользовательской сессии

Хакер, зная заранее логин и пароль пользователя, может авторизовать его с помощью advapi32!LogonUserA/W и создать полноценную новую пользовательскую сессию с новым токеном безопасности. А дальше, как мы уже разобрали ранее, либо продолжить работу в рамках своего потока, либо создать новый процесс. Отслеживая факт авторизации пользователя, мы снова дойдем до вызова NdrClientCall4, идентификатора интерфейса и функции SspirLogonUser, отвечающей за авторизацию пользователей.

Как детектируется в PT Sandbox?

В интерфейсе продукта на вкладке «Поведенческий анализ» в разделе «Потенциально опасное поведение» отображаются все случаи подозрительного и опасного поведения. Вердикты могут быть разные, например Write.Thread.Token.Impersonation, Create.Process.WithToken. Impersonation, Create.Token.LogonUser.Impersonation и другие.

UAC: что это, зачем нужен и при чем здесь доверенные приложения

Злоумышленникам, в принципе, ничего не мешает сразу создавать процессы с правами администратора. User Account Control — это всем известное всплывающее окошко, которое появляется в системе, когда пользователь хочет установить или запустить, например, программу, и для этого ему необходимо повысить свои привилегии до уровня администратора. UAC требуется, чтобы злоумышленник смог, например, провести атаку по шифрованию загрузочного сектора диска.

У этого механизма есть доверенные приложения, которые запускаются с правами администратора и не спрашивают UAC, так как они являются системными и работают с максимальными правами. Требования к доверенным приложениям следующие:

  • в манифесте есть ключ autoElevate, и он равен True;

  • правильная подпись;

  • запуск из доверенной директории.

Эксплуатируя баги, недоработки или легитимные особенности доверенных приложений, хакеры имеют много возможностей запускать вредоносное ПО в контексте администратора без окошка UAC: например, только в system32 есть более 50 таких приложений. Ниже рассмотрим техники обхода UAC.

Wusa

Довольно известный метод, который заключается в подмене легитимной библиотеки на необходимую хакерам. Создается процесс Wusa, а именно установщик обновлений с параметром /extract → извлекается архив в доверенную директорию → подменяется DLL после extract → запускается доверенное приложение, таким образом повышая привилегии созданного процесса до уровня администратора.

Это показательный пример того, как можно совершить подмену DLL, имея доверенное приложение с легитимной возможностью. Сейчас данный метод неактуален, так как в Windows 10 у Wusa была убрана функция extract.

Ключи реестра

Обход UAC может основываться не только на легитимных возможностях, но и на багах в приложениях — к примеру, это обращение к несуществующему ключу. Fodhelper — программа для настройки языка Windows 10, которая обращается к несуществующим ключам реестра. А если ключей не существует, значит, можно создать любой произвольный. Получается, хакеры записывают в среде ключей реестра необходимую им вредоносную команду, к которой в следующий раз обращается fodhelper и исполняет ее.

Данную или аналогичную уязвимость использует целая группа приложений (недавние примеры представлены на скриншотах ниже). Ее эксплуатацию можно зафиксировать путем отслеживания изменений в реестре.

Переменные окружения

В реестр, помимо ключей, можно записывать значения переменных окружения. Программы, которые используют переменные окружения при запуске кода, считаются уязвимыми. Рассмотрим ниже пример, где можно переписать значение переменной окружения windir, запустить заново задачу в планировщике (в качестве администратора), но с исполнением необходимого нам кода. Детектируется это также слежением за реестром — непосредственно за ключом, отвечающим за переменное окружение.

COM-объекты

СOM-объект — это интерфейс в Windows, который позволяет взаимодействовать с объектами. Существуют доверенные объекты, которые, по аналогии с доверенными приложениями, выполняют действия в контексте администратора без запроса UAC.

Использование IFileOperation, который позволяет переносить объекты из одного места в другое, — самая популярная техника, основанная на COM-объектах. В этом случае создается библиотека → вызывается IFileOperation → копируется в system32 → вызывается sysprep.exe, который ее подгружает → происходит подмена DLL. Следует отметить, что можно подменить любую DLL, которая небезопасно подгружается. И есть ряд приложений, которые хакеры таким образом могут эксплуатировать.

Кроме того, часть COM-объектов обладает недокументированной возможностью запуска кода — соответственно, появляется возможность отслеживать обращение к таким объектам, а затем запуск процесса dllhost.exe.

Shim-таблицы

Техника заключается в создании таблицы импортов для старых приложений в новой среде: некоторые вызовы перенаправляются на вредоносные объекты, и в случае доверенного приложения вредоносный код выполняется в контексте администратора.  Создание shim-таблицы и запуск процесса — два главных признака для детектирования эксплуатации этой уязвимости.

Ложная директория

В рамках этой техники эксплуатируются свойства, которыми обладает доверенное приложение: правильный манифест, правильная подпись и доверенная директория. Фейковая доверенная директория создается следующим образом:

  1. Создается Windows с пробелом — не из файлового менеджера, а с помощью API. При проверке этого пути парсинг происходит неправильно, то есть после windows пробел не учитывается, поэтому название созданной фиктивной директории будет восприниматься как «windowssystem32».

  2. Доверенное приложение копируется в ложную директорию.

  3. Загружается вредоносная DLL рядом с доверенным приложением.

  4. Запускается доверенное приложение с подменной DLL.

Получается, что хотя приложение и не из «правильной» директории, система считает ее доверенной. Детектируется за счет отслеживания наличия пробела: если пробел есть, значит, кто-то пытается проникнуть.

А как выглядит в PT Sandbox?

В продукте подобные детекты описываются как Create.Process.ExtraRegKey.UACBypass, Create.Process.EnvironmentVar.UACBypass, Create.Process.DirectoryMock.UACBypass, Create.Process.COMDLLHijack.UACBypass и так далее.

Рассмотрим в PT Sandbox пример 2020 года, когда загрузчик бэкдора Polpo использовал технику повышения привилегии с обходом UAC, — скриншоты ниже.

Как обнаружить эксплойты по повышению привилегий

В 2015 году в ходе атаки группировка APT28 использовала эксплойт уязвимости CVE-2015-1701 (на тот момент zero day) для повышения привилегий. На примере хеш-суммы MD5 рассмотрим технику эксплуатации.

Важно: функция CreateWindowExW создаст новое окно, а в качестве оконной процедуры выступает функция kernel_steal_token.

После того как будет вызвана API-функция CreateWindowsExW, управление  передается на перехваченную функцию hooked_ClientCopyImage. В результате будет получен описатель текущего потока и вызвана еще одна легитимная функция SetWindowLogPtrW, где первый параметр — это добытый описатель окна текущего потока, второй параметр — число – 4 — является командой, назначающей новый адрес для оконной процедуры по умолчанию. При выполнении данной команды указанная выше оконная процедура открываемого окна автоматически признается оконной процедурой по умолчанию, а процедуру с таким свойством ОС, в свою очередь, выполняет в ядре.

Далее вызывается ядерная функция PsLookupProcessByProcessId → на входе получаем идентификатор текущего процесса, а на выходе — указатель на структуру EPROCESS → функция вызывается еще раз → происходит переназначение, то есть указатель на токен действующего процесса теперь указывает не на свой токен, а на токен системного процесса. Таким образом, процесс получает все полномочия системного.

Ниже скриншот поведенческого анализа уязвимости CVE-2015-1701 в PT Sandbox: продукт обнаружил эксплойт.

Откуда взяли PsLookupProcessByProcessId?

Сначала у нас был пользовательский код, а затем неожиданно вызвана функция PsLookupProcessByProcessId из ядра. Откуда приложение знает ее адрес?

Выполняется недокументированный вызов NtQuerySystemInformation с параметром SystemInformationClass, равным 11. В результате данного вызова переменная на выходе получает структуру (информацию) о загруженных модулях. Информация о ядре OC — это первый элемент в этой структуре.

Далее извлекается полный путь до ядра ОС → появляется символ PsLookupProcessByProcessId (еще в пользовательском пространстве) → арифметически находится разница между адресом символа и базовым адресом ядра → к ней добавляется настоящий базовый адрес ядра в «ядре» (а не в пользовательском пространстве) → происходит корректный вызов.

Так как в нашем примере происходил маппинг ядра в пользовательское пространство, предлагаем вспомнить, как в 2011 году группировка FIN6 проводила свою очередную атаку, используя эксплойт повышения привилегий. По коду можно сделать вывод, что часть действий была связана с тем, что ядро подгружалось в пользовательское пространство — в данном случае указан реальный ядерный адрес структуры HalDispatchTable. Из практики известно, что, имея примитив на запись, злоумышленники обычно переписывают 4-й офсет в этой структуре, а потом, вызывая syscall из пользовательского пространства, передают управление на перезаписанный обратный вызов уже в ядре.

Таких примеров очень много. Например, загрузка ядра в пользовательское пространство была использована группировкой Fancy Bear в 2016 году при эксплуатации уже другого zero day.

Спустя два года APT FruityArmor во время своей атаки тоже подгружала в пользовательское пространство ядро.

А что предлагает PT Sandbox? В продукте было решено сделать детект на маппинг ядра OC в пользовательское пространство. (Разумеется, в легитимном порядке ничто из ориентированного на работу в пользовательском режиме не должно вызываться из ядра.)

Вердикт, который мы получаем в PT Sandbox на маппинг  ядра в пользовательскую память, представлен ниже. Помимо этого, есть другие варианты детектов попыток эксплуатации уязвимостей.

Подробнее о PT Sandbox

PT Sandbox — песочница для защиты от целевых и массовых атак с применением неизвестного вредоносного ПО и угроз нулевого дня. Продукт обеспечивает комплексный анализ файлов и трафика (включая шифрованный). Песочница глубоко кастомизирована — ее можно настроить как реальную машину в корпоративной сети, и не обнаруживается большей частью техник детектирования. Таким образом, шанс того, что вирус поймет, что он исполняется в виртуальной среде, ничтожно мал. Узнать больше о возможностях PT Sandbox можно здесь .

Для тех, кому удобнее слушать, а не читать, мы выложили запись вебинара по этой теме. Присоединяйтесь к экспертным вторникам PT Expert Security Center — расписание ближайших вебинаров здесь .


Авторы:

Алексей Вишняков

Руководитель отдела обнаружения вредоносного ПО PT ESC

Антон Шумаков

Специалист отдела обнаружения вредоносного ПО PT ESC

Alt text

Домашний Wi-Fi – ваша крепость или картонный домик?

Узнайте, как построить неприступную стену