S4U2Self is an extension to Kerberos used in Active Directory to allow
a service to request a kerberos ticket to itself from the Kerberos Key
Distribution Center (KDC) for a non-Kerberos authenticated user
(principal in Kerboros parlance). This is useful to allow internal
code paths to be standardized around Kerberos.
S4U2Proxy (constrained-delegation) is an extension of this mechanism
allowing this impersonation to a second service over the network. It
allows a privileged server that obtained a S4U2Self ticket to itself
to then assert the identity of that principal to a second service and
present itself as that principal to get services from the second
service.
There is a flaw in Samba's AD DC in the Heimdal KDC. When the Heimdal
KDC checks the checksum that is placed on the S4U2Self packet by the
server to protect the requested principal against modification, it
does not confirm that the checksum algorithm that protects the user
name (principal) in the request is keyed. This allows a
man-in-the-middle attacker who can intercept the request to the KDC to
modify the packet by replacing the user name (principal) in the
request with any desired user name (principal) that exists in the KDC
and replace the checksum protecting that name with a CRC32 checksum
(which requires no prior knowledge to compute).
This would allow a S4U2Self ticket requested on behalf of user name
(principal) user@EXAMPLE.COM to any service to be changed to a
S4U2Self ticket with a user name (principal) of
Administrator@EXAMPLE.COM. This ticket would then contain the PAC of
the modified user name (principal).
==================
CVSSv3 calculation
==================
CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H (7.5)
=========================
Workaround and Mitigation
=========================
If server does not take privileged actions based on Kerberos tickets
obtained by S4U2Self nor obtains Kerberos tickets via further
S4U2Proxy requests then this issue cannot be exploited.
Note that the path to an exploit is not generic, the KDC is not harmed
by the malicious checksum, it is the client service requesting the
ticket being mislead, because it trusted the KDC to return the correct
ticket and PAC.
It is out of scope for Samba to describe all of the possible tool
chains that might be vulnerable. Here are two examples of possible
exploits in order to explain the issue more clearly.
1). SFU2Self might be used by a web service authenticating an end user
via OAuth, Shibboleth, or other protocols to obtain a S4U2Self
Kerberos service ticket for use by any Kerberos service principal the
web service has a keytab for. One example is acquiring an AFS token
by requesting an afs/cell@REALM service ticket for a client via
SFU2Self. With this exploit an organization that deploys a KDC built
from Heimdal (be it Heimdal directly or vendor versions such as found
in Samba) is vulnerable to privilege escalation attacks.
2). If a server authenticates users using X509 certificates, and then
uses S4U2Self to obtain a Kerberos service ticket on behalf of the
user (principal) in order to authorize access to local resources, a
man-in-the-middle attacker could allow a non-privilaged user to access
privilaged resources being protected by the server, or privilaged
resources being protected by a second server, if the first server uses
the S4U2Proxy extension in order to get a new Kerberos service ticket
to obtain access to the second server.
In both these scenarios under conditions allowing man-in-the-middle
active network protocol manipulation, a malicious user could
authenticate using the non-Kerborized credentials of an unprivileged
user, and then elevate its privileges by intercepting the packet from
the server to the KDC and changing the requested user name (principal).
The only Samba clients that use S4U2Self are:
- the "net ads kerberos pac dump" (debugging) tool.
- the CIFS proxy in the deprecated/developer-only NTVFS file
server. Note this code is not compiled or enabled by default.
In particular, winbindd does *not* use S4U2Self.
Finally, MIT Kerberos and so therefore the experimental MIT KDC backend
for Samba AD is understood not to be impacted.
===============
Further Reading
===============
There is more detail on and a description of the protocols in
[MS-SFU]: Kerberos Protocol Extensions: Service for User and Constrained
Delegation Protocol
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/
=======
Credits
=======
Originally reported by Isaac Boukris and Andrew Bartlett of the Samba
Team and Catalyst.
Patches provided by Isaac Boukris.
Advisory written by Andrew Bartlett of the Samba Team and Catalyst,
with contributions from Isaac Boukris, Jeffrey Altman and Jeremy
Allison.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13685
Change-Id: I4ac69ebf0503eb999a7d497a2c30fe4d293a8cc8
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
Signed-off-by: Jeffrey Altman <jaltman@auristor.com>
Add _krb5_principal_is_anonymous() private API for checking if a principal is
anonymous or not. The third argument determines whether to match authenticated
anonymous, unauthenticated anonymous, or both types of principal.
Allow non-anonymous tickets to be used to obtain an anonymous service ticket,
by setting the anonymous KDC option. Do not include Win2K PAC in anonymous
service tickets. Validate anonymous flags per RFC 8062.
RFC8062 section 4.1 allows clients with long-term KDC keys to set the anonymous
flag; in this case their identity is authenticated but the returned ticket
contains the anonymous principal name as the client name.
kdc: allow authenticated anonymous PKINIT
The KDC PKINIT code conflated the checks for authenticated and unauthenticated
anonymous by only looking at the anonymous KDC request option.
The utility function _kdc_make_anonymous_principalname() previously returned a
principal of "anonymous" rather than "WELLKNOWN/ANONYMOUS", as specified by
RFC8062. This is not used by the AS-REQ code.
The PAC will typically contain information that may reveal the identity of a
principal. Do not include it for anonymous requests, at least until such time
as the PAC plugin API supports indicating that the request was anonymous.
RFC 8062 states that if the client in the AS request is anonymous, the
anonymous KDC option must be set in the request; otherwise, KDC_ERR_BADOPTION
must be returned. We were previously returning KDC_ERR_C_PRINCIPAL_UNKNOWN.
On 32-bit Windows Intel builds the __cdecl and __stdcall calling
conventions are different so labeling the functions that are
exported or assigned to function pointers matters.
Change-Id: I03b6f34baeb9ffb2e683fd979f12f27a5078a4da
If the salt for the AS-REP client key matches the default password salt for the
client principal in the AS-REQ, then it can be omitted from the PA-ETYPE-INFO,
PA-ETYPE-INFO2 (RFC4120) as the client will assume the default salt in its
absence.
Heimdal's current behavior regarding the generation of PA-ETYPE-INFO2
and PA-ETYPE-INFO violates RFC4120 in two ways:
1. when generating responding both PA-ETYPE-INFO2 and PA-ETYPE-INFO
the hints returned in the inverse order: INFO then INFO2 instead
of INFO2 then INFO.
2. the determination that both PA-ETYPE-INFO2 and PA-ETYPE-INFO is
currently based upon the KDC selected enctype when it should be
determine based upon examining the entire enctype list specified
by the requesting client.
This change corrects the behavior to follow the RFC4120 guidance.
Change-Id: I6ebda8a813c25f9296f10314e32e93a22380ca72
This reverts commit 1b7e196e66.
It turns out that, contrary to the referrals draft, Windows does not
canonicalize enterprise principal names if the canonicalize KDC option is
unset.
Enterprise principal client names in AS-REQs should always be canonicalized
irrespective of the setting the canonicalize KDC option. Perform this check in
the KDC rather than HDB.
Do not set the HDB_F_GET_KRBTGT flag unless the client actually requested a TGS
principal.
Mirroring the logic recently introduced in the TGS, this patch modifies the KDC
to perform client and server canonicalization itself rather than relying on the
backend to do so. Per RFC 6806, the behavior is slightly different for the AS
in that the setting of the canonicalize flag in the AS-REQ does impact the
returned names in the ticket. In order to support realm canonicalization or
other custom behavior, we allow the backend to force the KDC to canonicalize by
setting the force-canonicalize flag in the returned client or server entries.
e11abf41 added support in libhdb for always dereferencing principal aliases
during an AS-REQ (where dereferencing refers to enabling alias lookups, and
rewriting the returned entry with the alias name unless canonicalization was
enabled).
Due to the KDC setting HDB_F_FOR_AS_REQ for all lookups from the AS, this
allowed aliases on the TGS itself to be dereferenced during an AS-REQ; however,
on presenting the TGT, the TGS would fail to resolve. Creating an explicit TGS
principal for the aliased realm would work (at least prior to c555ed6a), but
this could be confusing to deploy.
This commit changes enables alias dereferencing when HDB_F_GET_ANY is set,
which essentially means dereference whenever the request is coming from the KDC
(as opposed to, say, kadmin).
We also backout c555ed6a, which changed the TGS to always canonicalize the
server realm, as this breaks serving multiple realms from a single KDC, where
server principals in different realms share a single canonical entry.
HDB_F_CANON is now passed to the backend as a hint only, and per RFC 6806 the
principal name is never changed in TGS replies. (However, for Samba interop,
backends can override this by setting the force-canonicalize HDB flag.)
Refactor plugin framework to use a single list of loaded plugins; add a new
plugin API where DSOs export a load function that can declare dependencies and
export multiple plugins; refactor kadm5 hook API to use krb5 plugin framework.
More information in krb5-plugin(7).
Without it, Windows clients will perform an
extra AS-REQ, causing password lockout count
to increase by two instead of one.
This is an alternative to Samba commit:
978bc8681e74ffa17f96fd5d4355094c4a26691c
One difference however, it doesn't return
ENC_TIMESTAMP in PREAUTH_REQUIRED, only the
necessary ETYPE_INFO{,2} (same as Windows).
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
This is used by Samba to set the canonical realm in
case netbios realm was requested (same as Windows).
Regression introduced by upstream commit:
378f34b4be
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
This can happen in the error path when processing malformed AS
requests with a NULL client name. Bug originally introduced on
Fri Feb 13 09:26:01 2015 +0100 in commit:
a873e21d7c
kdc: base _kdc_fast_mk_error() on krb5_mk_error_ext()
Original patch by Jeffrey Altman <jaltman@secure-endpoints.com>
- Simplify child process creation rate limit by moving
select_sleep() to happen right after the parent fork().
- Consider child pid table slots to be empty if the pid is
non-positive, rather than just -1 or just 0.
- Log warnings should we ever spawn a child with no free
slot to track it, or reap a child that does not match
a tracked slot.
When the termination of a child process is observed by reap_kid() it
clears the pids[] element by assigning it the invalid pid value
(pid_t)-1. However, start_kdc() assumes that the unused pid[[] element
value is 0. As a result, each pid[] element's associated child process
can only be restarted once since start_kdc() will not be able to locate
an unused element.
This change alters start_kdc() to initialize all elements of pids[] to
(pid_t)-1 and use that as the marker for unused elements. By doing so
start_kdc() can properly record child process pids and indefinitely
restart child processes as necessary.
Change-Id: Ia93c9284ab21289994eca7fc9cf1278be7c00683
The ASN.1 functions copy_Realm(), copy_PrincipalName() and
copy_EncryptionKey() can fail. Check the return and perform error
handling as appropriate.
Change-Id: I2b3629d19db96eb41d1cd554cef1dca99745e753
When comparing the first component of a multi-component
string that uses a field separator (e.g., '/' or ':'), be sure
to include the separator in the comparison to ensure that the
comparison does not succeed due to a prefix match.
Change-Id: Ieec3e73cb015a83bb652ec11cd7d83e57755c3d2
Commit f469fc6 (2010-10-02) inadvertently caused the previous hop realm
to not be added to the transit path of issued tickets. This may, in
some cases, enable bypass of capath policy in Heimdal versions 1.5
through 7.2.
Note, this may break sites that rely on the bug. With the bug some
incomplete [capaths] worked, that should not have. These may now break
authentication in some cross-realm configurations.
Each KDC is a kx509 server. The service principal must be of the
form
kca_service/<localhost.domain>@<DEFAULT_REALM>
where localhost.domain is the hostname returned by gethostname()
and <DEFAULT_REALM> is one of the realms for which the KDC has a service
principal "kca_service/<localhost.domain>".
The matching code was broken by a5e77c578e
when krb5_sname_to_principal() began to always return a referral
principal.
Since the second component is a host name update the default principal
type for service "kca_service" to be KRB5_NT_SRV_HST.
Change-Id: I6bd5f90b674ebb7220d8efafa6d339fdc21e1a07
In _kdc_do_kx509() do not free 'principal' until after its last
use. Move declaration to top of function and free it during the
common exit processing.
Introduced by 10a5976e45.
Change-Id: Iaf000eb090b0fa523f04a4864c6b17058d922995
The kdc nowadays forks and restarts worker children. This is nice, but
for leak checking in tests on OS X with leak(1) we really need the
worker to be the one process.
The prior structure of the code was safe but can appear otherwise to
static analyzers since the assignment to pids[i] occurs after exitting
the for() loop.
While here use calloc() instead of malloc()/memset().
Change-Id: I8455aa259fd8c7c17778827937ec26127fe0785c
The _kdc_is_anonymous() helper function must take into account
that principals of type NT-UNKNOWN can match any other principal
type including NT-WELLKNOWN.
Change-Id: I6085b9471f6f1d662119e359491bbdce629ef048