【域渗透】域用户枚举

admin 2022年7月8日04:49:12评论18 views字数 3791阅读12分38秒阅读模式

0x00 前言

我们有时候可能会遇到这样的环境:通过钓鱼或其他手段进入目标的内网,所处机器权限为工作组环境。通过内网存活探测,发现存在域环境,但当前没有用户凭证,域内个人机清一色 Win 10+,后续成功定位到域控及 ADCS。但是,针对域控无凭证利用的 ZeroLogin 漏洞已经被修复了。那么有朋友跳出来说,中继呢?说实话,除了 PetitPotam 不需要凭证,其他强认证工具是需要带上凭证的。经过测试,不知道是不是域控无法到达我们当前所在段还是被修复了(2022年初被修复)。那么又有朋友说了,那打域控同段啊,嗯嗯嗯,大佬说得对,只是条件有限,小弟打不下来而已。

那么接下来怎么办呢?首先,得先搞一个域凭证(当然,这不是绝对的),后续用于 ADCS 漏洞及其他 AD 域漏洞利用。那么该怎么搞用户凭证呢?这也是本篇文章要说的,思路也很简单,首先肯定要找域用户名,才能进行密码爆破。那么怎么找域用户名呢?如果目标存在邮件服务还好说,直接爬公网能爬到的邮箱,再进行用户名的验证。既然已经收集到了邮箱,为什么还需要验证用户名呢?这还要问的吗?嗯?那还不是因为它不是 Exchange 的缘故吗,如果内网使用 ADDC,又不使用 Exchange,多半只是刚开始时同步了一次 LDAP,因此需要做用户名的验证。如果没有邮服,那只能字典了。

0x01 Kerberos 的 AS_REQ

了解 ADDC Kerberos 协议的同学都知道,关于 AD 域涉及服务的认证,都是通过 Kerberos 进行认证的(域内域外均由 Kerberos 完成)。而 Kerberos 的认证大概分为几个步骤:

1.不带预认证数据的 AS_REQ/Error;2.带预认证数据的 AS_REQ/AS_REP;3.TGS_REQ/TGS_REP;

下面使用 Wireshark 抓取用户登录的流量包进行分析。

1.1 第一个 AS_REQ

我们重点来看第一个 AS_REQ 请求,抓取的流量包如下所示:

【域渗透】域用户枚举
image.png

这就是一个正常的请求包,具体内容如下所示:


                  pvnoKerberos 协议版本号 (5)               msg-type:应用程序类标记号 (10),简单来说就是消息类型                padata:仅包含 PA-PAC-REQUEST 结构的预认证数据           kdc-options:票据请求的标志(可转发、可更新、规范化、可再生)                 cname:包含被认证的用户名                 realm:域名                 sname:请求的服务名称                  till:请求的票据的到期时间                 rtime:如果请求的是可更新的票据,则该字段包含票据所需的过期时间                 nonce:消息随机数                 etype:请求的加密类型             addresses:客户端地址

1.2 KRB Error

接下来我们来看它的返回:

【域渗透】域用户枚举
image.png

从返回的错误数据包可以得到以下信息:


该用户需要“预认证”,并在请求中未找到所需 "paddata"。请求的用户在 DC 中存在,并额外返回 "e-data"。

这里列出 3 个常见的错误:

错误 定义 错误代码
KRB5DC_ERR_PREAUTH_REQUIRED 需要额外的预认证,表示用户存在 25
KRB5DC_ERR_CLIENT_REVOKED 客户端凭证已被吊销,表示用户已被禁用



KRB5DC_ERR_C_PRINCIPAL_UNKNOWN 在 Kerberos 数据库中找不到客户端信息,表示用户不存在 6

[1]因此,如果要编写工具,我们在组装 Kerberos 数据包的时候,根据上面第一个 AS_REQ 进行组装,然后给 ADDC 进行发送,根据返回错误来判断用户是否存在于域内。

0x02 现有工具

现在有几个很成熟的工具,它们包括但不限于:

1.使用 Go 编写的 kerbrute[2]2.使用 Python 编写的 pyKerbrute[3];

在这里我只介绍 kerbrute 的用户枚举功能:

