The Kerberos Key Distribution Center Proxy Protocol [MS-KKDCP] provides a
mechanism to proxy Kerberos over HTTPS. Standard Kerberos payload is wrapped
in an additional KDC-PROXY-MESSAGE
sequence and sent as HTTPS POST
request to a proxy server. The proxy server unwraps the request and forwards
its inner request to a KDC. The proxy server usually resides in the DMZ.
The kkdcpasn1
package provides a high performance, low memory usage
decoder and encoder for KDC-PROXY-MESSAGE
. The ASN.1 part is handled
by a C parser auto-generated by asn1c
. The Python interface is
implemented in Cython. On modern hardware it takes less than 15ns to decode
a request and wrap a response.
Author: Christian Heimes cheimes@redhat.com
https://msdn.microsoft.com/en-us/library/hh553774.aspx
>>> import kkdcpasn1
>>> asreq1 = b'''0\x81\xc4\xa0\x81\xb0\x04\x81\xad\x00\x00\x00\xa9j\
\x81\xa60\x81\xa3\xa1\x03\x02\x01\x05\xa2\x03\x02\x01\n\xa3\x0e0\x0c\
0\n\xa1\x04\x02\x02\x00\x95\xa2\x02\x04\x00\xa4\x81\x860\x81\x83\xa0\
\x07\x03\x05\x00@\x00\x00\x10\xa1\x120\x10\xa0\x03\x02\x01\x01\xa1\
\t0\x07\x1b\x05admin\xa2\x0f\x1b\rFREEIPA.LOCAL\xa3"0 \xa0\x03\x02\
\x01\x02\xa1\x190\x17\x1b\x06krbtgt\x1b\rFREEIPA.LOCAL\xa5\x11\x18\
\x0f20150514104238Z\xa7\x06\x02\x04\x11\xc8c\xb5\xa8\x140\x12\x02\x01\
\x12\x02\x01\x11\x02\x01\x10\x02\x01\x17\x02\x01\x19\x02\x01\x1a\xa1\
\x0f\x1b\rFREEIPA.LOCAL'''
>>> result = kkdcpasn1.decode_kkdcp_request(asreq1)
>>> result.realm
'FREEIPA.LOCAL'
>>> result.dclocator_hint
0
>>> result.request_type
'asreq'
>>> result.consumed
169
>>> result.offset
4
>>> result.request
b'...'
Supported request types are
-
asreq
authentication server request (4 bytes header,AS-REQ
) -
tgsreq
ticket granting server request (4 bytes header,TGS-REQ
) -
kpasswd
kpasswd request (10 bytes header,AP-REQ
,KRB-PRIV
), only kpasswd versions0x0001
and0xff80
are supported.
>>> import kkdcpasn1
>>> wrapped = kkdcpasn1.wrap_kkdcp_response(tcp_data)
>>> wrapped = kkdcpasn1.wrap_kkdcp_response(udp_data, add_prefix=True)
KKDCP DEFINITIONS EXPLICIT TAGS ::=
BEGIN
AS-REQ ::= [APPLICATION 10] KDC-REQ
TGS-REQ ::= [APPLICATION 12] KDC-REQ
KDC-REQ ::= SEQUENCE {
pvno [1] INTEGER,
msg-type [2] INTEGER,
padata [3] SEQUENCE OF PA-DATA OPTIONAL,
req-body [4] KDC-REQ-BODY
}
PA-DATA ::= SEQUENCE {
padata-type [1] INTEGER,
pa-data [2] OCTET STRING
}
KDC-REQ-BODY ::= SEQUENCE {
kdc-options [0] KDCOptions,
cname [1] PrincipalName OPTIONAL,
realm [2] Realm,
sname [3] PrincipalName OPTIONAL,
from [4] KerberosTime OPTIONAL,
till [5] KerberosTime,
rtime [6] KerberosTime OPTIONAL,
nonce [7] INTEGER,
etype [8] SEQUENCE OF INTEGER,
addresses [9] HostAddresses OPTIONAL,
enc-authorization-data [10] EncryptedData OPTIONAL,
additional-tickets [11] SEQUENCE OF Ticket OPTIONAL
}
KDCOptions ::= BIT STRING {
reserved(0),
forwardable(1),
forwarded(2),
proxiable(3),
proxy(4),
allow-postdate(5),
postdated(6),
unused7(7),
renewable(8),
unused9(9),
renewable-ok(27),
enc-tkt-in-skey(28),
renew(30),
validate(31)
}
PrincipalName ::= SEQUENCE {
name-type [0] INTEGER,
name-string [1] SEQUENCE OF GeneralString
}
Realm ::= GeneralString
KerberosTime ::= GeneralizedTime
HostAddress ::= SEQUENCE {
addr-type [0] INTEGER,
address [1] OCTET STRING
}
HostAddresses ::= SEQUENCE OF HostAddress
EncryptedData ::= SEQUENCE {
etype [0] INTEGER,
kvno [1] INTEGER OPTIONAL,
cipher [2] OCTET STRING
}
Ticket ::= [APPLICATION 1] SEQUENCE {
tkt-vno [0] INTEGER,
realm [1] Realm,
sname [2] PrincipalName,
enc-part [3] EncryptedData
}
AP-REQ ::= [APPLICATION 14] SEQUENCE {
pvno [0] INTEGER,
msg-type [1] INTEGER,
ap-options [2] APOptions,
ticket [3] Ticket,
authenticator [4] EncryptedData
}
APOptions ::= BIT STRING {
reserved(0),
use-session-key(1),
mutual-required(2)
}
KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
pvno [0] INTEGER,
msg-type [1] INTEGER,
enc-part [3] EncryptedData
}
KDC-PROXY-MESSAGE ::= SEQUENCE {
kerb-message [0] OCTET STRING,
target-domain [1] Realm OPTIONAL,
dclocator-hint [2] INTEGER OPTIONAL
}
END
american fuzzy lop 2.04b (aflpy)
┌─ process timing ─────────────────────────────────────┬─ overall results ─────┐
│ run time : 0 days, 11 hrs, 34 min, 21 sec │ cycles done : 1 │
│ last new path : 0 days, 0 hrs, 23 min, 21 sec │ total paths : 352 │
│ last uniq crash : none seen yet │ uniq crashes : 0 │
│ last uniq hang : 0 days, 6 hrs, 39 min, 45 sec │ uniq hangs : 1 │
├─ cycle progress ────────────────────┬─ map coverage ─┴───────────────────────┤
│ now processing : 170* (48.30%) │ map density : 1507 (2.30%) │
│ paths timed out : 0 (0.00%) │ count coverage : 2.07 bits/tuple │
├─ stage progress ────────────────────┼─ findings in depth ────────────────────┤
│ now trying : havoc │ favored paths : 149 (42.33%) │
│ stage execs : 2030/5000 (40.60%) │ new edges on : 202 (57.39%) │
│ total execs : 5.94M │ total crashes : 0 (0 unique) │
│ exec speed : 142.3/sec │ total hangs : 2 (1 unique) │
├─ fuzzing strategy yields ───────────┴───────────────┬─ path geometry ────────┤
│ bit flips : 137/275k, 20/275k, 9/275k │ levels : 11 │
│ byte flips : 1/34.5k, 1/18.3k, 3/18.6k │ pending : 171 │
│ arithmetics : 25/1.01M, 3/435k, 3/57.7k │ pend fav : 0 │
│ known ints : 10/92.2k, 26/476k, 55/796k │ own finds : 348 │
│ dictionary : 0/0, 0/0, 0/55.0k │ imported : n/a │
│ havoc : 55/2.09M, 0/0 │ variable : 0 │
│ trim : 9.60%/15.4k, 46.75% ├────────────────────────┘
└─────────────────────────────────────────────────────┘ [cpu: 28%]