Kerberos认证解析

kerberos定义

  1. Kerberos 是一种网络认证协议,其设计目标是经过密钥系统为客户机、服务器应用程序提供强大的认证服务。
  2. Kerberos 做为一种可信任的第三方认证服务,是经过传统的密码技术(如:共享密钥)执行认证服务的。
  3. Kerberos也能达到单点登陆的效果,即当Client经过了Kerberos server的认证后,即可以访问多个Real Server。

kerberos几个重要组件

  1. KDC又称Kerberos服务器:负责管理发放Ticket和记录受权的中心服务器,包含两部分:AS认证服务器(Authentication Server),TGS服务受权服务器(Ticket Granting Server)
  2. Client 客户端:须要使用kerbores服务的客户端
  3. AppServer 服务端:提供具体服务的服务端
  • Client在Kerberos注册用户名c,密码Kc;Kerberos服务器将用户的用户名及密码存放在它的数据库中,所以密码Kc只有Client和Kerberos才拥有。
  • AppServer在Kerberos注册用户名s,密码Ks;同理密码Ks只有AppServer和Kerberos才拥有。
  • TGS在Kerberos注册用户名tgs,密码Ktgs;同理密码Ktgs只有TGS和Kerberos才拥有。

image.png

kerberos中几个重要概念

  1. 用户principal的命名:相似elis/admin@EXAMPLE.COM,形式是用户名/角色/realm域。
  2. 服务principal的命名相似ftp/station1.example.com@EXAMPLE.COM,形式是服务名/地址(提供者)/realm域;
  3. principal(认证的主体即简称“用户名”):每添加一个服务或者用户就要添加一条principal,每一个principal都有一个密码。用户principal的密码用户本身记住,服务的principal密码服务本身记录在硬盘上(keytab文件中);
  4. realm(Kerberos的域):有点像编程语言中的namespace。在编程语言中,变量名只有在某个"namespace"里才有意义。一样的,一个principal只有在某个realm下才有意义。因此realm能够当作是principal的一个"容器"或者"空间"。相对应的,principal的命名规则是"what_name_you_like@realm"。

在kerberos, 你们都约定成俗用大写来命名realm, 好比"EXAMPLE.COM"算法

  1. Kerberos的进程:有krb5kdc(主进程,也就是KDC)、kadmind(用于远程管理principal数据库)、kpropd(slave同步数据用)。配置文件在/etc/krb5.conf和/var/kerberos/krb5kdc/下,数据库在/var/kerberos/krb5kdc/princical;
  2. Kerberos只提供一种功能——在网络上安全的完成用户的身份验证。它并不提供受权功能或者审计功能。

kerberos认证交互过程

kerberos认证交互过程能够简要归纳为如下图片中的三次通讯
image.pngshell

  • 每次通讯,消息包含两部分,一部分可解码,一部分不可解码;
  • 服务端不会直接与KDC通讯
  • KDC保存全部机器的帐户名和密码
  • KDC自己具备一个密码

第一次通讯

client-->AS(Authentication Service)认证服务数据库

  • 想要访问http服务,首先要向KDC表名本身的身份,经过未加密的信息发送至KDC获取Ticket Granting Ticket (TGT)。
  • 信息包含(你的用户名/ID、你的IP地址、TGT的有效时间);
  • Authentication Server收到你的请求后,会去数据库中验证,你是否存在。注意!仅仅是验证是否存在,不会验证对错。
  • 若是存在,Authentication Server会产生一个随机的Session key(能够是一个64位的字符串),这个key用于你和Ticket Granting Server (TGS)之间通讯。Authentication Server会发送两部分信息给你,一部分信息为TGT,经过KDC本身的密码进行加密,包含(你的name/ID、TGS的name/ID、时间戳、你的IP地址、TGT的生命周期、TGS session key),另一部分经过你的密码进行加密,包含的信息(TGS的name/ID、时间戳、生命周期、TGS session key)
  • 若是不存在会报出:client not found in Kerberos databases while getting initial这样的错误,意思就是KDC的数据库中没有找到你这用户。
  • 使用你的密码解密第二部分信息,获取到TGS session key。若是密码不正确,没法解密,则认证失败。第一部分信息TGT,你是没法解密的,但须要暂时缓存起来。

