草庐IT

内网安全——Kerberos协议详细全解

王志德发 2023-04-08 原文


参考链接:
https://www.freebuf.com/articles/web/341103.html
https://www.freebuf.com/articles/system/343451.html

Kerberos协议

Kerberos是一种计算机网络认证协议,它允许某实体在非安全网络环境下通信,向另一个实体以一种安全的方式证明自己的身份。它也指由麻省理工实现此协议,并发布的一套免费软件。它的设计主要针对客户-服务器模型,并提供了一系列交互认证——用户和服务器都能验证对方的身份。Kerberos协议可以保护网络实体免受窃听和重复攻击。

在网络的各种认证中随时都有可能存在中间人攻击的情况,Kerberos协议设计之初便考虑到了这个问题,所以Kerberos协议的整个认证过程实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求整个网络中每台主机都是安全的,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。在以上情况下, Kerberos作为一种可信任的第三方认证服务,是通过传统的密码技术(如:共享密钥)执行认证服务的。

在这种方式下让Kerberos的整个认证过程中不用担心受到中间人攻击。

关键词理解

DC

DC(Domain Controller):域控制器,是域中一台拥有最高管理权限的计算机,一个域内可以有多台域控制器,每一个域控制器的地位几乎是平等的,有几乎相同的数据库,如果有多台域控制器,当在其中一台域控制器添加一个用户账号,其他域控制器也会自动同步添加。
域控制器管理着整个域中所有主机,当域内主机需要互相通信必须经过域控制器审核通过才行。
通常情况下域控制器会和DNS服务器部署在同一台主机上,在内网渗透中可以通过DNS服务器来定位域控。

AD

AD(Active Directory):活动目录是Windows Server的目录服务。

在庞大的网络环境中存在着各种资源,网络中的各种对象:用户、用户组、计算机、域、组织单位以及安全策略等等,肯定需要存在到一个合理的位置便于管理,这个位置就是活动目录数据库,也就是AD。有了AD存储网络对象的信息,管理员和用户能够轻松地查找和使用这些信息。

活动目录AD主要提供的功能如下:

①服务器及客户端计算机管理:管理服务器及客户端计算机账户,所有服务器及客户端计算机加入域管理并实施组策略。
②用户服务:管理用户域账户、用户信息、企业通讯录(与电子邮件系统集成)、用户组管理、用户身份认证、用户授权管理等,按省实施组管理策略。
③资源管理:管理打印机、文件共享服务等网络资源。
④桌面配置:系统管理员可以集中的配置各种桌面配置策略,如:用户使用域中资源权限限制、界面功能的限制、应用程序执行特征限制、网络连接限制、安全配置限制等。
⑤应用系统支撑:支持财务、人事、电子邮件、企业信息门户、办公自动化)、补丁管理、防病毒系统等各种应用系统。

Kerberos认证中就需要通过查询AD中数据来判断发出请求的客户端是否合法。

这个存储了这么多数据的数据库肯定需要部署到域内的一台主机上,这台主机就是DC(域控制器),所以在一般情况下如果一台主机安装了AD,那么它就是DC。

KDC

KDC(Key Distributed Centre):秘钥分发中心是一种运行在物理安全服务器上的服务,是负责颁发凭证的Kerberos组件,这些凭证是使用KDC数据库中存储的信息创建的。KDC也是默认安装在域控中。包含了AS和TGS。
1. AS(Authentication Server):身份验证服务,为Client生成TGT的服务
2. TGS(Ticket GrantingServer):票证发放服务器,通过你的TGT来发放ST,为Client生成某个服务的Ticket。

Ticket & TGT

Ticket :票据,是网络对象互相访问的凭证。
TGT(Ticket Granting Ticket):票据授权票据,通过票据授权票据可以获得一个票据,类似临时凭证。
ST(Service Ticket):服务票据

Client:访问特定资源的客户

Server:拥有特定资源的服务器

特定账号

krbtgt是KDC的账号,密码是随机生成的,无法登陆可以使用以下语句查询

net user krbtgt

net user 账户名

​Kerberos认证流程

KDC存着所有用户的账号和密码

Client与AS的交互

双向认证,AS确认客户不是伪造的客户,客户确认AS不是伪造的AS客户把自己个人信息发给AS,AS验证客户ID是不是在自己的KDC数据库中AS检查到老铁没毛病,然后随机生成一个TGS-SessionKey AS再给客户发送两个宝物:

  1. 用客户的NTML HASH加密TGS-SessionKey之后,发送给客户

  2. AS将客户个人信息(客户ID,需要访问的服务ID,IP地址,时间戳,存活时间和TGS-SessionKey)用TGS(krbtgt)的密钥加密打包成一个TGT发给客户
    (Client向DC发出访问Server的请求,DC收到请求后AS通过AD来判断Client是否可信;当验证通过,AS生成TGT返回给Client。)

Client与TGS的交互

第二次交流,客户将第一次交流的TGT完好的送给了TGS,同时还有用TGS-SessionKey加密的Authenticator(包含了客户ID和时间戳)

TGS利用自己的密钥解密TGT,获取TGT解密出来的TGS-SessionKey,然后用TGS-SessionKey去解密加密过的Authenticator,从而得到客户ID,然后比对一下Authenticator中的客户ID和TGT中的客户ID是否相等,比较来自 Authenticator 的时间戳和TGT的时间戳 (典型的Kerberos系统的容忍度是2分钟,但也可以另行配置),检查TGT有没有过期(通过TGT中的存活时间),检查Authenticator是否已经在TGS的缓存中(不检查TGS缓存的话,那么如果TGS缓存中有Authenticator,会导致刷新TGS缓冲中的Authenticator,从而篡改客户ID和时间戳,导致重放攻击),所有检查过了之后,TGS随机生成一个Key(包含了客户ID和时间戳),用于加密后续客户和服务的通信数据,这个key就是Service-SessionKey,将这个Service-SessionKey用TGS-SessionKey加密,以及将客户ID、服务ID、IP地址、时间戳、存活时间和TGS-SessionKey用服务的密钥加密打包成ST(服务票据),然后将这两个发给客户
(Client拥有了TGT,继续向DC发出访问Server的请求(带有TGT),此时TGS通过TGT判断Client具有访问权限,TGS将具有访问Server权限的Ticket发送给Client。)

Client与Service的交互

客户将ST以及使用Service-SessionKey加密的个人信息Authenticator(包含客户ID和时间戳)发送给Service,然后Service利用自身密钥解密出ST,然后用ST中的Service-SessionKey去解密加密的Authenticator获取他的客户ID,然后比较两个ID是否相等,比较来自 Authenticator 的时间戳和来自ST的时间戳 (典型的 Kerberos 系统对差异的容忍度是 2 分钟,但也可以另行配置),检查ST是否过期(根据ST里面的存活时间字段判断),检查 Authenticator 是否已经在对应服务的服务器的缓存中(为了避免重播攻击,前面说过了重播攻击)
(Client拥有了Ticket,可以访问Server,但是整个Ticket只针对找这一个Server有效,Client与Server建立连接开始通信。)

至此,所有的认证过程通过,客户端即可与远程服务完成了身份认证,可以进行后续的信息通信。

Kerberos认证分析

通过上面的Kerberos认证流程可发现,Kerberos认证过程可以大致分为三个阶段:

AS_REQ & AS_REP

TGS_REQ & TGS_REP

AP-REQ & AP-REP
下面利用Wireshark抓包具体分析一下每一个阶段:

测试环境:

域用户:admin
域名:axpmyw

在域成员主机上登录域用户admin,然后再利用Wireshark抓包。

AS_REQ & AS_REP

AS_REQ的数据包:

其中包括了Kerberos的版本,这里使用的是Kerberos V5;消息类型这里是krb-as-req。

这里使用了用户Hash(NTLM Hash)加密时间戳,在进行认证时,KDC中的AS服务收到请求,首先使用对应用户的Hash解密时间戳,如果不超过5分钟,那么说明数据包有效预认证通过。

这里启用了PAC,PAC的存在会使认证更加安全。
AS_REP的数据包:

返回的数据除了一些客户端信息、和服务端信息外,还有ticket和enc-part。

当预认证成功之后,AS会生成一个随机字符串,叫Session Key,然后使用客户端用户的Hash(NTLM Hash)加密Session Key。

KDC使用特定账户(krbtgt)的Hash(NTLM Hash)对Session Key、时间戳、客户端的信息进行加密生成TGT就是这里的ticket。

enc-part由krbtgt的Hash加密生成的,这里如果可以得到krbtgt的hash就可以伪造TGT,也就是伪造黄金票据。

Kerberos认证的第一阶段完成,总结一下第一阶段:

客服端某个用户想要访问域内某个服务,客户端的Kerberos 服务向DC的KDC发出AS_REQ认证请求,请求内容包括使用用户的NTLM-Hash加密的时间戳,客户端信息和服务端信息等。

当KDC收到请求,AS会请求AD验证此用户是否合法(是否在AD目录中),验证不通过认证失败;验证通过之后使用该用户的NTLM-Hash解密时间戳,如果时间戳超过5分钟,则认证失败,如果在5分钟以内,AS会生成一个Session Key并使用用户的NTLM-Hash加密Session Key。

同时会使用特定账户krbtgt账户的NTLM-Hash加密Session Key、时间戳、客户端的信息作为TGT,然后TGT和Session Key一并发送给客户端。TGT的到期时间为8小时,如果超过了8小时,不能之间进入下一步获取Ticket,想要进入下一阶段必须重新申请TGT。

TGS_REQ & TGS_REP

第一阶段中,使用用户的NTLM-Hash加密Session Key发送到客户端后,客户端可以使用对应的NTLM-Hash解密获得Session Key并缓存本地;TGT客户端是无法解密的,但是客户端可以和TGS通信。

TGS_REQ的数据包:

数据包中有第一阶段收到的TGT,这个TGT就是AS-REP里面获取到的TGT。Authenticator是使用Session key加密的客户端信息、服务端信息和时间戳。

这里的到期时间rebeus和kekeo都是20370913024805Z,可用于作为特征值检验用。

TGS_REP的数据包:

当TGS收到请求后,首先解密TGT,从TGT中获得Session Key,再使用Session Key解密Authenticator,然后通过解密的信息验证来自客户端的请求是否可信。

通过验证之后,TGS生成Server Session Key主要用于第三阶段和服务器进行通信;同时TGS生成Ticket,Ticket是使用该服务的NTML hash加密的Server Session Key、客户端信息、时间戳。

将Server Session Key使用Session Key加密然后和Ticket一起发送给客户端。

Kerberos认证的第二阶段完成,总结一下第二阶段:

客户端收到第一阶段的数据之后,使用对应的NTLM-Hash解密获得Session Key,然后将TGT和Session Key存入内存中,当需要访问服务时使用TGT来获取Ticket。

在第二阶段中,客户端将收到的TGT和使用Session Key加密的客户端信息、时间戳等数据一并发送给TGS。

这里存在的安全问题,如果此时的数据被攻击者窃取,因为有加密短时间内攻击者无法破解数据,时间戳的存在可以让KDC验证数据是否可信。

KDC收到TGT和其他数据后,首先解密TGT(只有KDC才能解密TGT),解密完成获得Session Key,再使用Session Key解密其他数据,然后将解密出来的数据和TGT解密出来的数据进行比较,从而验证数据是否可信。当验证通过,TGS会生成Server Session Key,然后使用Session Key加密Server Session Key。

同时使用该服务的NTML hash加密的Server Session Key、客户端信息、时间戳生成最后的Ticket。KDC会将使用Session Key加密Server Session Key和Ticket一并发送给客户端。客户端收到数据之后就可以和服务端通信了。

