Обход контроля учетных записей (UAC) путем пародирования доверенных директорий

https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e
  • Перевод

Эксперт по информационной безопасности Дэвид Уэллс (David Wells) опубликовал способ обхода контроля учетных записей UAC в Windows 10

Всем привет!

Во время исследований некоторых новых методов обхода службы контроля учетных записей (UAC) я открыл совершенно новый метод обхода UAC на момент написания этой статьи. Стоит отметить, что Microsoft не считает UAC границей безопасности, однако мы до сих пор сообщаем о разных багах в Microsoft и я хочу поделиться подробностями найденной мной уязвимости тут. Этот метод был успешно протестирован на ОС Windows 10 Build 17134. До того, как я погружусь в подробности моей находки, я сначала представлю Вам небольшое пояснение по работе самой службы UAC.

UAC Primer

Когда пользователь, входящий в группу «Администраторы», хочет запустить приложение, требующее повышенных привилегий, то UAC отображает соответствующий запрос и пользователю, являющемуся членом группы «Администраторы», потребуется подтвердить действие Однако, этот запрос UAC не возникает для ВСЕХ административно исполняемых файлов в Windows. Есть несколько исключений, которые будут «автоматически» повышать привилегии исполняемого файла, не вызывая запроса UAC, в обход UAC (к большому удивлению!). Эта отдельная группа избранных надежных исполняемых файлов проходит дополнительные проверки безопасности системой, чтобы убедиться, что на самом деле эти файлы достоверны, поэтому информационные злоумышленники обычно не злоупотребляют данной функцией. Этот подход использовался в предыдущих методах обхода UAС и будет основой моего нового метода обхода. Однако, есть несколько лазеек, которые нам нужно воспользоваться, чтобы наша атака удалась. Давайте рассмотрим требования, которые должны соблюдаться, если мы хотим, чтобы наш исполняемый файл был «автоматически повышен в привилегиях». Для этого я покажу несколько картинок дисассемблируемой библиотеки appinfo.dll (служба AIS, обрабатывающая запросы на повышение привилегии — один из основных компонентов UAC).

Требование 1: Файл сконфигурирован для автоматического повышения привилегий

Когда возникает запрос на повышение привилегий для программы, то в службе AIS (appinfo.dll) выполняется вызов RPC с целевым исполняемым путем, переданным в качестве аргумента. Затем эта служба будет сопоставлять целевое исполняемое содержимое файла для чтения. В манифесте исполняемого файла делается попытка прочитать значение для получения ключа «autoElevate» (если он существует).

Рисунок 1 – Чтение манифеста исполняемого файла для получения значения ключа «autoElevate».



Если значение получено и это «Истина», то файл будет считаться как с «автоматическими» повышаемыми привилегиями исполняемым файлом, который будет запускаться с повышением привилегий и не вызывать диалоговое окно службы UAC (при условии, что оно передало следующие требования, упомянутые ниже).

Рисунок 2 — вызов «bsearch» для проверки имени исполняемого файла в списке исполняемых файлов «auto elevating»



Некоторые из этих жестко запрограммированных в системе файлов в белом списке:
‘cttunesvr.exe’, ‘inetmgr.exe’, ‘migsetup.exe’, ‘mmc.exe’, ‘oobe.exe’, ‘pkgmgr.exe’, ‘provisionshare.exe’, ‘provisionstorage.exe’, ‘spinstall.exe’, ‘winsat.exe’

Требование 2: Правильно подписанные

Предполагается, что второе условие для «автоматического» повышения привилегии после отправки запроса в UAC, это выполнение проверки подписи с помощью «wintrust! WTGetSignatureInfo».

Это означает, что злоумышленник не сможет просто создать свой собственный нужный для «автоматического» повышения привилегий манифест или исполняемый файл и добиться успеха, поскольку бинарный файл злоумышленника, скорее всего, будет неправильно подписан, и, вероятно, также не будет выполняться последнее требование — исполнение из надежного каталога\директории.

Требование 3: Исполнение из надежного каталога\директории