image.png

第二次通讯

client-->TGS(Ticket Granting Service)票据授予服务器编程

若是第一步认证成功了,说明此时你已经拥有了一个没法解密的TGT和一个经过本身密码解密第二部分信息获取到的TGS Session Key。缓存

  • 请求信息包含三部分:1.经过TGS Session Key加密的认证器部分(你的name/ID、时间戳)2.明文传输部分:(请求的Http服务名(就是请求信息)、HTTP Service的Ticket生命周期)3.TGT部分
  • Ticket Granting Server收到信息后,首先检查数据库中是否包含有你请求的Http服务名。
  • 若是无,直接返回错误信息。
  • 若是存在,则经过KDC的密码解密TGT,这个时候。咱们就能获取到TGS Session key。而后,经过TGS Session key去解密你传输的第一部分认证器,获取到你的用户名和时间戳。
  • TGS再次进行验证:
  • 对比TGT中的用户名与认证器中的用户名
  • 比较时间戳(认证器中的时间戳和系统的时间戳),不能超过必定范围(一般30分钟),时间戳用于防止重放攻击,因此全部的机器都必需使用安全的相似NTP的机制把时间同步好。
  • 检查是否过时
  • 检查IP地址是否一致
  • 检查认证器是否已在TGS缓存中(避免应答攻击)
  • 验证经过后TGS会发送两部分信息给你:1.经过Http服务的密码进行加密的信息(ST):(你的name/ID、Http服务name/ID、你的IP地址、时间戳、ST的生命周期、Http Service Session Key)和 经过TGS Session Key加密的信息(Http服务name/ID、时间戳、ST的生命周期、Http Service Session Key)
  • 你收到信息后,经过TGS Session Key解密,获取到了Http Service Session Key,可是你没法解密ST。

image.png

第三次通讯

client-->Http服务安全

前面两步成功后,之后每次获取Http服务,在Ticket没有过时,或者无更新的状况下,均可直接进行这一步。省略前面两个步骤。服务器

  • 向Http Server发送请求信息,包含两部分:1.经过Http Service Session Key,加密部分(你的name/ID、时间戳),2.ST
  • Http服务端经过本身的密码解密ST(KDC是用Http服务的密码加密的),这样就可以获取到Http Service Session Key,解密第一部分。
  • 服务端解密ST后,进行检查
  • 对比ST中的用户名(KDC给的)与认证器中的用户名
  • 比较时间戳(认证器中的时间戳和系统的时间戳),不能超过必定范围
  • 检查是否过时
  • 检查IP地址是否一致
  • 检查认证器是否已在HTTP服务端的缓存中(避免应答攻击)
  • Http Server应答信息:经过Http Service Session Key加密的信息(Http服务name/ID、时间戳)

image.png

  • 你经过缓存的Http Service Session Key解密这部分信息,而后验证是不是你想要的服务器发送给你的信息。完成你的服务器的验证。

至此,整个过程所有完成。网络

kerberos疑问

  1. 上面有个数据包是KDC经Client转发给Server的,为何不直接发给Server?
  • 由于Server可能给多个Client提供服务,这样Server须要维护一个Client和会话密钥的对应表,这对Server是一个负担。
  1. 为何要发两份关于Client的信息给Server?
  • 经过这两份数据的对比,Server就能判断出是否是对的Client在访问服务。
  1. Client是如何判断本身在访问对的Server呢?
  • 由于Client给Server的一个数据包是用Server的master key来加密的因此只有对的Server才能解密。
  1. 为何要用会话密钥
  • 通讯方的master key是长期有效的,若是在网络上传输,一旦被截取,理论上来讲只要有足够的时间是能够破解的。
  • 因此咱们才用临时的会话密钥来通讯,一段时间后会话密钥会过时,同时时间戳也防止了,恶意用户重复使用同一个数据包。
  1. 为何要用时间戳?
  • 若是Client向Server传送的数据包被其余的Client截取,而后本身拿来向Server请求服务这,这样就会出问题
  • Server收到请求后将从解密后的数据包中得到的时间戳和当前时间对比,一旦超过必定范围将直接拒绝请求

