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

Bug#798028: jessie-pu: package pykerberos/1.1.5-0.1+deb8u1



Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

Hi,
I'd like to fix CVE-2015-3206 (a loack (missing KDC authenticity
verification) for jessie 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)
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644
index 0000000..490dd3d
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,42 @@
+pykerberos (1.1.5-0.1+deb8u1) jessie; 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 Jessie, KDC verification support is disabled by default in
+  ordner not to break existing setups.
+ 
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 22 Aug 2015 12:08:41 +0200
diff --git a/debian/changelog b/debian/changelog
index 9521150..e382a4a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+pykerberos (1.1.5-0.1+deb8u1) jessie; 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
+    (Closes: #796195)
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 22 Aug 2015 13:48:57 +0200
+
 pykerberos (1.1.5-0.1) unstable; urgency=medium
 
   * Non-maintainer upload.
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/debian/patches/Add-KDC-authenticity-verification-support-CVE-2015-3206.patch b/debian/patches/Add-KDC-authenticity-verification-support-CVE-2015-3206.patch
new file mode 100644
index 0000000..e495497
--- /dev/null
+++ b/debian/patches/Add-KDC-authenticity-verification-support-CVE-2015-3206.patch
@@ -0,0 +1,150 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Sat, 22 Aug 2015 11:51:13 +0200
+Subject: Add KDC authenticity verification support (CVE-2015-3206)
+
+Obtained from upstream, ignoring white-space changes, URL:
+https://github.com/02strich/pykerberos/commit/02d13860b25fab58e739f0e000bed0067b7c6f9c
+---
+ pysrc/kerberos.py   |  4 +++-
+ src/kerberos.c      |  5 +++--
+ src/kerberosbasic.c | 41 ++++++++++++++++++++++++++++++++++-------
+ src/kerberosbasic.h |  2 +-
+ 4 files changed, 41 insertions(+), 11 deletions(-)
+
+diff --git a/pysrc/kerberos.py b/pysrc/kerberos.py
+index 8c6a712..06ddd38 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 740d9e1..af57b05 100644
+--- a/src/kerberos.c
++++ b/src/kerberos.c
+@@ -35,12 +35,13 @@ static PyObject *checkPassword(PyObject *self, PyObject *args)
+     const char *pswd = NULL;
+     const char *service = NULL;
+     const char *default_realm = NULL;
++    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 0c7bdd7..27d7c4f 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 0a91455..f3cfce5 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);
diff --git a/debian/patches/Include-bin-login-an-example-script-allowing-the-user.patch b/debian/patches/Include-bin-login-an-example-script-allowing-the-user.patch
new file mode 100644
index 0000000..d1b796a
--- /dev/null
+++ b/debian/patches/Include-bin-login-an-example-script-allowing-the-user.patch
@@ -0,0 +1,63 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Sat, 22 Aug 2015 11:53:34 +0200
+Subject: Include bin/login, an example script allowing the user
+
+to test the functionality of the new verify flag.
+---
+ bin/login | 47 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+ create mode 100644 bin/login
+
+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/patches/series b/debian/patches/series
new file mode 100644
index 0000000..e8d5a68
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,2 @@
+Add-KDC-authenticity-verification-support-CVE-2015-3206.patch
+Include-bin-login-an-example-script-allowing-the-user.patch

Reply to: