现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

基于Windows RDP实现客户端的Kerberos认证

2016-04-25 21:20 工业·编程 ⁄ 共 5841字 ⁄ 字号 暂无评论

NLA是一种身份验证方法,它要求用户在创建会话前必须通过RDP会话主机服务器的身份验证。NLA在建立远程桌面连接并出现登录屏幕之前完成用户身份验证。这是比较安全的身份验证方法,有助于保护远程计算机避免恶意用户和恶意软件的攻击。网络级身份验证的好处是[1]

1.              起初需要较少的远程计算机资源。验证用户身份之前,远程计算机使用有限的资源,而不是像以前版本那样启动完整的远程桌面连接。

2.              可以通过降低受到拒绝服务攻击的风险,帮助提高安全性。

Kerberos协议是由麻省理工研发用来保护Project Athena提供的网络服务器。这个协议以希腊神话中的人物Kerberos(或者Cerberus)命名,它在希腊神话中是地狱的一条凶猛的三头保卫神犬,Kerberos的官方网站是:http://web.mit.edu/KerberosKerberos作为实现NLA的一种可选择协议,已经广泛应用到各种主流操作系统,如Windows, Unix, LinuxMac OS等,作为一种安全的网络认证协议数年前已经被成功应用到微软的Windows操作系统中。

1  Kerberos原理

认证(Authentication)解决的是如何证明某个人确确实实就是他或她所声称的那个人的问题。对于如何进行认证,可以采用这样的方法:如果一个密钥仅仅存在于AB,那么有个人对B声称自己就是AB通过让A提供这个密钥来证明这个人就是他或她所声称的AKerberos也是基于这个认证原理来实现双方的认证,它使用了两个独立的逻辑部分:认证服务器和票据授权服务器组成的"可信赖的第三方",称为密钥分发中心(KDC)。Kerberos工作在用于证明用户身份的"票据"的基础上。KDC持有一个密钥数据库;每个网络实体-无论是客户还是服务器-共享了一套只有他自己和KDC知道的密钥。密钥的内容用于证明实体的身份。对于两个实体间的通信,KDC产生一个会议密钥,用来加密他们之间的交互信息[2]Kerberos工作原理如下图1所示。


图1 Kerberos协议工作原理

 

Kerberos协议的安全主要依赖于参加者对时间的松散同步和短周期的叫做Kerberos票据的认证声明。 下面是对这个协议的一个简化描述,将使用以下缩写:

   ASAuthentication Server= 认证服务器

   TGSTicket Granting Server= 票据授权服务器。

   SSSS= 服务器。

   TGTTGT= 票据授权票据。

简单地说,客户向AS认证时用了一个长期共享密钥,并从AS得到一个票据。随后客户可以使用这个票据得到与SS通信必须的附加的票据,而不需要转而使用共享密钥。这些票据可以向SS证明身份。


图2 Kerberos消息基本流程

    Kerberos消息的基本流程解释如下:

1.  ClientKDC申请TGTTicket Granting Ticket):由KRB_AS_REQKRB_AS_REP消息实现。

2.  Client通过获得TGTKDC申请用于访问ServerTicket:由KRB_TGS_REQKRB_TGS_REP消息实现。

3.  Client最终为了Server对自己的认证向其提交Ticket:由KRB_AP_REQKRB_AP_REP消息实现。

2        软件设计与实现

由于该系统基于Kerberos V5实现,但并非完全是Kerberos V5协议的实现,是对该协议的一种扩展实现。该软件总体数据流程图如图3所示,由三部分通信实现:客户端(Client),KDC与服务器(Server)。


3 基于Windows ServerKerberos认证实现流程

3.1   ClientKDC消息交互

Kerberos V5协议来看,ClientKDC主要实现KRB_AS_REQKRB_AS_REPKRB_TGS_REQKRB_TGS_REP四条消息,由于该系统是对Kerberos V5协议的扩展,所以其实现与标准会有所区别。根据图3,笔者来分析ClientKDC消息交互的设计与实现。

1.KRB_AS_REQ:消息发送的主要内容有消息类型、用户的基本信息和时间戳等,数据结构定义如下(参考RFC4120 5.4.1):

typedef struct KDC_REQ_t {

  int pvno;   //协议的版本号V5,即该值等于5

  int msg_type;   //消息类型为KRB_AS_REQ

  struct PA_DATA_t** padata;  //预认证数据,根据消息类型不同传输不同的内容

  KDC_REQ_BODY *req_body;     //扩展的消息结构

} __PACKED__ KDC_REQ;

其中struct PA_DATA_t结构定义如下:

typedef struct PA_DATA_t {

    int32_t type; //预认证数据类型

ubyte *value;  //预认证数据内容

} __PACKED__ PA_DATA;

其中KDC_REQ_BODY类型定义如下:

typedef struct KDC_REQ_BODY_t {

    ubyte4 kdc_options;     //设定控制KDC的一些flag标记

    PrincipalName cname;       //客户端的用户名        

    char realm[KRB_MAX_NAME_LEN];  //要登陆的域名           

    PrincipalName sname;            //要访问的Server     

    char*  from;               //期望获得票据的开始时间,如果未设定,默认为当前时间

    char* till;              //期望票据的过期时间   

    char* rtime;       //期望更新获得票据的过期时间        

    ubyte4 nonce;       //随机数用于验证消息          

    int* etype;         //可支持的加密类型,比如该系统支持RC4加解密算法      

    HostAddress addresses;   //客户主机的主机名信息(可选)           

    EncryptedData enc_authorization_data;

    Ticket adt;     //附加的票据,根据kdc_options 中的ENC-TKT-IN-SKEY标记确定是否存在 

} __PACKED__ KDC_REQ_BODY;