AP-REQ & AP-REP

第三阶段客户端开始和服务端进行通信。

客户端收到Ticket和其他数据后首先解密Session Key加密的Server Session Key得到Server Session Key并缓存本地,客户端无法解密Ticket,但是可以使用这个Ticket。

为了安全考虑,Kerberos协议还支持双向验证,即只有客户端和服务端互相都认证通过,确认对方身份之后才会建立起通信连接。实际进行访问时,如果客户端需要认证访问的服务端是否可信,客户端可以在发送的请求中设置是否需要双向认证的标志位。

这里的认证过程是双向认证:

1、服务端验证客户端:防止非法用户操作

当需要访问服务时,客户端将Ticket和使用Server Session Key加密的客户端信息和时间戳发送给服务端。

服务端收到客户端的请求,使用该服务的NTML hash解密Ticket,得到Server Session Key,再使用Server Session Key解密其他数据,然后将解密出来的数据和Ticket解密出来的数据进行比较,验证通过后,因为启用了PAC,服务端会将PAC发送给DC询问此用户是否有访问权限。DC收到PAC后会解密PAC,然后通过PAC中的SID判断用户信息、用户权限等,最后将结果返回到服务端。这里如果设置了ACL,服务端还会判断ACL有没有限制用户请求的服务,全部通过后服务端成功验证客户端。

2、客户端验证服务端:防止误入恶意服务

服务端将使用Server Session Key加密的客户端信息和时间戳(这里的时间戳是第三阶段客服端发送给服务端的时间戳)发送给客户端,客户端使用Server Session Key解密数据,解密成功之后客户端将时间戳和原来发送的时间戳进行对比,如果一致则客户端成功认证服务端。

Kerberos认证的第三阶段完成,Kerberos认证完成,客户端和服务端建立通信。

PAC

PAC(Privilege Attribute Certificate,特权属性证书),是为了区分不同权限的客户。

PAC包含两个数字签名PAC_SERVER_CHECKSUM和PAC_PRIVSVR_CHECKSUM,以及客户的sid和客户所在的组,第一个PAC_SERVER_CHECKSUM是由服务的NTLM HASH加密的,第二个PAC_PRIVSVR_CHECKSUM是由KDC(krbtgt)的NTLM HASH加密的

当没有使用PAC时,通过Kerberos的认证过程可以知,在第三阶段服务端成功解密Ticket,认证成功就会允许客户端开始访问服务端。

虽然看起来整个过程没有什么问题,但是因为没有PAC也就是服务端不会再次向DC确认用户是否有访问权限。这里就存在了一个安全问题,任何一个用户只要有了Ticket就可以访问服务。

微软为了解决这个问题就引入了PAC,改进了Kerberos认证过程。

在第一阶段,KDC发送给客户端的TGT中就包含了PAC,PAC中有用户的SID、用户所在的组。
在第三阶段,服务端解密Ticket验证通过后,还会将PAC发送给DC询问此用户是否有访问权限。

并且PAC在整个认证过程是不可见的,只有KDC可以制作和查看PAC,可见有了PAC的存在,使整个认证过程更加安全。

如果有些服务没有验证PAC,就说明只要用户拥有了Ticket,就可访问服务,这就是白银票据可以成功的前题。

PAC在第一步过程中被放在TGT中,然后返回给客户,然后在第二步过程中客户发送自己的TGT给TGS,TGS会验证PAC(其实就是验证两个数字签名)是否被篡改,然后重新构造新的PAC放在ST中返回给客户,然后在第三步过程中将客户的ST发送给服务,让服务进行验证,服务用自身密钥解密ST后,然后用ST中的Service-SessionKey去解密加密的Authenticator获取他的客户ID,然后比较两个ID是否相等,比较来自 Authenticator 的时间戳和ST的时间戳 (典型的 Kerberos 系统对差异的容忍度是 2 分钟,但也可以另行配置),检查ST是否过期(根据ST里面的存活时间字段判断),检查 Authenticator 是否已经在对应服务的服务器的缓存中(为了避免重播攻击,前面说过了重播攻击),检查完毕后,服务为了判断客户是否有合法的权限,需要将客户的信息传递给KDC, KDC通过客户的信息判断客户所属的用户组信息, 用户权限等,然后KDC将结果返回给服务,服务利用结果(客户所属的用户组信息,用户权限等)与客户所索取的资源的ACL(Access Control List,权限控制列表,这个列表记录了哪个用户哪个用户组可以访问此资源)对比,判断客户是否有权限访问此资源。

黄金票据和白银票据

黄金票据

黄金票据的原理就是,用krbtgt的NTLM HASH(也就是krbtgt的密码(密钥))来伪造TGT的内容。更改里面的ClientID参数与TGS-SessionKey等。让TGS以为我就是那个我所声称的人,当然我一般会声称自己是administrator

前提是:拥有krbtgt的NTLM HASH或者明文密码

白银票据

白银票据的原理就是伪造ST(Service Ticket,服务票据)。伪造ST的核心点是能够得到目标服务的服务器的NTLM HASH(也就是对应资源服务器的密码(密钥))

前提是:拥有目标服务的服务器的NTLM HASH或者明文密码

SPN攻击

SPN(Service Principal name)服务器主体名称。 SPN是服务在使用Kerberos 身份验证的网络上的唯一标识符(说白了他是某某服务的id,用来标识他是谁)。它由服务类、主机名和端口组成。

SPN分为两种类型:
一种是注册在活动目录的机器帐户(Computers)下,当一个服务的权限为 Local System 或 Network Service,则SPN注册在机器帐户(Computers)下。

域中的每个机器都会注册两个2个SPN:HOST/用户名和HOST/用户名.域名

比如:

另一种是注册在活动目录的域用户帐户(Users)下,当一个服务的权限为一个域用户,则SPN注册在域用户帐户(Users)下。

SPN格式:

/:/

  1. :标识服务类的字符串
  2. :服务所在主机名称
  3. :服务端口(存在一个实例且有默认端口可省略)
  4. :服务名称(可省略)

例如:MySQL/DC.china.com/MySQL

SPN攻击就是找到那个“主人”是krbtgt的服务器(一般那台服务器为域控)。这样子就可以去请求到用krbtgt的NTML HASH加密的TGT了。这个TGT加密的内容有客户ID,需要访问的服务ID,客户IP地址,时间戳,存活时间和TGS-SessionKey 。这时候可以用暴力破解技术来破解这个TGT,破解结果中有客户的相关信息,即可算作破解成功。进而得到krbtgt的密码,可以做黄金票据拿下整个域环境。

有关内网安全——Kerberos协议详细全解的更多相关文章

  1. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  2. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  3. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  4. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  5. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  6. ruby-on-rails - 安全地显示使用回形针 gem 上传的图像 - 2

    默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同

  7. ruby - 使写入文件线程安全 - 2

    我在一个ruby​​文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}

  8. ruby - HTTP POST 上的 SSL 错误(未知协议(protocol)) - 2

    尝试通过SSL连接到ImgurAPI时出现错误。这是代码和错误:API_URI=URI.parse('https://api.imgur.com')API_PUBLIC_KEY='Client-ID--'ENDPOINTS={:image=>'/3/image',:gallery=>'/3/gallery'}#Public:Uploadanimage##args-Theimagepathfortheimagetoupload#defupload(image_path)http=Net::HTTP.new(API_URI.host)http.use_ssl=truehttp.verify

  9. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

  10. ruby-on-rails - 最灵活的 Rails 密码安全实现 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭8年前。Improvethisquestion我需要实现具有各种灵活需求的密码安全。这些要求基本上取自Sanspasswordpolicy:Strongpasswordshavethefollowingcharacteristics:Containatleastthreeofthe

随机推荐