【域渗透】域用户枚举
image.png

不存在的用户,直接返回 KRB5DC_ERR_C_PRINCIPAL_UNKNOWN **错误。**


0x03 使用 Csharp 编写工具

至于我为什么要重新造轮子,那是因为关于内网渗透的工具我都是使用 C# 进行编写。除非能力不行,实现不了,否则在学习过后都会落地工具,达到知识 + 工具的落地。由于在 Kerberos 的请求及处理,Rubeus[4] 已经写得很好了,当前学习 Kerberos 时也是通过该源码进行学习的,因此在实现这个功能时,直接从 Rubeus 扣就行。

3.1 AS_REQ 结构

//AS-REQ          ::= [APPLICATION 10] KDC-REQ
//KDC-REQ ::= SEQUENCE {// -- NOTE: first tag is [1], not [0]// pvno [1] INTEGER (5) ,// msg-type [2] INTEGER (10 -- AS),// padata [3] SEQUENCE OF PA-DATA OPTIONAL// -- NOTE: not empty --,// req-body [4] KDC-REQ-BODY//}

使用 C# 表示为:

public calss AS_REQ(){    public long pvno = 5;    public long msg_type = 10;    public PA_DATA padata;    public KDCReqBody req_body;}

3.1.1 PA-DATA 结构

其中,padata 的结构固定为:

public PA_DATA(){    public long type = 128;    // 固定值为:0x30, 0x05, 0xa0, 0x03, 0x01, 0x01, 0x01    public Object value = new KERB_PA_PAC_REQUEST()     {        public bool include_pac = true;    };}

3.1.2 REQ-BODY 结构

KDC-REQ-BODY::= SEQUENCE {    kdc-options[0] KDCOptions,    cname[1] PrincipalName OPTIONAL                                -- Used only in AS-REQ --,    realm[2] Realm                                -- Server's realm                                -- Also client's in AS-REQ --,    sname[3] PrincipalName OPTIONAL,    from[4] KerberosTime OPTIONAL,    till[5] KerberosTime,    rtime[6] KerberosTime OPTIONAL,    nonce[7] UInt32,            etype[8] SEQUENCE OF Int32 -- EncryptionType                                        -- in preference order --,            addresses[9] HostAddresses OPTIONAL,    enc-authorization-data[10] EncryptedData OPTIONAL                                        -- AuthorizationData --,            additional-tickets[11] SEQUENCE OF Ticket OPTIONAL                                            -- NOTE: not empty}

使用 C# 表示为:

public KDCReqBody(string domain, string user){    public uint kdc-options = 40810010; // FORWARDABLE(0x40000000) | RENEWABLE(0x00800000) | CANONICALIZE(0x00010000) | RENEWABLEOK(0x00000010)    public PrincipalName cname = new PrincipalName()    {        public long name_type = 1;        public List<string> cname_string = new byte[]{ user }; // 用户名    }    public string realm = domain; // 域名    public PrincipalName sname = new PrincipalName()    {        public long name_type = 2;        public List<string> sname_string = new byte[]{"krbtgt", domain};    }
public DateTime till = ; public DateTime rtime = ; public uint nonce = 123456; // 随机数 public List<T> etypes = new List<T>(); public HostAddress addresses = new HostAddress();}

效果如下所示:

【域渗透】域用户枚举
image.png

相关源码我已经放在星球里了。有能力的同学自己扣扣就好了,很简单的。


0x04 总结

要完成爆破,那么肯定是需要先找到用户名,才拥有爆破的基础条件。至此,获取域内凭证的第一步就这样完成了。接下来就是爆破密码了、

【域渗透】域用户枚举

References

[1] : https://blog.csdn.net/m0_57221101/article/details/124172466
[2] kerbrute: https://github.com/ropnop/kerbrute/releases
[3] pyKerbrute: https://github.com/3gstudent/pyKerbrute
[4] Rubeus: https://github.com/GhostPack/Rubeus

原文始发于微信公众号(RowTeam):【域渗透】域用户枚举

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月8日04:49:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【域渗透】域用户枚举http://cn-sec.com/archives/1164306.html

发表评论

匿名网友 填写信息