kerberos自身的安全工做如何作?

  1. kerberos的安全是创建在主机都是安全的而网络不是安全的假定之上的。因此kerberos的安全其实就在于把主机的安全作好;
  2. 尤为是KDC那台机器的安全。出于安全的考虑,跑KDC的机器上不能再跑别的服务,若是KDC被攻陷了,那么全部的密码就所有泄露了;
  3. 若是只是服务的机器被攻陷了,那么更改服务的principal的密码便可;
  4. 若是是用户的机器被攻陷了,那么在ticket超时(通常是数小时的时间里)以前,用户都是不安全的,攻击者还有可能尝试反向用户的密码;
  5. Kerberos依赖其它的服务来存放用户信息(登陆shell、UID、GID啥的),所以须要注意到这些信息依然是很容易遭受攻击而且泄露的;
  6. 因为任何人均可以向KDC请求任何用户的TGT(使用用户密码加密的session key),那么攻击者就有可能请求一个这样的包下来尝试解密,他们有充足的时间离线去作这个工做,一旦解开了,他们也就拿到了用户的密码。简单密码几乎一解就开,因此不能设置简单密码,也不能在字典里。另外还能够打开Kerberos的预验证机制来防护这种攻击,预验证机制就是在KDC收到用户请求TGT的请求以后,要求用户先发一个用本身密码加密的时间戳过来给KDC,KDC若是确实能够用本身存储的用户密码解密,才发TGT给用户,这样攻击者在没有用户密码的时候就拿不到可用于反向的包含用户密码的TGT包了。在MIT kerberos中在配置文件中default_principal_flags = + preauth能够打开这个机制。但这个机制也并非无懈可击的,攻击者依然能够经过嗅探的方式在正经常使用户请求TGT时拿到上述的那个包(这个难度显然就高了一些);
  7. 还有一个问题是攻击者可能伪造一个KDC,而后用一个伪造的实际不存在的用户向这个KDC请求验证,经过后他就获得了一个用户登陆系统的shell。这种攻击须要在客户端防护,须要客户端主动去验证一下KDC是不是正确的KDC。具体来讲就是客户端在获得TGT后进一步要求KDC给一个本物理机的principal(也就是一个用物理机密钥加密的串),而后尝试用物理机存储的密码去解密,因为伪造的KDC没有物理机(host/hostname)的principal密码,因此它没法给出这个包,也就被客户端认定为是伪造的KDC,认证失败。这个机制须要在客户端开启(认证服务器端么),默认是关闭的,在krb5.conf里[appdefaults]章节里pam的部分中设置validate=true来开启;

Kerberos能够在不一样的realm之间创建信任关系

这样用户在一个realm中登陆后就能够享用多个realm中的服务。简单的创建互信的方法是在2个域名都创建一条共享密码的名为krbtgt的principal。更好的创建互信的方法是多个realm都创建一条信任到本身的父realm,这样在子realm之间也能创建起信任;session

Kerberos还能向SSL帮助网络流量套上一层加密

好比说telnet这种明文协议就可能能用上。可是跟SSL或者SSH比起来安全性仍然略低,由于它的session key是用对称加密传输的(若是TGT被盗取了,流量的加密也就失效了),这在理论上增长了被嗅探破解的可能。而SSH和SSL协商session key采用的DH算法是理论安全的(被称为PFS即Perfect forward secrecy,详见http://en.wikipedia.org/wiki/..._forward_secrecy)。还有一个问题是Kerberos采用的一些加密算法是已经不安全的了(如CRC32和DES),而另外一些加密算法(AES)并无被其余的kerberos实现普遍使用,因此会有一些兼容性的麻烦,选择加密算法时要避开这些算法;app

若是将princical密码设置为random

那么每次将其dump到本地keytab中时,都会random新的密码并dump到本地(可用于更新密码);

相关文章
相关标签/搜索