kerberos协议学习
该协议涉及的攻击手段如下
理解协议过程所画的草稿图
鉴于我画的图丑晕了,于是在笔记中还是使用别人的图吧
未引入TGS前的认证流程
客户端向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后的认证流程
这个图也就很好的表明了将KDC分为AS和TGS后的作用,也就解决了刚才未引入TGS前我们提出的问题1和2,对于2的解决是只有当确认了A的身份后,才会给sessionkey(a-b)
总体来说就是当client想要访问server上的某个服务时,需要先向AS证明自己的身份,验证通过后AS会发放一个TGT,client会再次向TGS证明自己的身份后,TGS会发放一个ST,随后client向server发起认证请求
详细认证过程
①: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的支持
NTLM 认证
简介
NTLM是NT LAN Manager的缩写,NTLM是指telnet的一种验证身份方式,即问询/应答身份验证协议
认证流程
进行一个嫌弃自己的字好丑
这就是我理解的并且画的流程图
- 用户登录客户端,进行本地认证
- 客户端首先在本地将当前用户的密码加密为HTLM Hash
- 确认双方协议版本,客户端向服务器明文发送自己的账号
- 服务器返回一个十六位随机数,也就是图中的challenge
- 客户端需要使用本地的NTLM Hash来加密这个challenge并发回给服务器,也就是图中的response
- 服务器将明文的用户名、challenge、response发给域控制器(DC
- 域控制器用这个用户名在SAM密码管理库中找此用户对应的NTLM Hash
- 用这个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))
之前很迫切的没有用内置的方法去搞它,一直在那里进行一个手搓,嘛,最后的脚本在上面辣