kerberos协议&&NTLM认证学习

kerberos协议学习

该协议涉及的攻击手段如下
image.png
理解协议过程所画的草稿图
aa84c82a24cfea51641782fb3471b4e.jpg
鉴于我画的图丑晕了,于是在笔记中还是使用别人的图吧

未引入TGS前的认证流程

image.png
客户端向KDC发起对sessionkey的请求,KDC使用数据库中存储的该客户端的密码对sessionkey进行加密,同时向客户端请求的服务器发送同样的sessionkey,但使用服务器端的密码进行加密,然后客户端再使用sessionkey向服务器进行认证

在这个流程中我们可以发现一些问题
1.A向KDC申请sessionkey,KDC同时向A和B发送sessionkey,如果由于网络等原因导致B在A向它请求认证时还没有收到sessionkey就会导致认证失败,所以可以尝试在返回给A使用client password加密的sessionkey的时候将本该发给B的信息一同发送给A,再由A向B请求验证的时候一同发送给B
2.A提出SessionKey的申请时,KDC凭什么就生成了SessionKey给了A,也就是说,KDC缺乏对A的认证,所以在分发SessionKey之前,KDC需要增加对A的认证,解决办法就是,将KDC机构分成两部分:

AS:Authentication Service,用于KDC对A的认证
TGS:Ticket Granting Service,用于KDC向A和B分发Session Key

引入TGS后的认证流程

image.png
这个图也就很好的表明了将KDC分为AS和TGS后的作用,也就解决了刚才未引入TGS前我们提出的问题1和2,对于2的解决是只有当确认了A的身份后,才会给sessionkey(a-b)

总体来说就是当client想要访问server上的某个服务时,需要先向AS证明自己的身份,验证通过后AS会发放一个TGT,client会再次向TGS证明自己的身份后,TGS会发放一个ST,随后client向server发起认证请求

详细认证过程

image.png
①:KRB_AS_REQ:Client-A发送Authenticator向KDC的AS服务认证自己的身份(通过提供自身密码加密的一个时间戳TimeStamp)

②:KRB_AS_REP:AS通过KDC数据库中存储的Client-A密码的副本,解密收到的Authenticator,如果解密出的TimeStamp符合要求,则AS服务认为Client-A就是所谓的Client-A。认证成功后,AS服务生成一个短期有效的SessionKeya-kdc,将该Key使用A的密码副本加密成密文1,另外将Key连同时间戳标志(控制该SessionKey的有效时间)通过TGS服务的密码也就是KDC的密码加密为密文2(称为TGT),将这两个密文组合成KRB_AS_REP返回给Client-A

③:KRB_TGS_REQ:Client-A在接收到KRB_AS_REP后,首先使用自身密码解密密文1得到SessionKeya-kdc,此时需要注意的是,密文2(TGT)是被KDC的密码加密的,所以Client-A无法解密,这也是Kerberos协议设计的精妙之处,既解决了Server端(TGS相对于Client-A也称之为Server端)无法及时接收SessionKey的问题,又不怕Client-A对该TGT的伪造,因为Client-A不知道Server端的密码

得到SessionKeya-kdc后,Client-A利用其加密时间戳生成Authenticator用于向TGS申请Client-A与Client-B进行认证所需的SessionKeya-b,连同刚才KRB_AS_REP接收的TGT一同组合成KRB_TGS_REQ发送给TGS

④:KRB_TGS_REP:TGS在接收到KRB_TGS_REQ之后,利用KDC密码解密TGT获得本来就该发送给自己的SessionKeya-kdc,然后用其解密KRB_TGS_REQ中的Authenticator得到Client-A发送过来的时间戳,如果时间戳符合要求,则生成一个短期有效的SessionKeya-b,注意此时利用SessionKeya-kdc将SessionKeya-b加密为密文1,然后利用Server-B的密码将SessionKeya-b加密为密文2(称为ServiceTicket),两个密文一同构成KRB_TGS_REP返回给Client-A

⑤:KRB_AP_REQ:Client-A在接收到KRB_TGS_REP之后,首先使用缓存的SessionKeya-kdc将密文1中的SessionKeya-b解密出来,然后利用其加密时间戳生成Authenticator用于向B进行对自身的验证,另外,和刚才TGT一样,密文2也就是ServiceTicket是用Server-B的密码加密的,所以Client-A无法解密,也就无法伪造,这也同样解决了在三方认证中作为Server端的B无法及时接收SessionKey的问题,又不怕Client-A对ServiceTicket的伪造

⑥:KRB_AP_REP:Server-B受到KRB_AP_REQ之后,利用自身密码解密ServiceTicket,得到SessionKeya-b,然后用SessionKeya-b解密Authenticator得到时间戳,验证A的身份

NTLM认证学习

系统版本对LM和NTLM的支持

image.png

NTLM 认证

简介

NTLM是NT LAN Manager的缩写,NTLM是指telnet的一种验证身份方式,即问询/应答身份验证协议

认证流程

进行一个嫌弃自己的字好丑
image.png

这就是我理解的并且画的流程图

  1. 用户登录客户端,进行本地认证
  2. 客户端首先在本地将当前用户的密码加密为HTLM Hash
  3. 确认双方协议版本,客户端向服务器明文发送自己的账号
  4. 服务器返回一个十六位随机数,也就是图中的challenge
  5. 客户端需要使用本地的NTLM Hash来加密这个challenge并发回给服务器,也就是图中的response
  6. 服务器将明文的用户名、challenge、response发给域控制器(DC
  7. 域控制器用这个用户名在SAM密码管理库中找此用户对应的NTLM Hash
  8. 用这个NTLM Hash来加密服务器发过来的与发给用户端一样的challenge,与服务器端传过来的response进行对比,如果相同,那么就认证成功
本地认证

Windows不会储存用户的明文密码,而是将明文密码加密后储存在SAM中

本地认证的过程中,用户登录时,系统会自动将用户输入的明文密码加密为NTLM Hash,然后和SAM中的NTLM Hash进行比较

NTLM Hash的生成

hhhh这个过程还算好吧,无非就是代码写了好多行突然发现可以五行之内解决)

import hashlib,binascii

hash = hashlib.new('md4', "fault".encode('utf-16le')).digest()

print(hash)

print(binascii.hexlify(hash))

之前很迫切的没有用内置的方法去搞它,一直在那里进行一个手搓,嘛,最后的脚本在上面辣

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值