长亭百川云 - 文章详情

Kerberos AS-REQ 之用户枚举

n1nty

58

2024-07-15

(360 A-TEAM 长期招收高级安全研究人员,APT 攻防人员,请联系 wufangdong@360.net


国外有文章在去年讲到了 Kerberos 账号枚举的技巧,同时提供了 Java 编写的一个枚举工具,nmap 也带有一个 NSE 脚本来实现了同样的功能。国内也有安全媒体翻译过。

https://www.attackdebris.com/?p=311

我在这里简单介绍一下一些与 Kerberos 账号枚举相关联的知识,以及我自己用 Python 实现的 Kerberos 账号枚举工具。编写这个工具本身并没有什么难度,只是为了简单练习一下自己对 Kerberos 协议的理解。

背景知识简述

Kerberos 的三个子协议:

  1. AS-REQ 与 AS-REP

  2. TGS-REQ 与 TGS-REP

  3. AP-REQ 与 AP-REP

Kerberos 账号枚举利用到的是 AS-REQ 与 AS-REP。

AS-REQ 与 AS-REP 简述

Kerberos 是基于票据的协议,访问任何使用 Kerberos 进行身份验证的服务,都需要你提供一张能够证明你身份的票据。所有的票据都是由 KDC 发布的,而你应该获取的第一张票据是一张被称为 TGT 的票,这个票代表着你的身份。

我们可以通过发送 AS-REQ 请求,来向 KDC 申请一张 TGT。KDC 对我们的 AS-REQ 请求进行的响应被称为 AS-REP,而 TGT 也包含在这个 AS-REP 响应里面。

Pre-Authentication 与 Authenticator 简述

在我们利用 AS-REQ 向 KDC 申请代表我们身份的 TGT 的时候,我们需要: 

  1. AS-REQ 的 cname 字段处写上我们的用户名(比如说 n1nty)

  2. 一般情况下,我们还需要在 AS-REQ 的 padata 字段处填上一段数据,这段数据被称为 authenticator,用于向 KDC 证明,我们知道 n1nty 这个账号的密码。 如果我们填写了 padata,则说明我们希望进行 pre authentication,如果没有填,说明我们不希望进行 pre authentication。

在 Kerberos 的设计中,padata 这个字段的值是可选的。如果我们不填写 padata,那么意思就是我们希望 KDC 能够将 n1nty 这个账号的 TGT 返回给我们,即使我们没有向 KDC 证明我们知道这个账号的密码。

看到这里是不是感觉有问题,我们不需要向 KDC 证明我们知道目标账号的密码就可以随意获取目标账号的 TGT?其实是没有问题的,因为:

  1.  这是可配置的。在微软对 Kerberos 的实现中,所有的账号默认都是强制要求我们进行 Pre authentication 的。也就是默认情况下所有账号都要求我们在提供 authenticator 后,才能给我们返回 TGT。当然你可以针对某些账号来进行单独的设置,允许在不提供 authenticator 的情况下从 KDC 申请这些账号的 TGT,如下图:

  2. 就算你在不提供 Authenticator 的情况下拿到了那些不要求进行 Pre authentication 的账号的 TGT,在不知道目标账号的密码的情况下,你是无法从 AS-REP 响应里面解密与 TGT 相关联的 session key的,导致你最终依然无法使用这张 TGT。

    但是这也确实造成了另一个问题,也就是 TGT 离线爆破。

    https://social.technet.microsoft.com/wiki/contents/articles/23559.kerberos-pre-authentication-why-it-should-not-be-disabled.aspx

    另一个与 TGT 的离线爆破很相似的一种攻击方式被称为 Kerberoast,Kerberoast 是对 TGS-REP 响应的离线爆破,用于爆破服务启动账号的密码。而 TGT 离线爆破是针对 AS-REP 响应进行的的离线爆破。

账号枚举的原理

原理其实很简单,我们可以向 KDC 发送 AS-REQ ,AS-REQ 里面包含我们想要判断的账号比如 n1nty,同时我们不进行 pre authentication,也就是我们不在 padata 字段里面提供 authenticator。此时,根据 KDC 的响应,我们能做出以下判断:

  1.  如果 KDC 给出的是 KRB_ERROR 响应,且 error-code 为 UNKNOWN_PRINCIPLE,则说明 n1nty 账号不存在

  2.  如果 KDC 给出的是 KRB_ERROR 响应,且 error-code 为 PREAUTH-REQUIRED,则说明目标账号是存在的,但是因为我们没有提供 authenticator,所以导致出现了错误

  3. 如果 KDC 给出的是 KRB_ERROR 响应,且 error-code 为 CLIENT_REVOKED,则说明账号存在,但是账号被禁用了

  4. 如果 KDC 给出的是 AS-REP 响应,则说明账号存在,并且账号关闭了 pre authentication,此时我们应该可以直接从 AS-REP 响应中获取到代表着 n1nty 这个账号的 TGT

KerberosUserEnum

我用 Python 编写了一个小工具来实现 Kerberos 账号的枚举。

https://github.com/360-A-Team/KerberosUserEnum

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2