Последнее требование для получения «автоматического» повышения привилегий заключается в том, что целевой исполняемый файл находится в «доверенном каталоге», например «C: \ Windows\System32». На Рисунке 3 показано, что служба AIS выполняет эту проверку пути с запросом на повышение, в этом случае одним из путей, считающихся «доверенным», является «C:\Windows\System32».

Рисунок 3



Название этой статьи «Обход контроля учетных записей (UAC) путем пародирования доверенных директорий», поэтому Вы, вероятно, сможете легко догадаться, что будет дальше.

Обход UAC

Как упоминалось ранее в разделе UAC Primer, автопривилегированность (обход UAC) будет выполняться для исполняемых файлов, которые:

  1. Сконфигурированы для получения «автоматического» повышения привилегий
  2. Правильно подписаны
  3. Запускаются из надежного каталога («C:\Windows\System32»)

Appinfo.dll (AIS) использует API RtlPrefixUnicodeString, чтобы проверить, соответствует ли исполняемый путь файла с «C:\Windows\System32\» для проверки одного из доверенных каталогов. Это довольно железобетонная проверка, учитывая ее сравнение с каноническим местом расположения файла.

Поэтому, для организации обхода этой проверки я создаю каталог под названием «C:\Windows \» (обратите внимание на пробел после «Windows»). Конечно, с помощью этого действия все еще нельзя пройти проверку RtlPrefixUnicodeString, и я также упомяну, что это несколько недопустимое (или, по крайней мере, «недружелюбное») имя каталога, поскольку Windows не разрешает ставить пробелы в конце имени при создании каталога (попробуйте).

Однако, используя API CreateDirectory и добавив «\\? \» к имени каталога, которое я хочу создать, мы можем обойти некоторые из этих правил фильтрации имен и отправить запрос на создание каталога непосредственно в файловую систему.



Это приводит к созданию неудобного каталога, который счастливо сосуществует в файловой системе наряду с реальным «C:\Windows\» (за исключением тех случаев, когда Вы пытаетесь что-либо сделать с ним в Проводнике Windows).



Теперь, когда у нас есть каталог «C: \Windows \», мы можем создать в нем каталог «System32» и скопировать туда один из подписанных, исполняемых файлов (у которого разрешено системой «автоматическое» повышение привилегий) из реального каталога «C:\Windows\System32».
Для этого я скопировал «winSAT.exe» (один из файлов в белом списков исполняемых файлов Windows с разрешённом системой возможности «автоматического» повышения привилегий).
Когда мы попытаемся запустить этот файл из нашего нового каталога «C:\Windows \System32\ winSAT.exe», он будет проходить через следующие API (см. Рис. 6) в appinfo.dll перед выполнением проверки доверенного каталога. Это важно, и основа того, почему этот обход работает.

Рисунок 6



Когда этот неудобный путь с пробелом отправляется в AIS для запроса на повышение привилегий, путь передается в GetLongPathNameW, который преобразует его обратно в «C:\Windows\System32\winSAT.exe» (пробел удален).

Отлично!

Теперь это строка, в которой прошла проверка достоверного каталога (используя RtlPrefixUnicodeString) для остальной части проверки.

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

Это позволяет пройти все другие проверки и приводит к тому, что appinfo.dll принимает мою копию winSAT.exe как с «автоматическим» повышением привилегий (так как она правильно подписана и добавлена в белый список для «автоматического» повышения привилегий).

Чтобы на самом деле использовать вредоносный код, я просто скопировал поддельную WINMM.dll (импортированную winSAT.exe) в своем текущем каталоге «C:\Windows \System32\» для подмены локальной dll. Полную концепцию можно увидеть на рисунке ниже.

Рисунок 7.



