Difference between revisions of "Projects/Audit"
(Extended Dictionary section) |
m |
||
(20 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | {{project- |
+ | {{project-rel|1.12}} |
− | == |
+ | == Description == |
− | + | This project creates a pluggable audit interface to allow the monitoring of security-related events on the KDC. |
|
− | In future expand Kerberos Audit facility to the application servers, kadmin if it remains desirable. |
||
+ | The interface is considered "experimental", in that API stability is not guaranteed to future major releases. |
||
== Requirements == |
== Requirements == |
||
Line 12: | Line 13: | ||
* build-time enabled; |
* build-time enabled; |
||
* run-time pluggable; |
* run-time pluggable; |
||
− | * simple, so it could be easily replaced with the OS specific implementations; |
+ | * simple and flexible, so it could be easily replaced with the OS specific and third-parties implementations; |
== Events == |
== Events == |
||
− | This section details the categories of the auditable events and the associated information. |
||
+ | We consider events under the categorization of the Common Criteria Class FIA. |
||
− | ===Audit module loaded/unloaded=== |
||
+ | This section details the categories of the auditable events and the associated data. |
||
− | :: Startup and shutdown of the audit system must be recorded by audit system; |
||
− | ===KDC started/stopped=== |
||
+ | 1. Startup and shutdown of the KDC must be recorded by audit system; |
||
− | :: Startup and shutdown of the KDC must be recorded by audit system; |
||
− | ===Authentication=== |
||
+ | 2. The bulk of the audit information will be produced while processing AS and TGS requests. Though KDC request processing can be grouped into several logical phases, we generate (usually) only two events, one at the initial receipt of a request, and a second, final, one before sending a reply. All events relating to the same request can be linked together in the audit log by a 32-character alphanumeric string (about 190 bits of uniqueness) which is randomly generated at the start of processing. If the request is a S4U2Self or S4U2Proxy request, an additional audit event will be generated with information particular to the S4U request. The following table lists the logical stages of KDC processing, and which components are logged in the AS and TGS cases: |
||
− | (Common Criteria Class FIA) |
||
− | ====AS exchange==== |
||
+ | {| class="wikitable" style="border: 3px solid #59121e" |
||
− | :: [[#Ticket ID|ticket ID]] (if available); |
||
+ | |+ |
||
− | :: KDC time; |
||
+ | |- |
||
− | :: client’s principal; |
||
+ | ! Phase |
||
− | :: requested service principal; |
||
+ | ! style="padding-left: 2em; padding-right: 2em;" | Data to be logged |
||
− | :: KDC status message (“ISSUE” on success); |
||
+ | ! AS_REQ |
||
− | :: client’s address and port; |
||
+ | ! TGS_REQ |
||
− | :: PA error; |
||
+ | |- |
||
− | :: chosen by KDC enctype; |
||
+ | |rowspan=3|Authenticate request content and client |
||
− | :: session key cleared (Common Criteria FCS_CKM.1, FCS_CKM.4); |
||
+ | | client’s address and port || ✔ || ✔ |
||
− | :: kdc request: |
||
+ | |- |
||
− | ::: kdc options; |
||
+ | | original KDC request and [[#Request ID| request ID ]] || ✔ || ✔ |
||
− | ::: requested ticket start/end/renew_till times; |
||
+ | |- |
||
− | ::: requested/available enctypes; |
||
+ | | primary [[#Ticket ID|ticket ID]] || ✗ ||(S4U:front-end server's) TGT |
||
− | ::: 2nd [[#Ticket details|ticket]]; |
||
+ | |- |
||
− | ::: AD type; |
||
+ | |rowspan=3|Determine service principal |
||
− | ::: PA type; |
||
+ | | modified KDC request and [[#Request ID|request ID]] ||✔ || ✔ |
||
− | ::: addresses; |
||
+ | |- |
||
− | :: kdc reply: |
||
+ | | cross-realm referral || ✗ || service principal, TGS |
||
− | ::: [[#Ticket details|ticket]]; |
||
+ | |- |
||
− | ::: client principal; |
||
+ | | user-to-user: client in the 2nd ticket || ✗ ||✔ |
||
− | ::: PA type. |
||
+ | |- |
||
+ | |rowspan=2|Validate policies |
||
+ | | local policy violation ||✔ || ✔ |
||
+ | |- |
||
+ | | protocol constraints ||✗ || S4U2Proxy, S4U2Self |
||
+ | |- |
||
+ | |rowspan=5|Issue ticket |
||
+ | | ticket renewed ||✗ || ✔ |
||
+ | |- |
||
+ | | ticket validated ||✗ || ✔ |
||
+ | |- |
||
+ | | session key enctype (short-term) ||✔ || ✔ |
||
+ | |- |
||
+ | | enctype of the service's long-term key||✗ || ✔ |
||
+ | |- |
||
+ | | derived [[#Ticket ID|ticket ID]]|| TGT || service or referral TGT |
||
+ | |- |
||
+ | |rowspan=2|Encrypt reply |
||
+ | | KDC reply ||✔ || ✔ |
||
+ | |- |
||
+ | | Reply-encrypting key enctype (long-term) ||✔ || ✔ |
||
+ | |- |
||
+ | |rowspan=1|All phases |
||
+ | | Additional info(KDC status,policy details,etc)|| ✔ ||✔ |
||
+ | |- |
||
+ | |} |
||
− | ====TGS exchange==== |
||
+ | The following information will be made available to audit plugins: |
||
− | :: [[#Ticket ID|ticket ID]] (if available); |
||
− | :: KDC time; |
||
− | :: KDC status message (“ISSUE” on success); |
||
− | :: client’s address and port; |
||
− | :: chosen by KDC enctype; |
||
− | :: session key cleared (Common Criteria FCS_CKM.1, FCS_CKM.4); |
||
− | :: client’s flags; |
||
− | :: cross realm name; |
||
− | :: alternate client principal; |
||
− | :: alternate server principal; |
||
− | :: u2u requested server principal; |
||
− | :: is it referral request; |
||
− | :: was ticket renewed; |
||
− | :: kdc request: |
||
− | ::: requested service principal; |
||
− | ::: client’s principal; |
||
− | ::: addresses; |
||
− | ::: requested/available enctypes; |
||
− | ::: KDC options; |
||
− | ::: number of second [[#Ticket details|tickets]]; |
||
− | ::: requested ticket start/end/renew_till times; |
||
− | ::: AD type; |
||
− | ::: PA type; |
||
− | :: kdc reply: |
||
− | ::: client principal; |
||
− | ::: PA type; |
||
− | ::: [[#Ticket details|ticket]]. |
||
− | ====Policy==== |
||
+ | : a unique [[#Request ID| request ID ]] |
||
− | :: Policies violation when processing requests; |
||
+ | : the complete KDC request structure |
||
− | ::AS request; |
||
+ | : the KDC reply structure (possibly only partially populated) |
||
− | ::TGS request; |
||
+ | : the client's IP address and port number |
||
− | ::S4U2PROXY request. |
||
+ | : the stage of KDC processing at which the audit event was triggered |
||
+ | : the KDC status string (as appears in kdc.log) |
||
+ | : [[#Ticket ID|ticket IDs]] (checksums) for any supplied tickets or ticket to be returned |
||
+ | : the remote client's realm (for referrals) |
||
+ | : the impersonated user for an S4U2Self request |
||
+ | : the "type of violation" which caused the request to fail, if applicable |
||
− | ====Ticket details==== |
||
+ | Other events to consider for the future development: |
||
− | ::client and server principals; |
||
− | ::flags; |
||
− | ::start/end/renew_till times; |
||
− | ::authtime; |
||
− | ::transited encoding type and contents; |
||
− | ::key type; |
||
− | ::addresses. |
||
+ | 3. Further details about policy viloations |
||
+ | :Event description, reason and how to fix it; |
||
+ | 4. Secrets (Common Criteria FCS_CKM.1, FCS_CKM.4); |
||
+ | :long- and short-term key creation, manipulation, cleaning. |
||
== Design details == |
== Design details == |
||
− | |||
− | The following are highlights of this new feature: |
||
====Ticket ID==== |
====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. |
|
− | : Ticket ID is created as a hash of AS session key or client principal name plus timestamp or some other way; |
||
− | : TODO: Consider a new authorization data element AD_TKT_ID per http://tools.ietf.org/html/draft-ietf-krb-wg-cammac-04 draft to securely communicate ticket id between all Kerberos exchange participants. |
||
− | ====Hybrid==== |
||
+ | 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. |
||
− | The proposal is a hybrid of variadic key-type-value triplet (KTV) and one-API-per-event approaches. |
||
− | On the KDC side call audit event-specific functions, whose input consists of the event-id, event-status and event-specific structure. If event-specific callback is implemented by the audit plugin, strip the event-specific structure from the security sensitive information and then pass the pointer to the event-specific structure to the plugin. Otherwise, fallback to the generic function with variadic KTV arguments. In the latter case all non-string values should be converted into the strings and the key-types serve as a hint to the plugin implementor about the "original" type of the key-value. |
||
+ | 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 [[#Future work|this]] section. |
||
+ | ====Request ID==== |
||
+ | Request ID is a randomly generated alpha-numeric string. Using this ID an administrator can easily correlate multiple audit events related to a single request. It should be informative both in cases when the request is sent to multiple KDCs, or to the same KDC multiple times. |
||
=== KDC facing API === |
=== KDC facing API === |
||
Line 116: | Line 113: | ||
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, |
+ | 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, |
+ | kau_kdc_stop(krb5_context context, const int event_id, const int status); |
− | krb5_error_code |
+ | krb5_error_code |
− | + | kau_asreq(krb5_context context, const int event_id, const int status, audit_state *state); |
|
− | krb5_error_code |
+ | 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| 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; /* additional information string */ |
||
+ | 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 131: | Line 130: | ||
typedef struct krb5_audit_vtable_st { |
typedef struct krb5_audit_vtable_st { |
||
/* Mandatory: name of module. */ |
/* Mandatory: name of module. */ |
||
− | char *name; |
+ | char *name; |
− | + | int conf_options; |
|
− | + | kau_open_fn open; |
|
− | + | 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_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_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_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_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_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); |
||
− | 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. |
||
− | |||
− | ==== Example ==== |
||
− | |||
− | krb5_error_code |
||
− | kau_as_req(krb5_context context, struct as_req_state *state, |
||
− | krb5_error_code status) |
||
− | { |
||
− | krb5_error_code rc = 0; |
||
− | ... |
||
− | /* If audit plugin event-specific callback is implemented, call it */ |
||
− | if (hdl->vt.as_req) { |
||
− | rc = hdl->vt.as_req(hdl->au_ctx, event_id, event_status, state); |
||
− | return rc; |
||
− | } |
||
− | /* Otherwise, try the generic one. */ |
||
− | if (hdl->vt.generic) |
||
− | rc = rec_as_req(hdl->au_ctx, event_id, event_status, state); |
||
− | return rc; |
||
− | } |
||
− | |||
− | static krb5_error_code |
||
− | rec_as_req(krb5_context context, struct as_req_state_san *state, |
||
− | krb5_error_code status) |
||
− | { |
||
− | krb5_error_code rc = 0; |
||
− | ... |
||
− | /* All values with TYPE_NUM type-hint are string representations of |
||
− | * their numeric conterparts in 'state' structure. |
||
− | */ |
||
− | hdl->vt.record(hdl->au_ctx, event_id, event_status, |
||
− | "tkt_id", TYPE_NUM, tkt_id, // state->tkt_id |
||
− | "kdc_status", TYPE_STR, state->status, |
||
− | "full_address", TYPE_STR, state->full_address, |
||
− | "skey_etype", TYPE_NUM, session_key_enctype, // state->session_key_enctype |
||
− | "pa_error", TYPE_NUM, preauth_err, // state->preauth_err |
||
− | /* request */ |
||
− | "req.msg_type", TYPE_STR, state->req_msg_type, |
||
− | "req.client", TYPE_STR, state->req_client, |
||
− | "req.server", TYPE_STR, state->req_server, |
||
− | "req.kdc_options", TYPE_STR, state->req_kdc_options, |
||
− | "req.start", TYPE_NUM, req_from, // state->req_from |
||
− | "req.end", TYPE_NUM, req_end, // state->req_end |
||
− | "req.renew_till", TYPE_NUM, req_time, // state->req_rtime |
||
− | /* reply */ |
||
− | "rep.msg_type", TYPE_STR,state->rep_msg_type, |
||
− | "rep.client", TYPE_STR, state->rep_client, |
||
− | "rep.server", TYPE_STR, state->rep_server, |
||
− | "rep.tkt.server", TYPE_STR, state->rep_tkt_server, |
||
− | "rep.tkt.flags", TYPE_NUM, rep_tkt_flags, // state->rep_tkt_flags |
||
− | "rep.tkt.start", TYPE_NUM, rep_tarttime, // state->rep_tarttime |
||
− | "rep.tkt.end", TYPE_NUM, rep_endtime, // pstate->rep_endtime, |
||
− | "rep.tkt.renew_till", TYPE_NUM, rep_renew_till, // state->rep_renew_till |
||
− | "rep.tkt.authtime", TYPE_NUM, rep_authtime, // state->rep_authtime, |
||
− | "rep.tkt.tr_type", TYPE_NUM, rep_transited_type // state->rep_transited_type |
||
− | "rep.tkt.skey_etype", TYPE_NUM, rep_session_enctype, // state->rep_session_enctype |
||
− | "rep.tkt.caddrs", TYPE_STR, state->rep_caddrs |
||
− | ); |
||
− | return rc; |
||
− | } |
||
+ | == JSON based audit module == |
||
− | == Dictionary== |
||
+ | We will use libaudit module available on Fedora, Debian, SuSe for the first round. The new JSON utility library will be built to parse Kerberos specific structures. The "simple" audit module will be statically linked to this library. |
||
− | The |
+ | The following is a proposed ''Dictionary '' - the basic field names for JSON parsing: |
{| class="wikitable" style="border: 3px solid #59121e" |
{| class="wikitable" style="border: 3px solid #59121e" |
||
Line 235: | Line 170: | ||
! Comments |
! Comments |
||
|- |
|- |
||
− | | |
+ | | event_success || style="padding-left: 2em "| INT || event was success or failure |
|- |
|- |
||
− | | |
+ | | event_name || style="padding-left: 2em "| STR || name of the event (KDC_START, AS_REQ etc) |
|- |
|- |
||
− | | |
+ | | stage || style="padding-left: 2em "| INT || stage in the KDC exchange processing |
|- |
|- |
||
− | | |
+ | | tkt_id_in || style="padding-left: 2em "| STR || primary (TGT) ticket ID |
|- |
|- |
||
− | | |
+ | | tkt_id_out || style="padding-left: 2em "| STR || derived (service or referral TGT) ticket ID |
|- |
|- |
||
− | | |
+ | | req_id || style="padding-left: 2em "| STR || request ID |
|- |
|- |
||
− | | |
+ | | kdc_status || style="padding-left: 2em "| STR|| Additional information string |
|- |
|- |
||
− | | |
+ | | fromaddr || style="padding-left: 2em "| STR || client's address |
|- |
|- |
||
− | | |
+ | | fromport || style="padding-left: 2em "| NUM || client's port |
|- |
|- |
||
− | | |
+ | |sess_etype || style="padding-left: 2em "| NUM || enctype of session key |
|- |
|- |
||
− | | |
+ | |rep_etype || style="padding-left: 2em "| NUM || enctype of reply-encrypting key |
|- |
|- |
||
− | | |
+ | |srv_etype || style="padding-left: 2em "| NUM || enctype of long-term key of the service key |
|- |
|- |
||
− | | |
+ | |tkt_renewed|| style="padding-left: 2em "| BOOL || was ticket renewed |
− | |- |
||
− | |alts_princ || style="padding-left: 2em "| STR || alternate server principal |
||
|- |
|- |
||
− | | |
+ | |tkt_validated|| style="padding-left: 2em "| BOOL || was ticket validated |
− | |- |
||
− | |is_referral|| style="padding-left: 2em "| BOOL || is it referral request |
||
− | |- |
||
− | |tkt_renewed|| style="padding-left: 2em "| BOOL || was ticket renewed |
||
|- |
|- |
||
|req.addresses || style="padding-left: 2em "| STR || requested addresses |
|req.addresses || style="padding-left: 2em "| STR || requested addresses |
||
Line 268: | Line 203: | ||
|- |
|- |
||
|req.kdc_options || style="padding-left: 2em "| NUM || KDC options (forwardable, allow_postdate etc) |
|req.kdc_options || style="padding-left: 2em "| NUM || KDC options (forwardable, allow_postdate etc) |
||
− | |- |
||
− | |req.pa_type || style="padding-left: 2em "| STR|| PA type |
||
− | |- |
||
− | |req.ad_type || style="padding-left: 2em "| STR || AD type |
||
|- |
|- |
||
|req.tkt_start || style="padding-left: 2em "| NUM || requested ticket start time |
|req.tkt_start || style="padding-left: 2em "| NUM || requested ticket start time |
||
Line 279: | Line 210: | ||
|req.tkt_renew_till || style="padding-left: 2em "| NUM || requested ticket renew-till time |
|req.tkt_renew_till || style="padding-left: 2em "| NUM || requested ticket renew-till time |
||
|- |
|- |
||
− | | |
+ | |req.tkt_authtime || style="padding-left: 2em "| NUM || requested ticket authtime |
+ | |- |
||
+ | | req.sectkt_cname|| style="padding-left: 2em "| STR || client principal in the second ticket (U2U etc) |
||
+ | |- |
||
+ | | req.sectkt_sname|| style="padding-left: 2em "| STR || service principal in the second ticket |
||
+ | |- |
||
+ | | req.sectkt_flags|| style="padding-left: 2em "| NUM || second ticket flags |
||
+ | |- |
||
+ | | req.sectkt_start|| style="padding-left: 2em "| NUM || second ticket start time |
||
+ | |- |
||
+ | | req.sectkt_end|| style="padding-left: 2em "| NUM || second ticket end time |
||
+ | |- |
||
+ | | req.sectkt_authtime|| style="padding-left: 2em "| NUM || second ticket authtime |
||
+ | |- |
||
+ | | req.sectkt_etype|| style="padding-left: 2em "| NUM || second ticket key type |
||
|- |
|- |
||
|req.sname || style="padding-left: 2em "| STR || requested service principal |
|req.sname || style="padding-left: 2em "| STR || requested service principal |
||
Line 289: | Line 220: | ||
| rep.cname || style="padding-left: 2em "| STR || client principal in ticket |
| rep.cname || style="padding-left: 2em "| STR || client principal in ticket |
||
|- |
|- |
||
− | | rep.pa_type || style="padding-left: 2em "| STR || reply |
+ | | rep.pa_type || style="padding-left: 2em "| STR || reply preauth types |
− | |- |
||
− | | rep.caddrs || style="padding-left: 2em "| STR || addresses in ticket |
||
− | |- |
||
− | | rep.rep_flags || style="padding-left: 2em "| NUM || ticket flags |
||
− | |- |
||
− | | rep.ad_type || style="padding-left: 2em "| STR || ticket AD type |
||
|- |
|- |
||
| rep.rep_authtime || style="padding-left: 2em "| NUM || ticket authtime |
| rep.rep_authtime || style="padding-left: 2em "| NUM || ticket authtime |
||
Line 298: | Line 229: | ||
|- |
|- |
||
| rep.tkt_renew_till|| style="padding-left: 2em "| NUM || ticket renewed-till time |
| rep.tkt_renew_till|| style="padding-left: 2em "| NUM || ticket renewed-till time |
||
− | |- |
||
− | |rep.tr_type|| style="padding-left: 2em "| NUM || ticket transited type |
||
|- |
|- |
||
|rep.tr_contents|| style="padding-left: 2em "| STR|| ticket transited-realms list |
|rep.tr_contents|| style="padding-left: 2em "| STR|| ticket transited-realms list |
||
|- |
|- |
||
|} |
|} |
||
− | |||
− | |||
− | |||
− | |||
== Configuration == |
== Configuration == |
||
− | The following ./configure option to be added: |
+ | 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. |
||
+ | --with-audit-plugin |
||
+ | For example,'' --with-audit-plugin=simple'', where ''simple'' is the name of the audit plugin module |
||
− | == Future work == |
||
− | # Make reporting auditable events configurable. For example, one can choose to report TGS_REQ, but not AS_REQ etc; |
||
+ | == Test == |
||
− | # Define and make configurable the DETAILED and BASIC levels of the events. |
||
+ | A testable audit module, k5audit_test, will be built, and enabled for a python test program which is added. This test module uses the internal libauditjenc library to generate a JSON encoding of the audit event, and writes that encoded string to a flat file, which is parsed by the python test program. |
||
− | == Test implementation == |
||
− | We will use libaudit module available on Fedora, Debian, Suse for the first round. |
||
+ | ==Future work== |
||
+ | |||
+ | # Standardize a ''Ticket ID''; |
||
+ | # Make reporting auditable events configurable. For example, one can choose to report TGS_REQ, but not AS_REQ; |
||
+ | # Sanitize ''KDC request'' and ''KDC reply'' before passing them to the concrete audit implementation: security sensitive information should not leave KDC boundaries; |
||
+ | # Develop audit system for Preauth and Authdata mechanisms; |
||
+ | # Expand Kerberos Audit facility to the application servers and kadmin. |
||
− | 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 == |
== References == |
||
Line 336: | Line 265: | ||
# Events Classification in Log Audit http://airccse.org/journal/nsa/0410ijnsa5.pdf |
# Events Classification in Log Audit http://airccse.org/journal/nsa/0410ijnsa5.pdf |
||
# CEE Log Syntax (CLS) Encoding http://cee.mitre.org/language/1.0-beta1/cls.html |
# CEE Log Syntax (CLS) Encoding http://cee.mitre.org/language/1.0-beta1/cls.html |
||
+ | |||
+ | |||
+ | == Commits == |
||
+ | |||
+ | e63b2c9b0ed3b19f6aa1ac90222240690a1bc55b KDC Audit infrastructure and plugin implementation |
||
+ | 1003f0173f266a6428ccf2c89976f0029d3ee831 KDC Audit infrastructure and plugin implementation (merged) |
||
+ | 5036f91e7b61a73a1ec2d39ce1cc6bbf60dd82ab Fix audit test module initialization |
||
+ | |||
+ | Completed in {{bug|7712}} and {{bug|7713}} |
||
+ | |||
+ | |||
+ | == Release Notes == |
||
+ | |||
+ | Administrator experience: |
||
+ | |||
+ | * Add an experimental pluggable interface for auditing KDC processing. This interface may change in a backwards-incompatible way in a future release. |
Latest revision as of 12:01, 29 October 2013
Contents
Description
This project creates a pluggable audit interface to allow the monitoring of security-related events on the KDC.
The interface is considered "experimental", in that API stability is not guaranteed to future major releases.
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
We consider events under the categorization of the 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. The bulk of the audit information will be produced while processing AS and TGS requests. Though KDC request processing can be grouped into several logical phases, we generate (usually) only two events, one at the initial receipt of a request, and a second, final, one before sending a reply. All events relating to the same request can be linked together in the audit log by a 32-character alphanumeric string (about 190 bits of uniqueness) which is randomly generated at the start of processing. If the request is a S4U2Self or S4U2Proxy request, an additional audit event will be generated with information particular to the S4U request. The following table lists the logical stages of KDC processing, and which components are logged in the AS and TGS cases:
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 | Additional info(KDC status,policy details,etc) | ✔ | ✔ |
The following information will be made available to audit plugins:
- a unique request ID
- the complete KDC request structure
- the KDC reply structure (possibly only partially populated)
- the client's IP address and port number
- the stage of KDC processing at which the audit event was triggered
- the KDC status string (as appears in kdc.log)
- ticket IDs (checksums) for any supplied tickets or ticket to be returned
- the remote client's realm (for referrals)
- the impersonated user for an S4U2Self request
- the "type of violation" which caused the request to fail, if applicable
Other events to consider for the future development:
3. Further details about policy viloations
- Event description, reason and how to fix it;
4. Secrets (Common Criteria FCS_CKM.1, FCS_CKM.4);
- long- and short-term key 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 is a randomly generated alpha-numeric string. Using this ID an administrator can easily correlate multiple audit events related to a single request. It should be informative both in cases when the request is sent to multiple KDCs, or to the same KDC multiple times.
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; /* additional information string */ 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);
JSON based audit module
We will use libaudit module available on Fedora, Debian, SuSe for the first round. The new JSON utility library will be built to parse Kerberos specific structures. The "simple" audit module will be statically linked to this library.
The following is a proposed Dictionary - the basic field names for JSON parsing:
Key | Type | Comments |
---|---|---|
event_success | INT | event was success or failure |
event_name | STR | name of the event (KDC_START, AS_REQ etc) |
stage | INT | stage in the KDC exchange processing |
tkt_id_in | STR | primary (TGT) ticket ID |
tkt_id_out | STR | derived (service or referral TGT) ticket ID |
req_id | STR | request ID |
kdc_status | STR | Additional information string |
fromaddr | STR | client's address |
fromport | NUM | client's port |
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.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_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
For example, --with-audit-plugin=simple, where simple is the name of the audit plugin module
Test
A testable audit module, k5audit_test, will be built, and enabled for a python test program which is added. This test module uses the internal libauditjenc library to generate a JSON encoding of the audit event, and writes that encoded string to a flat file, which is parsed by the python test program.
Future work
- Standardize a Ticket ID;
- Make reporting auditable events configurable. For example, one can choose to report TGS_REQ, but not AS_REQ;
- Sanitize KDC request and KDC reply before passing them to the concrete audit implementation: security sensitive information should not leave KDC boundaries;
- Develop audit system for Preauth and Authdata mechanisms;
- Expand Kerberos Audit facility to the application servers and kadmin.
References
- Common Criteria for Information Technology Security Evaluation http://www.commoncriteriaportal.org/files/ccfiles/CCPART2V3.1R4.pdf
- Oracle Solaris Auditing http://docs.oracle.com/cd/E19963-01/html/821-1456/auditov-1.html
- Understanding Linux Audit http://doc.opensuse.org/products/draft/SLES/SLES-security_sd_draft/cha.audit.comp.html
- Advanced Security Audit Policy Settings http://technet.microsoft.com/en-us/library/dd772712(v=ws.10).aspx
- Events Classification in Log Audit http://airccse.org/journal/nsa/0410ijnsa5.pdf
- CEE Log Syntax (CLS) Encoding http://cee.mitre.org/language/1.0-beta1/cls.html
Commits
e63b2c9b0ed3b19f6aa1ac90222240690a1bc55b KDC Audit infrastructure and plugin implementation 1003f0173f266a6428ccf2c89976f0029d3ee831 KDC Audit infrastructure and plugin implementation (merged) 5036f91e7b61a73a1ec2d39ce1cc6bbf60dd82ab Fix audit test module initialization
Completed in [krbdev.mit.edu #7712] and [krbdev.mit.edu #7713]
Release Notes
Administrator experience:
- Add an experimental pluggable interface for auditing KDC processing. This interface may change in a backwards-incompatible way in a future release.