https://web.mit.edu/kerberos/
https://blog.csdn.net/wulantian/article/details/42418231
Kerberos
是一种网络认证协议
它被设计用来通过密钥加密算法为客户服务器应用程序提供强认证
从麻省理工的网站上可以获得一份该协议的free实现(此处的free指的是自由软件)
https://web.mit.edu/
Kerberos在许多商业产品上一样很有用处
因特网是一个不安全的地方,许多在网络中使用的应用程序不提供任何安全性。用于sniff
密码的工具都被黑客用烂了,因此,在网络中使用明文传输密码的应用程序sucks。更糟糕的是,一些客户服务程序竟然依赖于客户端的诚实(意思就是认为客户是没有恶意的),还有一些其他的客户服务程序依赖于客户端自己限制自己的活动(are you kidding?)而服务器本身并没有做任何强制性的限制。。。。。
一些网站通过firewall
来解决他们的网络安全问题,但是造成的破坏最大的网络攻击往往是来源于内部,而且firewall
使用起来非常不人性化,对内部用户访问外网的活动也造成了很多限制,也就只是比断网好那么一点而已
Kerberos是由MIT创建的,用于解决上述安全问题。Kerberos
使用强加密算法,所以客户端可以直接通过因特网(因特网是不安全的)向服务器提交自己的身份认证信息。在服务器和客户端通过Kerberos
认证完对方的身份之后,它们还可以使用Kerberos
来加密它们之间的通信来保障数据的完整性和私密性。(这在商业应用中非常重要的)
现在B想要信任A,那么A就要向B证明自己就是B所信任的那个A,其中一种方法就是A向B展示只有AB两个人知道的一个秘密,这里就涉及到三个问题:
下面基于这三个问题展开说明,我们将上面提到的秘密用一个Key
来表示
client
为了向server
证明自己的身份,需要做以下两件事情:
identity
使用明文传递过去identity
使用key
作为密钥进行加密传输过去server
收到两组数据,一组没有被加密,一组被加密,直接把加密的数据解密通未加密的明文进行比较即可验证client
的身份
这里遗留了一个问题,就是client
和server
如何拥有相同的key
作为密钥来对数据进行加解密
对于一个账户,我们需要使用密码来认证信息,但是又不想直接告诉负责认证的一方自己的明文密码,这里的解决方案就是传输一个使用hash
算法对密码进行加密过的hash code
来作为认证信息,这样既可以保证密码和hash code
的一一对应,又可以保证自己密码的安全,这个hash code
一般被称作master key
现在来解决上面的遗留问题
,这个密钥需要在server
和client
之间进行传输,就注定了它只能是一个short-term key
,它只在server
和client
的一次session
中有效,所以我们称这个key
为session key
(skey),那么这个skey
是如何被client
和server
获取到的呢?这时就用到了KDC
,它作为kerberos
协议中的第三方
在Windows
的域环境中,DC
就是一个KDC
,DC
中有一个数据库,存储着所有域中账户的信息,这就意味着它知道所有账户的master key
,skey
也是由KDC
来进行分发的,看一下KDC
是如何向client
和server
分发skey
的:
可以看到KDC
向client
发了两份数据,一份是使用client master key
进行加密的,另一份是使用server master key
进行加密的(因为KDC
知道client
和server
的密码,自然也就有它们的master key
),client
使用自己的master key
对第一份数据进行解密,即可得到会话使用的密钥skey
(Sclient-server)
第二份数据乍看上去好像有点不太对劲,怎么把使用server
的master key
加密过的数据也发送给了client
呢,client
并没有server
的master key
啊,它又解密不了,干嘛发给client
呢??请看下面的解释:
直接将skey
发送给server
也是可以的,但是会出现下面两个问题:
因为server
的数量肯定是少于client
的数量的,如果KDC
直接分发的话,那么server
就要维护一个列表,在上面记录每一个client
和skey
的对应关系,然后当client
的认证数据包到了之后找到对应于该client
的skey
对认证信息进行解密,但是如果让client
通知server
,就免去了server
查表的过程
有可能client
已经收到了skey
,但是server
还没有收到skey
,这样导致无法认证
所以为了保证client
的身份能够被正常识别,就由client
告知server
单纯地使用一个client
和server
都知道的key
来进行身份的认证是有漏洞的,所以真正的认证过程并没有这么简单,client
会提供额外的信息来自证,这些证明身份的信息统一称为Authenticator
,Kerberos
协议中的Authenticator
就是关于client的一些信息(client info)和一个timestamp
这里再遗留两个问题:
time stamp
?在此基础,client
解密KDC
给自己的使用client
的master key
加密过的skey
,获得skey
,使用skey
加密自己的Authenticator
,然后连同KDC
发给自己的使用server
的master key
加密过的skey
和client info
打成一个数据包发给server
,我们称使用server
的master key
加密过的skey
为session ticket
client
发送过来的数据包中,包含两个client info
,一个是使用server
的master key
加密过的来自于KDC
的client info
(这个来自于server
绝对信任的第三方),另一个是使用skey
加密的来自于client
的client info
,server
通过比较这两个client info
,可以证明client
的身份,那么time stamp
又有啥用呢??
现在来解释上面遗留的问题:
先解释一下为什么会出现漏洞吧
如果网络中的攻击者监听并截获到了上面client
发送给server
的认证数据包,那么攻击者可以直接把认证数据包当成自己的credential
重新发送给server
,也可以获得认证,timestamp
就是为了解决这个问题的
server
在接收到client
发送过来的数据包之后,会优先提取出来自client
的timestamp
信息,通当前时间进行比较,如果差值超出了可接受时间(5min),则不进行后续的身份认证,直接拒绝客户请求
其实这个我是从上面链接的博客看的,有些知识点的确很合理,但是就时间戳的讲解来说,我有点弄不明白,按照博主的说法,攻击这只要在5分钟之内解惑并转发数据包即可,那样的话,时间戳还有啥用???
上面一直在说server
对client
的认证,但client
对server
的认证在某些场景下也是很有必要的,如果访问倒了而已伪装的服务器,并向其发送了重要的信息,将会造成或大或小的损失,具体实现方式是client
在向server
发送数据包的时候带上了一个flag
,表示要求对server
的身份进行认证,server
知道后会把从client
接收到的数据包中的timestamp
提取出来使用skey
加密回送给client
,client
收到后解密并和自己原来的timestamp比对,一致则认为自己在访问所期望的server
,这里主要是为了防止攻击者通过截获数据包来冒充server
,因为timestamp
是被skey
加密的,但是如果攻击者不知道server
的密码的话,是无法获得skey
的,也就无法冒充server
了,但是如果攻击者得到了server
的密码,那么就存在伪装server
的可能性了
说到底,client
要想获得server
的认证,就必须向其提交从KDC
获取到的使用server
的mastar key
加密过的client info + skey
(Session Ticket
),这个ticket
由一个双方都信任的Ticket颁发机构–KDC负责生成
Ticket Granting Ticket--TGT
,这个Ticket
也是由KDC
负责分发的,client
在从KDC
获得session ticket
之前,需要先拥有TGT
,下面讲解client
如何从KDC
获得TGT
和client
向KDC
申请对某个server
的访问时的ticket
的流程差不多,client
告诉kdc
,它想要一个TGT
,然后KDC
发给它两条数据,一条是使用client
的master key
加密的skey
(KDC
与client
之间的skey
),另一条是skey+client info
,使用KDC
的master key
进行加密,以后client
再向kdc
申请访问server
的ticket
时直接使用TGT
就行了,对与client
来说,TGT
就是使用KDC
的master key
加密过的skey+client info
,可以看到TGT
与skey
是关联的,而我们前面说过,skey
是一个short term key
,skey
过期之后,TGT
也就是失效了,client
用户注销再重新登录之后也会导致skey
失效,因此skey
又被称作logon session key
下面看一下client
如何使用TGT
从KDC
申请访问某个server
的ticket
通过上面这个图片可以看出,client
向KDC
发送了两个数据包,一个是TGT
,另一个是使用skey
进行加密的Authenticator
,由client
生成,包含client info
信息,第二个就是之前从KDC
申请到的TGT
KDC
收到这两个数据包之后,先解密TGT
,从而获取到skey
和client info
,然后再使用skey
对Authenticator
进行解密,提取出client info
,并和TGT
中的client info
进行比对,两者相同,则client
的身份认证成功,然后KDC
就会向其分发ticket
和skey
(用于server
和client
进行认证)
上面这些就是Kerberos
认证的基本过程,总结下来是这样的:
client
向KDC
申请TGT
client
使用TGT
申请访问某个server
的ticket
client
拿着ticket
和自己生成的Authenticator
向server
证明自己的身份KDC提供两个服务
KDC作为一个第三者,或者受委托人来参与另外两个委托人的通信过程,这另外两个委托人,一般就是用户和服务
用户通过UPN
(User Principal Name)来标识自己,注意区分委托人(principal)和原则(principle)
服务通过SPN
(Service Principal Name)来标识自己,格式为serviceclass/host_port/serviceName
,比如:ldap/dc1.bhusa.com
上面的client向KDC请求TGT的过程中涉及到了KDC
的master key
,这个master key
就是AD
中的域控制器中的krbtgt
账户的密码的散列值
在windows
的认证过程中,并不对TGT
的来源进行验证,因此我们如果从域中的某台计算机中导出了TGT
,我们可以拿着这个TGT
去访问域内的其他资源
黄金票据其实就是TGT
,有了伪造的TGT
之后,我们就免去了向KDC
申请TGT
的过程,可以直接申请service ticket