logo_kerberos.gif

Difference between revisions of "Projects/Audit"

From K5Wiki
Jump to: navigation, search
(Abandoning "hybrid")
m
Line 68: Line 68:
 
|-
 
|-
 
| Reply-encrypting key enctype (long-term) ||✔ || ✔
 
| Reply-encrypting key enctype (long-term) ||✔ || ✔
  +
|-
  +
|rowspan=1|All phases
  +
| KDC status || on error ||on error and "ISSUE"
 
|-
 
|-
 
|}
 
|}
   
Note, that audit plugin implementors will be able to extract the following auditable information:
+
The implementors of audit plugin will be able to extract the following auditable information:
   
 
KDC request:
 
KDC request:
Line 93: Line 96:
   
 
Other events to consider for the future development:
 
Other events to consider for the future development:
:Policy
 
::Policies violation - what went wrong and how to prevent it;
 
:Secrets (Common Criteria FCS_CKM.1, FCS_CKM.4);
 
::long- and short-term keys creation, manipulation, cleaning.
 
== Design details ==
 
   
The following are highlights of this new feature:
 
 
3. Policy
 
:Policies violation - event description, reason and how to fix it;
 
4. Secrets (Common Criteria FCS_CKM.1, FCS_CKM.4);
 
:long- and short-term keys creation, manipulation, cleaning.
  +
 
== Design details ==
   
 
====Ticket ID====
 
====Ticket ID====
Line 118: Line 121:
 
krb5_error_code
 
krb5_error_code
 
unload_audit_plugin(krb5_context context);
 
unload_audit_plugin(krb5_context context);
  +
krb5_boolean
  +
kau_isloaded(krb5_context context);
 
/* event specific functions */
 
/* event specific functions */
krb5_error_code
+
krb5_error_code
kau_kdc_start(krb5_context context, struct server_handle shdl, int status);
+
kau_kdc_start(krb5_context context, const int event_id, const int status);
krb5_error_code
+
krb5_error_code
kau_kdc_stop(krb5_context context, krb5_error_code status);
+
kau_kdc_stop(krb5_context context, const int event_id, const int status);
krb5_error_code
+
krb5_error_code
kau_as_req(krb5_context context, struct as_req_state *state, int status);
+
kau_asreq(krb5_context context, const int event_id, const int status, audit_state *state);
krb5_error_code
+
krb5_error_code
kau_tgs(krb5_context context, struct tgs_req_audit_state *state, int status);
+
kau_tgsreq(krb5_context context, const int event_id, const int status, audit_state *state);
+
krb5_error_code
  +
kau_s4u2self(krb5_context context, const int event_id, const int status, audit_state *state);
  +
krb5_error_code
  +
kau_s4u2proxy(krb5_context context, const int event_id, const int status, audit_state *state);
  +
krb5_error_code
  +
kau_u2u(krb5_context context, const int event_id, const int status, audit_state *state);
  +
/* utilities */
  +
krb5_error_code
  +
kau_init_kdc_req(krb5_context context, krb5_kdc_req *request, const krb5_fulladdr *from, audit_state **au_state);
  +
krb5_error_code
  +
kau_make_tkt_id(krb5_context context, const krb5_ticket *ticket, char **out);
  +
krb5_error_code
  +
kau_make_req_id(krb5_context context, const krb5_kdc_req *request, char **out);
  +
  +