Ссылка на Github
Поделиться публикацией
Комментарии 17
    +2
    Вот поэтому и не надо сидеть из-под админа.

    Интересно, а этот трюк с файловыми путями можно использовать, чтобы обойти белый список в SRP?
      +1
      Ползунок настроек UAC имеет 4 позиции (по крайней мере в восьмерке, в десятке не знаю как): от 'Never notify' до 'Always notify'. Единственное положение, которое гарантирует (насколько это может быть прогарантировано by Microsoft), что предупреждение UAC будет выдаваться всегда и всем (в т.ч. и учетке админа) не зависимо ни от чего (и поэтому не подвержено способам обхода через доверенные приложения/пути) это крайнее верхнее — 'Always notify'. И это единственный, имеющий более-менее реальную защитную силу (и соответственно смысл), вариант настройки UAC.
        0
        Не работает этот POC — winmm.dll грузится из доверенного каталога, а не из нашего
        Пруф (результат listdll.exe)
        Заголовок спойлера
        — WinSAT.exe pid: 17480
        Command line: «C:\Windows \System32\WinSAT.exe» formal

        Base Size Path
        0x0000000092270000 0x2c5000 C:\Windows \System32\WinSAT.exe
        0x00000000e0e30000 0x1e0000 C:\WINDOWS\SYSTEM32\ntdll.dll
        0x00000000df1a0000 0xae000 C:\WINDOWS\System32\KERNEL32.DLL
        0x00000000dda70000 0x266000 C:\WINDOWS\System32\KERNELBASE.dll
        0x00000000deda0000 0xa1000 C:\WINDOWS\System32\ADVAPI32.dll
        0x00000000e0d30000 0x9d000 C:\WINDOWS\System32\msvcrt.dll
        0x00000000de8f0000 0x5b000 C:\WINDOWS\System32\sechost.dll
        0x00000000de330000 0x11f000 C:\WINDOWS\System32\RPCRT4.dll
        0x00000000e0be0000 0xc5000 C:\WINDOWS\System32\OLEAUT32.dll
        0x00000000dd230000 0x9b000 C:\WINDOWS\System32\msvcp_win.dll
        0x00000000dde30000 0xf6000 C:\WINDOWS\System32\ucrtbase.dll
        0x00000000de450000 0x308000 C:\WINDOWS\System32\combase.dll
        0x00000000ddd00000 0x72000 C:\WINDOWS\System32\bcryptPrimitives.dll
        0x00000000df050000 0x149000 C:\WINDOWS\System32\ole32.dll
        0x00000000de300000 0x28000 C:\WINDOWS\System32\GDI32.dll
        0x00000000ddf90000 0x193000 C:\WINDOWS\System32\gdi32full.dll
        0x00000000de760000 0x18f000 C:\WINDOWS\System32\USER32.dll
        0x00000000ddce0000 0x20000 C:\WINDOWS\System32\win32u.dll
        0x00000000df300000 0x1436000 C:\WINDOWS\System32\SHELL32.dll
        0x00000000dda20000 0x4a000 C:\WINDOWS\System32\cfgmgr32.dll
        0x00000000d1af0000 0xa000 C:\WINDOWS\SYSTEM32\VERSION.dll
        0x00000000df250000 0xa6000 C:\WINDOWS\System32\shcore.dll
        0x00000000db000000 0x23000 C:\WINDOWS\SYSTEM32\WINMM.dll

        А вот сам exe файл, как ни странно, стартует из нашего.
        Но я попробовал WinSAT.exe поменять (всего пару байт).
        И вот что получилось:
        Скрытый текст


        Так что UAC жив. Автор, пиши ещё.
          +2
          Но я попробовал WinSAT.exe поменять (всего пару байт).
          И вот что получилось:

          Потому что нарушилось «Требование 2» касательно подписи.
            +2
            Проделал всё точно как в статье и заработало!
            Не работает, только если перевести полозок UAC в самый верх.
            По умолчанию он стоит на 3ем делении на котором UAC обходится.
            Заголовок спойлера


            Проделал при неизменной WinSAT и на своей winmm.dll
            (с сохранением таблицы экспорта конечно же, иначе exe не загрузится)
            В своей DLL написал
            #include <windows.h>
            int DllMain(void* hInst,int dwReason,void* lpReserved)
            {
               WinExec("cmd.exe /c reg query HKU\\S-1-5-19 > %temp%\\test.txt", 1);
               exit(0);
            }
            

            И получил в TEMP файл test.txt что говорит о том, что UAC пройден
            HKEY_USERS\S-1-5-19\AppEvents
            HKEY_USERS\S-1-5-19\Console
            HKEY_USERS\S-1-5-19\Control Panel
            HKEY_USERS\S-1-5-19\Environment
            HKEY_USERS\S-1-5-19\EUDC
            HKEY_USERS\S-1-5-19\Keyboard Layout
            HKEY_USERS\S-1-5-19\Software
            HKEY_USERS\S-1-5-19\System
            

            SID: S-1-5-19
            Название: Администратор NT
            Описание: Локальная служба
          0
          Не работает этот POC — winmm.dll грузится из доверенного каталога, а не из нашего

          Подозреваю, что есть способ перенаправить на нужную нам dll (dll hell).
            0

            Может все же не "пародирования", а имитации?

              0
              Да вообще весь перевод какой-то углепластиковый, даже подмена DLL превратилась в «захват».
              +1
              Вещь рабочая, но нужно чтобы фейковая DLL экспортировала некоторые функции, иначе доверенное приложение падает с ошибкой. Причем, эти функции отличаются от системы к системе, и то, что у меня сработало на 10х86 (импорт 2 функций), упало на 7х86 (там импорт 3 функций + 1 динамически, глубоко не копал). Надо или делать полноценную проксирующую winmm.dll, или брать другой способ.

              Но сама идея интересная, конечно.
                +2
                Зачем проксирующую? Можно сделать
                dumpbin winmm.dll /exports

                и далее все 180 функций оформить как пустые
                void CloseDriver(void) {}
                void DefDriverProc(void) {}
                void DriverCallback(void) {}
                void DrvGetModuleHandle(void) {}
                void GetDriverModuleHandle(void) {}
                void OpenDriver(void) {}
                ...

                этого будет достаточно, чтобы winmm.dll подгрузилась в адресное пространство, ну а после загрузки, вызываем что нам надо и сразу делаем exit(0) см код для DllMain в сообщении выше — это я к тому, что функционал проксирования нам неинтересен, достаточно только загрузки с нужными правами
                  0
                  кстати, версия с экспортом всех функций опробована на Windows 7, 8.1, 10 — работает везде
                  0
                  А откуда берется доверенный путь c:\windows\system32? из реестра? из переменных окружения? захардкожено? я точно помню winxp и win2k можно было устанавливать на любой раздел, в каталог с любым именем (например windows -> w, program files -> pf), и проблемы могли возникнуть только у стороннего софта типа corel который наивно искал что то там в c:
                  Теперь такое в принципе не возможно?

                  p.s. <эмоции> сравнение строки с полным путем зачем то парсится по каталогам, затем от туда удаляются пробелы и черт его знает еще, собирается заново и уже потом сравнивается?
                  запуск подписанного приложения, которое использует не подписанную библиотеку? о какой безопасности вообще может тут идти речь?
                    0
                    Вроде как и сейчас можно установить куда угодно, но выше «семерки» я не пробовал. Дальше — с переменных окружения берутся пути.
                    запуск подписанного приложения, которое использует не подписанную библиотеку?

                    Как бы библиотека запускается из доверенной директории (по логике вещей). А вообще, все эти «обходы UAC» не являются особой дырой в безопасности, ведь они работают только от админского профиля. В линуксе ведь никто не сидит от root'a, а в винде почему-то это в порядке вещей.
                      +1
                      Нет, в linux большинство сидит в том пользователе-администраторе, который создан по умолчанию, и так же повышают его привилегии с помощью sudo при администрировании.

                      Просто по умолчанию, sudo запрашивает пароль, а в windows только окно предупреждение, кстати с очень скудной информацией (нет путей к запускаемому приложению).
                    0
                    кстати с очень скудной информацией (нет путей к запускаемому приложению).

                    Справедливости ради, путь там таки есть, просто он скрыт по умолчанию (в моей Win7 нужно нажать «развернуть», чтобы увидеть полный путь с аргументами).
                    А так да, видно только имя приложения и издатель. Чем и пользуются вирусописатели, запуская свои поделия через wmi, cmd или еще как нибудь. Полного пути не видно — юзер видит доверенный майкросовский софт и жмет «да».

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое