[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#798091: marked as done (wheezy-pu: package pykerberos/1.1+svn4895-1+deb7u1)



Your message dated Sat, 02 Apr 2016 14:22:42 +0100
with message-id <1459603362.2441.217.camel@adam-barratt.org.uk>
and subject line Fix included in oldstable
has caused the Debian Bug report #798091,
regarding wheezy-pu: package pykerberos/1.1+svn4895-1+deb7u1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
798091: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=798091
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian.org@packages.debian.org
Usertags: pu

Hi,
I'd like to fix CVE-2015-3206 (missing KDC authenticity verification)
for wheezy via a point release. The debdiff is attached. The bug is
fixed in unstable as well as squeeze-lts already.

As in squeeze-lts the KDC check is disabled by default to not break existing
installations.

Cheers,
 -- Guido.


-- System Information:
Debian Release: 8.1
  APT prefers stable
  APT policy: (990, 'stable'), (500, 'stable-updates'), (500, 'unstable'), (500, 'testing'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.1.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
>From 196366a8fbf843cc91f88aa17eed7aff2591b693 Mon Sep 17 00:00:00 2001
Message-Id: <196366a8fbf843cc91f88aa17eed7aff2591b693.1441460328.git.agx@sigxcpu.org>
From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
Date: Sat, 5 Sep 2015 15:32:08 +0200
Subject: [PATCH] Forward port fix for CVE-2015-3206 to wheezy

from squeeze-lts
---
 bin/login           | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 debian/NEWS         | 42 ++++++++++++++++++++++++++++++++++++++++++
 debian/changelog    |  9 +++++++++
 debian/examples     |  1 +
 pysrc/kerberos.py   |  4 +++-
 src/kerberos.c      |  5 +++--
 src/kerberosbasic.c | 41 ++++++++++++++++++++++++++++++++++-------
 src/kerberosbasic.h |  2 +-
 8 files changed, 140 insertions(+), 11 deletions(-)
 create mode 100644 bin/login
 create mode 100644 debian/NEWS

diff --git a/bin/login b/bin/login
new file mode 100644
index 0000000..d9becaa
--- /dev/null
+++ b/bin/login
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+##
+# Copyright (c) 2008 Jelmer Vernooij <jelmer@samba.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A sample script showing how to verify a user with username and password."""
+
+import argparse
+import getpass
+import kerberos
+import sys
+
+
+def main():
+    # construct arg parser
+    parser = argparse.ArgumentParser(description='Verify Kerberos login.')
+    parser.add_argument('--service', default='', help='the service to authenticate as')
+    parser.add_argument('--default_realm', default='', help='the realm to use if none is provided in the username')
+    parser.add_argument('--verify', default=False, action='store_true', help='enable KDC verification support')
+    parser.add_argument('user', metavar='user', help='the username to verify')
+    args = parser.parse_args()
+
+    print args.service
+
+    # get the password
+    password = getpass.getpass('Password: ')
+
+    # verify
+    try:
+        kerberos.checkPassword(args.user, password, args.service, args.default_realm, args.verify)
+        print "Successfully verified"
+    except kerberos.BasicAuthError as e:
+        print "{0} ({1})".format(*e.args)
+
+if __name__ == "__main__":
+    main()
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644
index 0000000..2143663
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,42 @@
+pykerberos (1.1+svn4895-1+deb7u1) wheezy; urgency=medium
+
+  The python-kerberos checkPassword() method has been badly insecure in
+  previous releases. It used to do (and still does by default) a kinit
+  (AS-REQ) to ask a KDC for a TGT for the given user principal, and
+  interprets the success or failure of that as indicating whether the
+  password is correct. It does not, however, verify that it actually spoke
+  to a trusted KDC: an attacker may simply reply instead with an AS-REP
+  which matches the password he just gave you.
+  .
+  Imagine you were verifying a password using LDAP authentication rather
+  than Kerberos: you would, of course, use TLS in conjunction with LDAP to
+  make sure you were talking to a real, trusted LDAP server. The same
+  requirement applies here. kinit is not a password-verification service.
+  .
+  The usual way of doing this is to take the TGT you've obtained with the
+  user's password, and then obtain a ticket for a principal for which the
+  verifier has keys (e.g. a web server processing a username/password form
+  login might get a ticket for its own HTTP/host@REALM principal), which
+  it can then verify. Note that this requires that the verifier has its
+  own Kerberos identity, which is mandated by the symmetric nature of
+  Kerberos (whereas in the LDAP case, the use of public-key cryptography
+  allows anonymous verification).
+  .
+  The fact of pykerberos being susceptible to KDC spoofing attacks has
+  been filed as CVE-2015-3206.
+  .
+  With this version of the pykerberos package a new option is introduced
+  for the checkPassword() method. Setting verify to True when using
+  checkPassword() will perform a KDC verification. For this to work, you
+  need to provide a krb5.keytab file containing service principal keys for
+  the service you intend to use.
+  .
+  As the default krb5.keytab file in /etc is normally not accessible by
+  non-root users/processes, you have to make sure a custom krb5.keytab
+  file containing the correct principal keys is provided to your
+  application using the KRB5_KTNAME environment variable.
+  .
+  Note: In Debian wheezy, KDC verification support is disabled by
+  default in ordner not to break existing setups.
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 05 Sep 2015 15:31:19 +0200
diff --git a/debian/changelog b/debian/changelog
index 27c11ff..f0076d2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+pykerberos (1.1+svn4895-1+deb7u1) wheezy; urgency=medium
+
+  * Add KDC authenticity verification support (CVE-2015-3206).
+    Obtained from upstream, ignoring white-space changes, URL:
+    https://github.com/02strich/pykerberos/commit/
+       02d13860b25fab58e739f0e000bed0067b7c6f9c
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 05 Sep 2015 15:31:19 +0200
+
 pykerberos (1.1+svn4895-1) unstable; urgency=low
 
   * [d6e470d] fix typo in package description (Closes: #520276) - thanks to
diff --git a/debian/examples b/debian/examples
index de45608..10845a7 100644
--- a/debian/examples
+++ b/debian/examples
@@ -1 +1,2 @@
 bin/ftp-gss
+bin/login
diff --git a/pysrc/kerberos.py b/pysrc/kerberos.py
index eb8839f..a6c4c3a 100644
--- a/pysrc/kerberos.py
+++ b/pysrc/kerberos.py
@@ -27,7 +27,7 @@ class BasicAuthError(KrbError):
 class GSSError(KrbError):
     pass
 
-def checkPassword(user, pswd, service, default_realm):
+def checkPassword(user, pswd, service, default_realm, verify=False):
     """
     This function provides a simple way to verify that a user name and password match
     those normally used for Kerberos authentication. It does this by checking that the
@@ -49,6 +49,8 @@ def checkPassword(user, pswd, service, default_realm):
     @param default_realm: a string containing the default realm to use if one is not
         supplied in the user argument. Note that Kerberos realms are normally all
         uppercase (e.g., 'EXAMPLE.COM').
+    @param verify:        a boolean flagging KDC verification to enabled or disabled
+                          (default: False).
     @return:              True if authentication succeeds, False otherwise.
     """
 
diff --git a/src/kerberos.c b/src/kerberos.c
index e0d8938..a887f7c 100644
--- a/src/kerberos.c
+++ b/src/kerberos.c
@@ -31,12 +31,13 @@ static PyObject *checkPassword(PyObject *self, PyObject *args)
     const char *pswd;
     const char *service;
     const char *default_realm;
+    int verify = 0;
     int result = 0;
 
-    if (!PyArg_ParseTuple(args, "ssss", &user, &pswd, &service, &default_realm))
+    if (!PyArg_ParseTuple(args, "ssss|b", &user, &pswd, &service, &default_realm, &verify))
         return NULL;
 
-    result = authenticate_user_krb5pwd(user, pswd, service, default_realm);
+    result = authenticate_user_krb5pwd(user, pswd, service, default_realm, verify);
 
     if (result)
         return Py_INCREF(Py_True), Py_True;
diff --git a/src/kerberosbasic.c b/src/kerberosbasic.c
index 8b38f11..65ec176 100644
--- a/src/kerberosbasic.c
+++ b/src/kerberosbasic.c
@@ -26,9 +26,9 @@
 extern PyObject *BasicAuthException_class;
 static void set_basicauth_error(krb5_context context, krb5_error_code code);
 
-static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server);
+static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server, unsigned char verify);
 
-int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm)
+int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm, unsigned char verify)
 {
     krb5_context    kcontext = NULL;
     krb5_error_code code;
@@ -87,7 +87,7 @@ int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *se
         goto end;
     }
 
-    code = verify_krb5_user(kcontext, client, pswd, server);
+    code = verify_krb5_user(kcontext, client, pswd, server, verify);
 
     if (code)
     {
@@ -113,10 +113,11 @@ end:
 }
 
 /* Inspired by krb5_verify_user from Heimdal */
-static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server)
+static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server, unsigned char verify)
 {
     krb5_creds creds;
-    krb5_get_init_creds_opt gic_options;
+    krb5_get_init_creds_opt *gic_options;
+    krb5_verify_init_creds_opt vic_options;
     krb5_error_code ret;
     char *name = NULL;
 
@@ -131,17 +132,43 @@ static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal pri
         free(name);
     }
 
-    krb5_get_init_creds_opt_init(&gic_options);
-    ret = krb5_get_init_creds_password(context, &creds, principal, (char *)password, NULL, NULL, 0, NULL, &gic_options);
+    // verify passed in server principal if needed
+    if (verify) {
+         ret = krb5_unparse_name(context, server, &name);
+         if (ret == 0) {
+#ifdef PRINTFS
+             printf("Trying to get TGT for service %s\n", name);
+#endif
+             free(name);
+         }
+    }
+
+    // verify password
+    krb5_get_init_creds_opt_alloc(context, &gic_options);
+    ret = krb5_get_init_creds_password(context, &creds, principal, (char *)password, NULL, NULL, 0, NULL, gic_options);
     if (ret)
     {
         set_basicauth_error(context, ret);
         goto end;
     }
 
+    // verify response authenticity
+    if (verify) {
+        krb5_verify_init_creds_opt_init(&vic_options);
+        krb5_verify_init_creds_opt_set_ap_req_nofail(&vic_options, 1);
+        ret = krb5_verify_init_creds(context, &creds, server, NULL, NULL, &vic_options);
+        if (ret) {
+            set_basicauth_error(context, ret);
+        }
+    }
+
 end:
+    // clean up
     krb5_free_cred_contents(context, &creds);
 
+    if (gic_options)
+        krb5_get_init_creds_opt_free(context, gic_options);
+
     return ret;
 }
 
diff --git a/src/kerberosbasic.h b/src/kerberosbasic.h
index d3dca95..116d93d 100644
--- a/src/kerberosbasic.h
+++ b/src/kerberosbasic.h
@@ -20,4 +20,4 @@
 
 #define krb5_get_err_text(context,code) error_message(code)
 
-int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm);
+int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm, unsigned char verify);
-- 
2.1.4


--- End Message ---
--- Begin Message ---
Version: 7.10

Hi,

The updates referenced in these bugs were included in today's wheezy
point release.

Regards,

Adam

--- End Message ---

Reply to: