. UAC Bypass или история о трех эскалациях
UAC Bypass или история о трех эскалациях

UAC Bypass или история о трех эскалациях

На работе я исследую безопасность ОС или программ. Ниже я расскажу об одном из таких исследований, результатом которого стал полнофункциональный эксплоит типа UAC bypass (да-да, с source-code и гифками).

История

GUI UAC bypass

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

Гифка показывает, как такая атака выглядела в Windows 98. Атакующий хитрыми манипуляциями вызывает окно открытия файла и через него запускает explorer.

Сначала проведем простой тест, чтобы посмотреть, что происходит — запускаем блокнот. Выбираем в меню пункт «Открыть», а в появившемся окне переходим в папку C:\Windows\system32\. В окне отображаются только файлы txt и папки. Это легко поправить — достаточно вместо имени файла написать *.* и будут отображены все файлы (в случае блокнота можно проще — выбрать фильтр «Все файлы», но такой фильтр будет доступен не всегда, а звездочки будет работать всегда). Находим notepad.exe и запускаем его через контекстное меню.

Process Explorer показывает вполне ожидаемую картину:

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

Тут я вспомнил о приложениях с автоматически поднимаемыми привилегиями. Речь идет о программах, у которых в манифесте прописано поднятие привилегий без запроса UAC (элемент autoElevate). Для первого эксперимента я выбрал многострадальный eventwvr.exe (он уже пару раз засветился в обходах UAC).

Все оказалось очень просто, в меню «Действие» есть пункт «Открыть сохраненный журнал…» — этот пункт выводит окно открытия файла, что мы и хотим получить.

После запуска мы увидим такую ситуацию:

Мы запустили консоль с правами администратора без появления окна UAC.

Такой вид уязвимостей называется UAC bypass (обход запроса UAC). Важно отметить существенное ограничение — автоматическое поднятие прав работает, только если пользователь входит в группу администраторов. Поэтому с помощью такой уязвимости нельзя поднять права с уровня пользователя. Но все же уязвимость довольно опасна — очень много пользователей Windows использует аккаунт администратора для повседневной работы. Вредоносная программа, которую запустит пользователь такого аккаунта, без внешних проявлений получит сначала административные привилегии, а затем, если ей надо, то может получить хоть NT AUTHORITY\SYSTEM. С привилегиями администратора это очень легко.

На гитхабе есть отличный проект https://github.com/hfiref0x/UACME, где собраны, наверное, все имеющиеся в открытом доступе уязвимости такого рода, причем с указанием с какой версии Windows уязвимость начала работать, и в какой ее поправили, если поправили.

Я далеко не первый, кто подумал об уязвимости такого плана. Ниже я прикладываю два анимационных изображения, которые наглядно показывают обход UAC еще двумя способами.

Я прошелся по разным приложениям и ниже прикладываю еще 18 способов реализации такого обхода.

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

Кроме того, если у вас установлен принтер, то с большой вероятностью в окошках, связанных с печатью, вы найдете много дополнительных способов вызвать окно выбора файла.

cliconfg.exe 1) Кнопка «Справка», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Просмотр HTML-кода», в появившемся окне Блокнота выбрать в меню «Файл», пункт «Открыть». 2) Кнопка «Справка», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Печать», в появившемся окне «Найти принтер…», в окне поиска выбрать меню «Файл», пункт «Сохранить условия поиска».

compMgmtLauncher.exe 3) Меню «Действие», пункт «Экспортировать список…». 4) Меню «Справка», пункт «Вызов справки», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Просмотр HTML-кода», в появившемся окне Блокнота выбрать в меню «Файл», пункт «Открыть». 5) Меню «Справка», пункт «Вызов справки», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Печать», в появившемся окне «Найти принтер…», в окне поиска выбрать меню «Файл», пункт «Сохранить условия поиска».

dcomcnfg.exe 6) В списке слева выбрать «Службы (локальные)», в контекстном меню выбрать пункт «Экспортировать список…».

eudcedit.exe 7) После старта, программа предложит выбрать код. Выбираем любой и нажимаем ОК; В меню «Файл» выбираем пункт «Связи шрифтов…», в появившемся окне отмечаем «Установить связь с выбранными шрифтами», это разблокирует кнопку «Сохранить как…».

eventvwr.exe 8) Меню «Действие», пункт «Открыть сохраненный журнал…». 9) Меню «Справка», пункт «Вызов справки», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Просмотр HTML-кода», в появившемся окне Блокнота выбрать в меню «Файл», пункт «Открыть». 10) Меню «Справка», пункт «Вызов справки», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Печать», в появившемся окне «Найти принтер…», в окне поиска выбрать меню «Файл», пункт «Сохранить условия поиска».

netplwiz.exe 11) Выбрать вкладку «Дополнительно», в группе «Дополнительное управление пользователями» нажать кнопку «Дополнительно». Будет запущена оснастка lusrmgr.msc. Меню «Действие», пункт «Экспортировать список…».

odbcad32.exe 12) Кнопка «Справка», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Просмотр HTML-кода», в появившемся окне Блокнота выбрать в меню «Файл», пункт «Открыть». 13) Кнопка «Справка», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Печать», в появившемся окне «Найти принтер…», в окне поиска выбрать меню «Файл», пункт «Сохранить условия поиска». 14) Выбрать вкладку «Трассировка», кнопка «Обор…» 15) Выбрать вкладку «Трассировка», кнопка «Выбор DLL…»

perfmon.exe 16) В списке слева выбрать группу «Отчеты», в ней «Особые», в контекстном меню выбрать пункт «Экспортировать список…». 17) Меню «Справка», пункт «Вызов справки», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Просмотр HTML-кода», в появившемся окне Блокнота выбрать в меню «Файл», пункт «Открыть». 18) Меню «Справка», пункт «Вызов справки», в появившемся окне справки вызвать контекстное меню в рабочей области, выбрать «Печать», в появившемся окне «Найти принтер…», в окне поиска выбрать меню «Файл», пункт «Сохранить условия поиска».

Хоть мы и получили консоль администратора с правами администратора, но назвать это уязвимостью или эксплоитом сложно — нужны осознанные действия пользователя. Чтобы данную уязвимость считать практической, а не теоретической — нужно автоматизировать действия.

UIPI bypass

Автоматизация? Да легко! Берем AutoIt и быстро клепаем приложение, которое эмулирует нажатие клавиатуры.

  • WIN-R, eventvwr, ENTER — запустили приложение;
  • ALT-нажали-и-отпустили — фокус на главное меню;
  • Вправо-Вниз-Вниз-ENTER — выбрали нужный пункт в меню;
  • C:\windows\system32 ENTER — перешли в нужную папку;
  • * ENTER — сбросили фильтр;
  • SHIFT-TAB, SHIFT-TAB — окно фокуса на списке файлов;
  • сmd — выбрали файл cmd.exe;
  • App (Кнопка контекстного меню, обычно рядом с правым Ctrl и правыми Alt), вниз, вниз, ENTER — выбираем пункт «Открыть».

Все оказывается довольно просто — Майкрософт использует технологию UIPI (User Interface Privilege Isolation). Если коротко, то многие интерфейсные взаимодействия блокируются, если Integrity Level (IL) инициатора ниже, чем у целевого приложения. Процессы с привилегиями администратора имеют High IL и выше, а приложение, запускаемое пользователем без поднятия привилегий, имеет Medium IL. Нельзя слать большинство сообщений, эмулировать мышь, клавиатуру.

Как же обойти UIPI? Майкрософт указывает, что есть еще один интересный параметр, который можно указать в манифесте — UIAccess. При выполнении ряда суровых условий приложение получит возможность взаимодействовать с интерфейсом других программ. Собственно, сами условия:

  1. UIAccess=«true» в манифесте.
  2. Программа должна быть подписана и сертификат подписи должен восприниматься компьютером как доверенный.
  3. Программа должна быть расположена в «безопасной» папке или глубже. Под безопасными папками понимаются папка C:\Windows (с некоторыми исключениями), C:\Program Files, C:\Program Files (x86).

Появляется идея попробовать скопировать Osk.exe куда-то, где он все еще будет считаться расположенным по «безопасному» пути. Тогда мы сможем контролировать это приложение, но все равно выполнять условия для обхода UIPI.

Я написал простой поисковик по директориям C:\Windows, C:\Program Files, C:\Program Files (x86), который бы искал места, куда можно копировать без прав администратора. На удивление, таких директорий нашлось немало. К сожалению, большая часть из них либо входит в исключения C:\Windows, либо является директориями, куда можно писать, но откуда нельзя запускать приложения. И все равно, нашлось две подходящих папки:

  • C:\Windows\minidump
  • C:\Program Files\Microsoft SQL Server\130\Shared\ErrorDumps

А вот вторая папка уже лучше — за исключением того, что она появляется при установке Microsoft Visual Studio (2017 в данном случае, у других студий будут другие числа вместо 130, например 120 у MSVS 2015).

Копируем osk.exe в папку C:\Program Files\Microsoft SQL Server\130\Shared\ErrorDumps. Смотрим таблицу импорта приложения. Среди библиотек в импорте я выбрал osksupport.dll — это библиотека, экспортирующая всего 2 функции, поэтому можно быстро сделать поддельную.

Собираем dll и копируем по тому же пути — будет dll-инъекция. Запускаем, проверяем — скопированный osk.exe запускается с High IL, код из dll исполняется.

Дописываем в dll автоматизацию клавиатурных нажатий (уже не AutoIt, а быстро все перекинутое на плюсовый код keybd_event). Убеждаемся, что все работает. Теперь у нас уже почти готов эксплоит. Надо провести чистый тест.

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

Вот это уже можно назвать эксплоитом — все-таки программа без участия пользователя обходит UAC. Пользователь, конечно, все это видит, но не беда — это мелочи.

Это была первая версия эксплоита — две эскалации (autoElevate и UIAccess), но пользователь видит, что происходит что-то не то.

Я отправился перечитывать Windows Internals Руссиновича в тех главах, где упоминается UIAccess и UIPI. Внезапно, русским по белому там было написано, что UIPI предотвращает использование SetWindowsHookEx. Но я как раз обошел UIPI, а значит мог использовать эту функцию — так стало еще лучше! Я смог провести инъекцию кода, вместо отправки клавиатурных нажатий. Вот и вторая версия эксплоита — те же эскалации, но теперь без заметных действий на экране. Почти сразу после запуска эксплоита запускалась привилегированная консоль.

Directory bypass

На этом этапе я написал письмо с описанием уязвимости, кодом эксплоита и пошаговым объяснением в Майкрософт. Реакция саппорта немного удивила — они спрашивали: «Получается, что для запуска вашего эксплоита нужны права администратора?». Попытка объяснить, что это не эскалация привилегий с пользователя до администратора, а обход UAC, успехом не увенчалась.

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

Сначала я попробовал «распаковать» произвольный файл в C:\windows\system32. Получил ошибку отказа в доступе. Логично, я давно читал, что вроде бы этот способ убрали. Но на всякий случай решил проверить с путем в Program Files. Утилита отработала, файл скопировался. Вот теперь запахло жареным — необходимость папки с правами на запись в Program Files постепенно пропадала.

Но от способа с WUSA я решил отказаться. В Windows 10 (10147) у приложения убрали опцию /extract. Тем не менее я не унывал. На примере WUSA я понял, что не всегда защита C:\Windows означает защиту C:\Program Files. Кроме WUSA был еще способ копировать файлы без запроса UAC — интерфейс IFileOperation.

Дальше было несложно. Я написал код, использующий этот метод (вот она, третья автоматическая эскалация), и он отлично отработал. Для надежности я взял чистую виртуальную машину с максимальным количеством установленных обновлений последней версии Windows 10 (RS2, 15063). Это было особенно важно, поскольку RS2 как раз исправлял часть обходов UAC. И вся моя цепочка прекрасно отработала на этой версии. Это и есть третья версия эксплоита, с 3 эскалациями, без каких-либо специальных требований.

Техническое описание

Работоспособность эксплоита тестировалась на Windows 8, Windows 8.1 и Windows 10 (RS2, 15063) — техника работает. С вероятностью в 99% будет работать и в младших версиях, начиная с Windows Vista, но потребуются правки (другое имя и таблица экспорта для dll на 2 и 3 шагах). Настройки UAC должны быть выставлены по-умолчанию, и пользователь, от которого происходит запуск инициирующей программы, должен входить в группу администраторов ПК.

Шаг 1. Программа запускается без запроса предоставления привилегий. IL программы Medium, что позволяет сделать инъекцию кода в процесс explorer.exe (например, через SetWindowsHookEx).

Шаг 2. Код, работающий в контексте explorer.exe, инициирует файловую операцию копирования через IFileOperation. Происходит первая автоматическая эскалация привилегий — explorer.exe считается доверенным процессом, поэтому ему позволяется копировать файлы в Program Files без запроса подтверждения UAC. В любую папку в Program Files копируется системный файл osk.exe, изначально расположенный C:\Windows\system32\osk.exe. Рядом копируется библиотека с полезной нагрузкой под именем osksupport.dll.

Шаг 3. Запускается только что скопированный osk.exe. Поскольку выполняются все требования для предоставления UIAccess, то файл имеет High IL — происходит вторая автоматическая эскалация привилегий (поднят только IL, но прав администратора все еще нет). Сразу после старта срабатывается Dll-инъекция и в контексте данного процесса исполняется код из osksupport.dll. Полезная нагрузка этой библиотеки ожидает старта привилегированного процесса, чтобы провести инъекцию кода в него.

Шаг 4. Запускается любой процесс, который автоматически поднимается в правах до администратора (например, многострадальный eventvwr.exe, это третья эскалация). В него происходит инъекция кода. В данный момент код будет исполняться с привилегиями администратора.

Proof of Concept

PoC состоит из двух частей — dll (написана на c++) и exe (написан на c#). Сначала необходимо собрать dll и подключить эту библиотеку как ресурс для кода приложения. Обязательно обратите внимание на комментарии в коде.

Готовый к эксплуатации бинарный файл не выкладывается осознанно. Не менее осознанно исходные коды не выкладываются на гитхаб.

📎📎📎📎📎📎📎📎📎📎