2KRB_ERROR: KRB5KDC_ERR_PREAUTH_REQUIRED (25),KDC返回该消息表明需要附加的认证信息(PA-ENC-TIMESTAMP类型)。关于KRB_ERROR类型的消息,该系统中其数据结构定义(参考RFC4120 5.9.1)如下:

typedef struct krb_error_t {

  int pvno;  //同上

  int msg_type; //同上

  ubyte ctime[KRB_STAMP_LEN];   //当前的时间ASN.1中的GeneralTime格式

  ubyte2  cusec;     //当前时间的微秒数

  ubyte stime[KRB_STAMP_LEN]; //Server端的当前时间

  unsigned int susec;   //Server端当前时间的微秒数

  int code;           //错误代码号,参考RFC4120 7.5.9

  char crealm[KRB_MAX_NAME_LEN];

  PrincipalName cname;

  char realm[KRB_MAX_NAME_LEN];

  PrincipalName sname;

  char *e_text; //附加的消息帮助解释错误原因,可选的

  e_data edata; //帮助恢复或处理错误的数据

} krb_error_msg;

3KRB_AS_REQ:消息格式与1相同,主要区别是该消息中增加了PA-ENC-TIMESTAMP (2)消息,该消息的数据结构定义(参考RFC4120 5.2.7.2)如下:

typedef struct PA_ENC_TS_ENC_t {

ubyte    patimestamp[15];  //客户端当前的时间,格式为:32303130303630343037343831365a //代表2010-06-04 07:48:16 (UTC)

    int       pausec;       //客户端当前时间的微秒数

} __PACKED__ PA_ENC_TS_ENC;

4KRB_AS_REP:该消息为KDC正常返回给Client的消息,消息包含票务Ticket消息和加密的信息。该消息的数据结构定义(参考RFC4120 5.4.2)如下:

typedef struct KDC_REP_t {

  int pvno;

  int msg_type;

  struct PA_DATA_t* padata;

  char  crealm[KRB_MAX_NAME_LEN]; 

  PrincipalName cname;    

  Ticket ticket;  //需要转发的Ticket消息

  EncryptedData enc_part; //加密的信息,数据格式为EncKDCRepPart

} __PACKED__ KDC_REP;

关于Ticket的定义参考RFC4120 5.3,用于传递交互的票据信息。关于EncKDCRepPart的定义参考RFC4120 5.4.2,该信息包含双方协商使用的Session Key和一些认证信息。

5KRB_TGS_REQ: 该消息用来申请用于访问ServerTicket,消息格式与KRB_AS_REQ相同。

6KRB_TGS_REP:该消息返回响应KRB_TGS_REQ请求信息,消息格式与KRB_AS_REP相同。

9KRB_TGS_REQ: 该消息用来申请用于访问ServerTicket,消息格式与KRB_AS_REQ相同。

10KRB_TGS_REP:该消息返回响应KRB_TGS_REQ请求信息,消息格式与KRB_AS_REP相同。

3.2   ClientServer消息交互

ClientServer之间的交互主要完成两件事情:一、协商Token用于后续的交互认证,由消息7(NegTokenInit)与8NegTokenResp)消息实现;二、ClientServer的互相认证,由11KRB_AP_REQ),12(KRB_AP_REP)13(NegTokenResp)实现。

7.NegTokenInit:用于发送请求协商TokenOID列表,每一个OID代表一种可支持的GSS-APIGeneric Security Service Application Program Interface)机制。NegTokenInit结构定义参考RFC4178 4.2.1,定义内容如下:

typedef struct NegTokenInit_t {

          ubyte *mechTypes        //OID列表

          ubyte4 reqFlags        //ContextFlags  OPTIONAL, 该系统未使用

          ubyte *mechToken       //协商的Token内容

          ubyte * mechListMIC    //如果协商不支持完整性保护,该项就不使用

} __PACKED__ NegTokenInit

8NegTokenResp:响应NegTokenInit的请求,返回所支持的OID,以及相应的Token内容,该结构的定义参考RFC4178 4.2.1 4.2.2,定义如下:

typedef struct NegTokenResp _t {

      enum negState {COMPLETED, INCOMPLETE, REJECT , REQUEST-MIC }; //协商的状态

      ubyte * supportedMech; //支持的机制OID

      ubyte *responseToken;  //协商的Token内容

      ubyte * mechListMIC;  // MIC token计算根据RFC4178 5小节。

} __PACKED__ NegTokenResp;

11KRB_AP_REQ:该消息主要用于完成ClientServer的认证,即让Server明白该Client是合法的,是可信的。该消息的定义参考RFC4120 5.5.1节,定义如下:

struct AP_REQ_t {

       int pvno;

       int msg_type;

       ubyte ap_options[5];  //请求的标记

       Ticket ticket;   //转发的Ticket

       Authenticator auth;  //加密的认证信息,包含客户可选的subkey,定义参考RFC4120 5.5.1

} __PACKED__ AP_REQ;

12KRB_AP_REP:这个消息是根据KRB_AP_REQ消息中的ap_optionsmutual-required标记)选项来产生的,用于证明自己就是Client要访问的Server。主要返回一个双方协商的subkey为后续的具体应用程序加解密使用。

13NegTokenResp:与消息8格式相同,不同的是这里的negState的状态为COMPLETED,表示协商已完成。并且包含已计算好的mechListMIC值。

至此,关于KerberosRDP协议中的认证过程已经完成,为后续安全传递数据铺平了道路。

结 语

随着网络的飞速发展,网络安全认证日趋重要,Kerberos作为一种强大的网络认证协议已被广泛应用。本文讨论的是Kerberos基于Windows系统RDP协议中的一个典型网络认证应用,通过本文读者可以学习Kerberos协议的工作原理,以及它在实际工作中的具体应用实现。 

给我留言

留言无头像?