where ''event_id'' references to the ''Phase'' (left column of [[#Events| events]] table), and ''audit_state'' structure holds the following information:
  +
  +
typedef struct _audit_state {
  +
krb5_kdc_req *req_in; /* request in the original form */
  +
krb5_kdc_req *req_mod; /* modified (per protocol) request */
  +
krb5_kdc_rep *reply;
  +
const krb5_fulladdr *from;
  +
const char *status; /* KDC status message */
  +
char *tkt_in_id; /* primary (TGT) ticket ID */
  +
char *tkt_out_id; /* derived (service or referral TGT) ticket ID */
  +
char *evid_tkt_id; /* for s4u2proxy - user's evidence ticket ID, for u2u - TGT ticket ID */
  +
char *req_in_id; /* original-request ID */
  +
char *req_mod_id; /* modified-request ID */
  +
krb5_int32 sess_etype; /* session key enctype */
  +
krb5_int32 srv_etype; /* enctype of the long-term key of service */
  +
krb5_int32 rep_etype; /* reply-encrypting key enctype */
  +
krb5_boolean tkt_renewed;
  +
krb5_boolean tkt_validated;
  +
/* referrals */
  +
krb5_data *cl_realm; /* remote client's realm */
  +
/* s4u and u2u */
  +
krb5_principal s4u2self_user; /* impersonated user */
  +
krb5_principal s4u2proxy_user; /* delegated user */
  +
krb5_principal u2u_user; /* client for the second ticket */
  +
char *violation; /* local or protocol policy problem */
  +
} audit_state;
  +
 
=== Pluggable interface ===
 
=== Pluggable interface ===
   
Line 133: Line 138:
 
typedef struct krb5_audit_vtable_st {
 
typedef struct krb5_audit_vtable_st {
 
/* Mandatory: name of module. */
 
/* Mandatory: name of module. */
char *name;
+
char *name;
kau_open_fn open;
+
int conf_options;
kau_close_fn close;
+
kau_open_fn open;
kau_generic_fn generic;
+
kau_close_fn close;
kau_kdc_start_fn kdc_start;
+
kau_kdc_start_fn kdc_start;
kau_kdc_stop_fn kdc_stop;
+
kau_kdc_stop_fn kdc_stop;
kau_as_req_fn as_req;
+
kau_as_req_fn as_req;
kau_tgs_req_fn tgs_req;
+
kau_tgs_req_fn tgs_req;
  +
kau_s4u2self_fn tgs_s4u2self;
  +
kau_s4u2proxy_fn tgs_s4u2proxy;
  +
kau_u2u_fn tgs_u2u;;
 
} *krb5_audit_vtable;
 
} *krb5_audit_vtable;
 
 
 
typedef krb5_error_code
 
typedef krb5_error_code
 
(*kau_open_fn)(kau_ctx *au_ctx);
 
(*kau_open_fn)(kau_ctx *au_ctx);
 
 
typedef krb5_error_code
 
typedef krb5_error_code
 
(*kau_close_fn)(kau_ctx au_ctx);
 
(*kau_close_fn)(kau_ctx au_ctx);
 
/* general purpose interface to pass unspecified number of
 
* key-type-value triplets to a plugable interface.
 
*/
 
 
typedef krb5_error_code
 
typedef krb5_error_code
(*kau_generic_fn)(kau_ctx au_ctx, const int event_id, const int status, ... );
+
(*kau_kdc_start_fn)(kau_ctx au_ctx, const int event_id, int status);
 
/* one-API-per-event surrogate */
 
 
typedef krb5_error_code
 
typedef krb5_error_code
(*kau_kdc_start_fn)(kau_ctx au_ctx, const int event_id, const int status,
+
(*kau_kdc_stop_fn)(kau_ctx au_ctx, const int event_id, int status);
struct server_handle_san shdl);
 
 
typedef krb5_error_code
 
typedef krb5_error_code
(*kau_kdc_stop_fn)(kau_ctx au_ctx, const int event_id, const int status);
+
(*kau_as_req_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
 
typedef krb5_error_code
 
typedef krb5_error_code
(*kau_as_req_fn)(kau_ctx au_ctx, const int event_id, const int status,
+
(*kau_tgs_req_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
struct as_req_state_san *state);
 
 
typedef krb5_error_code
 
typedef krb5_error_code
(*kau_tgs_fn)(kau_ctx au_ctx, const int event_id, const int status,
+
(*kau_s4u2self_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
struct tgs_req_state_san *state);
+
typedef krb5_error_code
+
(*kau_s4u2proxy_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
where new types server_handle_san, as_req_state_san and tgs_req_state_san are sanitized variants of server_handle, as_req_state and tgs_req_state structures respectively.
+
typedef krb5_error_code
  +
(*kau_u2u_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
   
   
 
== Dictionary==
 
== Dictionary==
   
The possible basic field names are:
+
The following are proposed basic field names for JSON parsing:
   
 
{| class="wikitable" style="border: 3px solid #59121e"
 
{| class="wikitable" style="border: 3px solid #59121e"
Line 186: Line 186:
 
| service || style="padding-left: 2em "| STR|| requested service principal
 
| service || style="padding-left: 2em "| STR|| requested service principal
 
|-
 
|-
| kdc_status || style="padding-left: 2em "| TR|| KDC status (“ISSUE” on success)
+
| kdc_status || style="padding-left: 2em "| STR|| KDC status (“ISSUE” on success)
 
|-
 
|-
 
| full_address || style="padding-left: 2em "| STR || Alternative to "fromport"/"fromaddr"
 
| full_address || style="padding-left: 2em "| STR || Alternative to "fromport"/"fromaddr"
Line 253: Line 253:
 
|-
 
|-
 
|}
 
|}
 
 
 
 
   
 
== Configuration ==
 
== Configuration ==
Line 268: Line 264:
   
 
# Standardize a Ticket_ID;
 
# Standardize a Ticket_ID;
# Make reporting auditable events configurable. For example, one can choose to report TGS_REQ, but not AS_REQ etc;
+
# Make reporting auditable events configurable. For example, one can choose to report TGS_REQ, but not AS_REQ;
# Define and make configurable the DETAILED and BASIC levels of the events;
+
# Sanitize ''KDC request'' and ''KDC reply'' before passing them to the concrete audit implementation: security sensitive information should not leave KDC boundaries;
# Sanitize KDC request and reply before passing them to audit implementation: security sensitive information should not leave KDC boundaries;
 
 
# Develop Audit system for Preauth and Authdata mechanisms.
 
# Develop Audit system for Preauth and Authdata mechanisms.
   

Revision as of 11:26, 29 July 2013

This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.


Purpose

Create an Audit infrastructure within MIT Kerberos to monitor security related events on the KDC. In future expand Kerberos Audit facility to the application servers, kadmin if it remains desirable.


Requirements

The new audit system should be:

  • build-time enabled;
  • run-time pluggable;
  • simple and flexible, so it could be easily replaced with the OS specific and third-parties implementations;


Events

(Common Criteria Class FIA)

This section details the categories of the auditable events and the associated data.

1. Startup and shutdown of the KDC must be recorded by audit system;

2. AS_REQ and TGS_REQ:

Phase Data to be logged AS_REQ TGS_REQ
Authenticate request content and client client’s address and port
original KDC request and request ID
primary ticket ID (S4U:front-end server's) TGT
Determine service principal modified KDC request and request ID
cross-realm referral service principal, TGS
user-to-user: client in the 2nd ticket
Validate policies local policy violation
protocol constraints S4U2Proxy, S4U2Self
Issue ticket ticket renewed
ticket validated
session key enctype (short-term)
enctype of the service's long-term key
derived ticket ID TGT service or referral TGT
Encrypt reply KDC reply
Reply-encrypting key enctype (long-term)
All phases KDC status on error on error and "ISSUE"

The implementors of audit plugin will be able to extract the following auditable information:

KDC request:

requested service principal;
client’s principal;
KDC options;
requested ticket start, end and renew_till times;
list of requested addresses;
requested enctypes;
preauth types

KDC reply:

preauth types;
TGT, referral TGT or service ticket with the following level of details:
client and server principals;
flags;
start, end and renew_till times;
authtime;
authentication path - encoded list of transited realms for service ticket or referral TGT (for TGS only);


Other events to consider for the future development:

3. Policy

Policies violation - event description, reason and how to fix it;

4. Secrets (Common Criteria FCS_CKM.1, FCS_CKM.4);

long- and short-term keys creation, manipulation, cleaning.

Design details

Ticket ID

Ticket ID is recorded as part of audit messages. This allows to link tickets to their initial TGT at any stage of the Kerberos exchange.

For the purpose of this project we will create a private to KDC ticket ID: each successfully created ticket will be hashed and recorded into audit log. The administrators will correlate the primary and derived ticket IDs after the fact.

For the future, however, we need a more complex system that would allow to tie the tickets from a successful AS_REQ all the way to the application server. It is marked as an action item in this section.

Request ID

Request ID - hash of the request is recorded as part of audit messages. Using this piece of information an administrator can easily correlate multiple audit events related to a single request.

KDC facing API

/* Audit plugin loaded/unloaded */
krb5_error_code 
load_audit_plugin(krb5_context context);
krb5_error_code 
unload_audit_plugin(krb5_context context);
krb5_boolean
kau_isloaded(krb5_context context);
/* event specific functions */
krb5_error_code
kau_kdc_start(krb5_context context, const int event_id, const int status);
krb5_error_code
kau_kdc_stop(krb5_context context, const int event_id, const int status);
krb5_error_code
kau_asreq(krb5_context context, const int event_id, const int status, audit_state *state);
krb5_error_code
kau_tgsreq(krb5_context context, const int event_id, const int status, audit_state *state);
krb5_error_code
kau_s4u2self(krb5_context context, const int event_id, const int status,  audit_state *state);
krb5_error_code
kau_s4u2proxy(krb5_context context, const int event_id, const int status, audit_state *state);
krb5_error_code
kau_u2u(krb5_context context, const int event_id, const int status, audit_state *state);
/* utilities */
krb5_error_code
kau_init_kdc_req(krb5_context context, krb5_kdc_req *request,  const krb5_fulladdr *from, audit_state **au_state);
krb5_error_code
kau_make_tkt_id(krb5_context context, const krb5_ticket *ticket, char **out);
krb5_error_code
kau_make_req_id(krb5_context context, const krb5_kdc_req *request, char **out);

where event_id references to the Phase (left column of events table), and audit_state structure holds the following information:

typedef struct _audit_state {
   krb5_kdc_req *req_in;   /* request in the original form */
   krb5_kdc_req *req_mod;  /* modified (per protocol) request */
   krb5_kdc_rep  *reply;
   const krb5_fulladdr *from;
   const char    *status; /* KDC status message */
   char *tkt_in_id;       /* primary (TGT) ticket ID */
   char *tkt_out_id;      /* derived (service or referral TGT) ticket ID */
   char *evid_tkt_id;     /* for s4u2proxy - user's evidence ticket ID, for u2u - TGT ticket ID */
   char *req_in_id;       /* original-request ID */
   char *req_mod_id;      /* modified-request ID */
   krb5_int32 sess_etype; /* session key enctype */
   krb5_int32 srv_etype;  /* enctype of the long-term key of service */
   krb5_int32 rep_etype;  /* reply-encrypting key enctype */
   krb5_boolean tkt_renewed;
   krb5_boolean tkt_validated;
   /* referrals */
   krb5_data *cl_realm;   /* remote client's realm */
   /* s4u and u2u */
   krb5_principal s4u2self_user;  /* impersonated user */
   krb5_principal s4u2proxy_user; /* delegated user */
   krb5_principal u2u_user;       /* client for the second ticket */
   char *violation;               /* local or protocol policy problem */
} audit_state;

Pluggable interface

/* Audit plugin vtable */
typedef struct krb5_audit_vtable_st {
   /* Mandatory: name of module. */
   char                 *name;
   int                   conf_options;
   kau_open_fn           open;
   kau_close_fn          close;
   kau_kdc_start_fn      kdc_start;
   kau_kdc_stop_fn       kdc_stop;
   kau_as_req_fn         as_req;
   kau_tgs_req_fn        tgs_req;
   kau_s4u2self_fn       tgs_s4u2self;
   kau_s4u2proxy_fn      tgs_s4u2proxy;
   kau_u2u_fn            tgs_u2u;;
} *krb5_audit_vtable;
 
typedef krb5_error_code
(*kau_open_fn)(kau_ctx *au_ctx);
typedef krb5_error_code
(*kau_close_fn)(kau_ctx au_ctx);
typedef krb5_error_code
(*kau_kdc_start_fn)(kau_ctx au_ctx, const int event_id, int status);
typedef krb5_error_code
(*kau_kdc_stop_fn)(kau_ctx au_ctx, const int event_id, int status);
typedef krb5_error_code
(*kau_as_req_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
typedef krb5_error_code
(*kau_tgs_req_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);
typedef krb5_error_code
(*kau_s4u2self_fn)(kau_ctx au_ctx, const int event_id, int status,  audit_state *state);
typedef krb5_error_code
(*kau_s4u2proxy_fn)(kau_ctx au_ctx, const int event_id, int status,  audit_state *state);
typedef krb5_error_code
(*kau_u2u_fn)(kau_ctx au_ctx, const int event_id, int status, audit_state *state);


Dictionary

The following are proposed basic field names for JSON parsing:

Key Type Comments
tkt_id_in STR primary (TGT) ticket ID
tkt_id_out STR derived (service or referral TGT) ticket ID
client STR client’s principal
service STR requested service principal
kdc_status STR KDC status (“ISSUE” on success)
full_address STR Alternative to "fromport"/"fromaddr"
sess_etype NUM enctype of session key
rep_etype NUM enctype of reply-encrypting key
srv_etype NUM enctype of long-term key of the service key
tkt_renewed BOOL was ticket renewed
tkt_validated BOOL was ticket validated
req.addresses STR requested addresses
req.avail_etypes STR requested/available enc types
req.kdc_options NUM KDC options (forwardable, allow_postdate etc)
req.pa_type STR preauth types
req.tkt_start NUM requested ticket start time
req.tkt_end NUM requested ticket end time
req.tkt_renew_till NUM requested ticket renew-till time
req.tkt_authtime NUM requested ticket authtime
req.sectkt_cname STR client principal in the second ticket (U2U etc)
req.sectkt_sname STR service principal in the second ticket
req.sectkt_flags NUM second ticket flags
req.sectkt_start NUM second ticket start time
req.sectkt_end NUM second ticket end time
req.sectkt_authtime NUM second ticket authtime
req.sectkt_etype NUM second ticket key type
req.sname STR requested service principal
req.cname STR client's principal
rep.sname STR service principal in ticket
rep.cname STR client principal in ticket
rep.pa_type STR reply preauth types
rep.rep_flags NUM ticket flags
rep.rep_authtime NUM ticket authtime
rep.tkt_start NUM ticket start time
rep.tkt_end NUM ticket end time
rep.tkt_renew_till NUM ticket renewed-till time
rep.tr_contents STR ticket transited-realms list

Configuration

The following ./configure option to be added:

--with-audit-plugin=simple
(For demo and testing purposes) Build the audit plugin "simple" and enable audit plugin.


Future work

  1. Standardize a Ticket_ID;
  2. Make reporting auditable events configurable. For example, one can choose to report TGS_REQ, but not AS_REQ;
  3. Sanitize KDC request and KDC reply before passing them to the concrete audit implementation: security sensitive information should not leave KDC boundaries;
  4. Develop Audit system for Preauth and Authdata mechanisms.

Test implementation

We will use libaudit module available on Fedora, Debian, Suse for the first round.

Some "simple" audit plugin will be implemented and Python test system will become aware of its existence. New ./configure --with-audit-plugin option will be introduced to build "simple" audit plugin for testing purpose. If audit is enabled and audit plugin is available, "make check" will store audit messages into audit log file.

References

  1. Common Criteria for Information Technology Security Evaluation http://www.commoncriteriaportal.org/files/ccfiles/CCPART2V3.1R4.pdf
  2. Oracle Solaris Auditing http://docs.oracle.com/cd/E19963-01/html/821-1456/auditov-1.html
  3. Understanding Linux Audit http://doc.opensuse.org/products/draft/SLES/SLES-security_sd_draft/cha.audit.comp.html
  4. Advanced Security Audit Policy Settings http://technet.microsoft.com/en-us/library/dd772712(v=ws.10).aspx
  5. Events Classification in Log Audit http://airccse.org/journal/nsa/0410ijnsa5.pdf
  6. CEE Log Syntax (CLS) Encoding http://cee.mitre.org/language/1.0-beta1/cls.html