From a8d2ee2e83269a07d7cba0b3990ebf135e7914d5 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sun, 27 Oct 2019 14:02:00 +0200 Subject: [PATCH 1/4] samba-tool: add user-sensitive command to set not-delegated flag Signed-off-by: Isaac Boukris --- python/samba/netcmd/user.py | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py index cadd80fd991..ee11a6ad682 100644 --- a/python/samba/netcmd/user.py +++ b/python/samba/netcmd/user.py @@ -2827,6 +2827,63 @@ unixHomeDirectory: {6} .format(username)) +class cmd_user_sensitive(Command): + """Set/unset or show UF_NOT_DELEGATED for an account.""" + + synopsis = "%prog [(show|on|off)] [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "credopts": options.CredentialsOptions, + "versionopts": options.VersionOptions, + } + + takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", type=str, + metavar="URL", dest="H"), + ] + + takes_args = ["accountname", "cmd"] + + def run(self, accountname, cmd, H=None, credopts=None, sambaopts=None, + versionopts=None): + + if cmd not in ("show", "on", "off"): + raise CommandError("invalid argument: '%s' (choose from 'show', 'on', 'off')" % cmd) + + lp = sambaopts.get_loadparm() + creds = credopts.get_credentials(lp, fallback_machine=True) + sam = SamDB(url=H, session_info=system_session(), + credentials=creds, lp=lp) + + search_filter = "sAMAccountName=%s" % ldb.binary_encode(accountname) + flag = dsdb.UF_NOT_DELEGATED; + + if cmd == "show": + res = sam.search(scope=ldb.SCOPE_SUBTREE, expression=search_filter, + attrs=["userAccountControl"]) + if len(res) == 0: + raise Exception("Unable to find account where '%s'" % search_filter) + + uac = int(res[0].get("userAccountControl")[0]) + + self.outf.write("Account-DN: %s\n" % str(res[0].dn)) + self.outf.write("UF_NOT_DELEGATED: %s\n" % bool(uac & flag)) + + return + + if cmd == "on": + on = True + elif cmd == "off": + on = False + + try: + sam.toggle_userAccountFlags(search_filter, flag, flags_str="Not-Delegated", + on=on, strict=True) + except Exception as err: + raise CommandError(err) + + class cmd_user(SuperCommand): """User management.""" @@ -2846,3 +2903,4 @@ class cmd_user(SuperCommand): subcommands["show"] = cmd_user_show() subcommands["move"] = cmd_user_move() subcommands["addunixattrs"] = cmd_user_add_unix_attrs() + subcommands["sensitive"] = cmd_user_sensitive() -- 2.21.0 From 45cc72cbb1a90b685db84c87fdc503a5dccc0f5a Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Sun, 27 Oct 2019 19:22:43 +0200 Subject: [PATCH 2/4] CVE-2019-14870: mit-kdc: enforce delegation_not_allowed flag and work around a bug in old MIT kdc used in ubuntu CI. This partially reverts commit 84c4b91f. Signed-off-by: Isaac Boukris --- selftest/old_mit_kdc_forward_bug_knownfail | 9 +++++++++ selftest/wscript | 3 +++ source4/kdc/sdb_to_kdb.c | 17 ++++++----------- wscript_configure_system_mitkrb5 | 4 ++++ 4 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 selftest/old_mit_kdc_forward_bug_knownfail diff --git a/selftest/old_mit_kdc_forward_bug_knownfail b/selftest/old_mit_kdc_forward_bug_knownfail new file mode 100644 index 00000000000..ec9a603d649 --- /dev/null +++ b/selftest/old_mit_kdc_forward_bug_knownfail @@ -0,0 +1,9 @@ +^samba.tests.pam_winbind\(trust_f_both[1-4]\+krb5\) +^samba.tests.pam_winbind\(trust_e_both[1-4]\+krb5\) +^samba4.blackbox.kinit_trust.Test login with kerberos ccache +^samba4.blackbox.kinit_trust.Test login with user kerberos ccache +^samba4.blackbox.kinit_trust.Test login with user kerberos lowercase realm +^samba4.blackbox.kinit_trust.Test user login with the first outgoing secret +^samba4.blackbox.kinit_trust.Test user login with the changed outgoing secret +^samba4.blackbox.kinit_trust.check time with kerberos ccache +^samba4.blackbox.trust_token.Test token with kerberos diff --git a/selftest/wscript b/selftest/wscript index 4d03eb76842..b7cc8490f4b 100644 --- a/selftest/wscript +++ b/selftest/wscript @@ -142,6 +142,9 @@ def cmd_testonly(opt): '--flapping=${srcdir}/selftest/flapping ' '--flapping=${srcdir}/selftest/flapping.d') + if CONFIG_SET(opt, 'HAVE_MIT_KDC_FRWD_BUG'): + env.FILTER_XFAIL += ' --expected-failures=${srcdir}/selftest/old_mit_kdc_forward_bug_knownfail' + if Options.options.FAIL_IMMEDIATELY: env.FILTER_XFAIL += ' --fail-immediately' diff --git a/source4/kdc/sdb_to_kdb.c b/source4/kdc/sdb_to_kdb.c index 1411b0f5f66..2981f180333 100644 --- a/source4/kdc/sdb_to_kdb.c +++ b/source4/kdc/sdb_to_kdb.c @@ -36,18 +36,13 @@ static int SDBFlags_to_kflags(const struct SDBFlags *s, if (s->initial) { *k |= KRB5_KDB_DISALLOW_TGT_BASED; } - /* - * Do not set any disallow rules for forwardable, proxiable, - * renewable, postdate and server. - * - * The KDC will take care setting the flags based on the incoming - * ticket. - */ - if (s->forwardable) { - ; + /* The forwardable and proxiable flags are set according to client and + * server attributes. */ + if (!s->forwardable) { + *k |= KRB5_KDB_DISALLOW_FORWARDABLE; } - if (s->proxiable) { - ; + if (!s->proxiable) { + *k |= KRB5_KDB_DISALLOW_PROXIABLE; } if (s->renewable) { ; diff --git a/wscript_configure_system_mitkrb5 b/wscript_configure_system_mitkrb5 index b05ac3f3e50..f72d751d9d3 100644 --- a/wscript_configure_system_mitkrb5 +++ b/wscript_configure_system_mitkrb5 @@ -77,6 +77,10 @@ if conf.env.KRB5_CONFIG: else: Logs.info('MIT Kerberos %s detected, MIT krb5 build can proceed' % (krb5_version)) + # Old MIT KDC had a bug and was overly enforcing forwardable flag (fixed upstream in 08e948cce2) + if parse_version(krb5_version) < parse_version('1.17'): + conf.DEFINE('HAVE_MIT_KDC_FRWD_BUG', 1) + conf.CHECK_CFG(args="--cflags --libs", package="com_err", uselib_store="com_err") conf.CHECK_FUNCS_IN('_et_list', 'com_err') conf.CHECK_HEADERS('com_err.h', lib='com_err') -- 2.21.0 From d5fd28d7603e68e7bc146b52e175914a27c92f8c Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Wed, 30 Oct 2019 15:59:16 +0100 Subject: [PATCH 3/4] CVE-2019-14870: heimdal: add S4U test for delegation_not_allowed Signed-off-by: Isaac Boukris --- selftest/knownfail.d/heimdal_not_delegated | 1 + source4/selftest/tests.py | 1 + testprogs/blackbox/test_s4u_heimdal.sh | 73 ++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 selftest/knownfail.d/heimdal_not_delegated create mode 100755 testprogs/blackbox/test_s4u_heimdal.sh diff --git a/selftest/knownfail.d/heimdal_not_delegated b/selftest/knownfail.d/heimdal_not_delegated new file mode 100644 index 00000000000..bfc382a3fc2 --- /dev/null +++ b/selftest/knownfail.d/heimdal_not_delegated @@ -0,0 +1 @@ +^samba4.blackbox.krb5.s4u diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 642dc680fa4..2caf0725b68 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -458,6 +458,7 @@ if have_heimdal_support: plantestsuite("samba4.blackbox.kinit_trust", "fl2003dc:local", [os.path.join(bbdir, "test_kinit_trusts_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$TRUST_SERVER', '$TRUST_USERNAME', '$TRUST_PASSWORD', '$TRUST_REALM', '$TRUST_DOMAIN', '$PREFIX', "external", "arcfour-hmac-md5"]) plantestsuite("samba4.blackbox.export.keytab", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_export_keytab_heimdal.sh"), '$SERVER', '$USERNAME', '$REALM', '$DOMAIN', "$PREFIX", smbclient4]) plantestsuite("samba4.blackbox.kpasswd", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kpasswd_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', "$PREFIX/ad_dc_ntvfs"]) + plantestsuite("samba4.blackbox.krb5.s4u", "fl2008r2dc:local", [os.path.join(bbdir, "test_s4u_heimdal.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', configuration]) else: plantestsuite("samba4.blackbox.kinit", "ad_dc_ntvfs:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) plantestsuite("samba4.blackbox.kinit", "fl2000dc:local", [os.path.join(bbdir, "test_kinit_mit.sh"), '$SERVER', '$USERNAME', '$PASSWORD', '$REALM', '$DOMAIN', '$PREFIX', smbclient4, configuration]) diff --git a/testprogs/blackbox/test_s4u_heimdal.sh b/testprogs/blackbox/test_s4u_heimdal.sh new file mode 100755 index 00000000000..0e12c7ec096 --- /dev/null +++ b/testprogs/blackbox/test_s4u_heimdal.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +if [ $# -lt 5 ]; then +cat < $PREFIX/tmppassfile +testit "kinit with password" $samba4kinit -f --password-file=$PREFIX/tmppassfile $impersonator || failed=`expr $failed + 1` + +testit "test S4U2Self with normal user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=${USERNAME} $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy with normal user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +testit "test S4U2Self with sensitive user" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` +testit_expect_failure "test S4U2Proxy with sensitive user" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + +rm -f $ocache +testit "unset not-delegated flag" $samba_tool user sensitive $princ off || failed=`expr $failed + 1` + +testit "test S4U2Self after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --forwardable --impersonate=$princ $impersonator || failed=`expr $failed + 1` +testit "test S4U2Proxy after unsetting ND flag" $samba4kgetcred --out-cache=$ocache --delegation-credential-cache=${ocache} $target || failed=`expr $failed + 1` + + +rm -f $ocache $PREFIX/tmpccache tmppassfile +exit $failed -- 2.21.0 From a7d3f6852956bd2be62600f9f0ac27fb25ddb591 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 28 Oct 2019 02:54:09 +0200 Subject: [PATCH 4/4] CVE-2019-14870: heimdal: enforce delegation_not_allowed in S4U2Self Signed-off-by: Isaac Boukris --- selftest/knownfail.d/heimdal_not_delegated | 1 - source4/heimdal/kdc/krb5tgs.c | 58 ++++++++++++++-------- 2 files changed, 36 insertions(+), 23 deletions(-) delete mode 100644 selftest/knownfail.d/heimdal_not_delegated diff --git a/selftest/knownfail.d/heimdal_not_delegated b/selftest/knownfail.d/heimdal_not_delegated deleted file mode 100644 index bfc382a3fc2..00000000000 --- a/selftest/knownfail.d/heimdal_not_delegated +++ /dev/null @@ -1 +0,0 @@ -^samba4.blackbox.krb5.s4u diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index ff7d93138c0..ee3ac3d8f53 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1975,30 +1975,42 @@ server_lookup: if (ret) goto out; + ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, + NULL, &s4u2self_impersonated_clientdb, + &s4u2self_impersonated_client); + if (ret) { + const char *msg; + + /* + * If the client belongs to the same realm as our krbtgt, it + * should exist in the local database. + * + */ + + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + msg = krb5_get_error_message(context, ret); + kdc_log(context, config, 1, + "S2U4Self principal to impersonate %s not found in database: %s", + tpn, msg); + krb5_free_error_message(context, msg); + goto out; + } + + /* Ignore pw_end attributes (as Windows does), + * since S4U2Self is not password authentication. */ + free(s4u2self_impersonated_client->entry.pw_end); + s4u2self_impersonated_client->entry.pw_end = NULL; + + ret = kdc_check_flags(context, config, s4u2self_impersonated_client, tpn, + NULL, NULL, FALSE); + if (ret) + goto out; + /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */ if(rspac.data) { krb5_pac p = NULL; krb5_data_free(&rspac); - ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags, - NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client); - if (ret) { - const char *msg; - - /* - * If the client belongs to the same realm as our krbtgt, it - * should exist in the local database. - * - */ - - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - msg = krb5_get_error_message(context, ret); - kdc_log(context, config, 1, - "S2U4Self principal to impersonate %s not found in database: %s", - tpn, msg); - krb5_free_error_message(context, msg); - goto out; - } ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, &p); if (ret) { kdc_log(context, config, 0, "PAC generation failed for -- %s", @@ -2034,10 +2046,12 @@ server_lookup: /* * If the service isn't trusted for authentication to - * delegation, remove the forward flag. + * delegation or if the impersonate client is disallowed + * forwardable, remove the forwardable flag. */ - if (client->entry.flags.trusted_for_delegation) { + if (client->entry.flags.trusted_for_delegation && + s4u2self_impersonated_client->entry.flags.forwardable) { str = "[forwardable]"; } else { b->kdc_options.forwardable = 0; -- 2.21.0