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

Bug#854782: unblock: python-bottle-cork/0.12.0-2



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package python-bottle-cork

Recently a vulnerability in the package has been discovered (due to very weak
hashing of passwords), reported in the BTS as #854390.

Upstream has provided a fix in their repository, which I have now backported
and uploaded.

>From a Debian repository perspective, python-bottle-cork is a leaf package
with a very small popcon (i'm not entirely sure, how many of the 5 installments
are actually mine), so the impact should be small enough.

unblock python-bottle-cork/0.12.0-2

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

Kernel: Linux 4.9.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
diff -Nru python-bottle-cork-0.12.0/debian/changelog python-bottle-cork-0.12.0/debian/changelog
--- python-bottle-cork-0.12.0/debian/changelog	2016-08-31 21:13:24.000000000 +0200
+++ python-bottle-cork-0.12.0/debian/changelog	2017-02-10 10:04:27.000000000 +0100
@@ -1,3 +1,10 @@
+python-bottle-cork (0.12.0-2) unstable; urgency=medium
+
+  * Backported fix for weak hashing defaults (Closes: #854390)
+    * Thanks: Federico Ceratto
+
+ -- IOhannes m zmölnig (Debian/GNU) <umlaeute@debian.org>  Fri, 10 Feb 2017 10:04:27 +0100
+
 python-bottle-cork (0.12.0-1) unstable; urgency=medium
 
   * Initial package (Closes: #836163)
diff -Nru python-bottle-cork-0.12.0/debian/.git-dpm python-bottle-cork-0.12.0/debian/.git-dpm
--- python-bottle-cork-0.12.0/debian/.git-dpm	2016-08-31 21:13:24.000000000 +0200
+++ python-bottle-cork-0.12.0/debian/.git-dpm	2017-02-10 10:04:27.000000000 +0100
@@ -1,6 +1,6 @@
 # see git-dpm(1) from git-dpm package
-9f5b7a899774140f053c15ed7fd0b3c9d9b02bf8
-9f5b7a899774140f053c15ed7fd0b3c9d9b02bf8
+5cc4bf91c713ec506ced30483ce277456d55a609
+5cc4bf91c713ec506ced30483ce277456d55a609
 a9a0d14d2806481a276a7cc79f3dacf05a1e5fd6
 a9a0d14d2806481a276a7cc79f3dacf05a1e5fd6
 python-bottle-cork_0.12.0.orig.tar.gz
diff -Nru python-bottle-cork-0.12.0/debian/patches/0002-Backported-fix-for-weak-hashing-defaults.patch python-bottle-cork-0.12.0/debian/patches/0002-Backported-fix-for-weak-hashing-defaults.patch
--- python-bottle-cork-0.12.0/debian/patches/0002-Backported-fix-for-weak-hashing-defaults.patch	1970-01-01 01:00:00.000000000 +0100
+++ python-bottle-cork-0.12.0/debian/patches/0002-Backported-fix-for-weak-hashing-defaults.patch	2017-02-10 10:04:27.000000000 +0100
@@ -0,0 +1,164 @@
+From 5cc4bf91c713ec506ced30483ce277456d55a609 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig=20=28Debian/GNU=29?=
+ <umlaeute@debian.org>
+Date: Thu, 9 Feb 2017 22:51:53 +0100
+Subject: Backported fix for weak hashing defaults
+
+upstream: ebb2777d6eaeff0cfa95f9b1d8b83ed9d87a493b
+Closes: #854390
+---
+ cork/cork.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 56 insertions(+), 17 deletions(-)
+
+diff --git a/cork/cork.py b/cork/cork.py
+index d8b2320..e8b6358 100644
+--- a/cork/cork.py
++++ b/cork/cork.py
+@@ -69,7 +69,8 @@ class BaseCork(object):
+ 
+     def __init__(self, directory=None, backend=None, email_sender=None,
+                  initialize=False, session_domain=None, smtp_server=None,
+-                 smtp_url='localhost', session_key_name=None):
++                 smtp_url='localhost', session_key_name=None,
++                 preferred_hashing_algorithm=None, pbkdf2_iterations=None):
+         """Auth/Authorization/Accounting class
+ 
+         :param directory: configuration directory
+@@ -79,13 +80,24 @@ class BaseCork(object):
+         :param roles_fname: roles filename (without .json), defaults to 'roles'
+         :type roles_fname: str.
+         """
++        if preferred_hashing_algorithm not in ("PBKDF2sha1", "PBKDF2sha256", "scrypt"):
++            raise Exception("preferred_hashing_algorithm must be 'PBKDF2sha256', 'PBKDF2sha1' or 'scrypt'")
++
++        if preferred_hashing_algorithm.startswith("PBKDF2") and not pbkdf2_iterations:
++            raise Exception("pbkdf2_iterations must be set")
++        elif preferred_hashing_algorithm == 'scrypt' and not scrypt_available:
++            raise Exception("scrypt.hash required."
++                            " Please install the scrypt library.")
++
+         if smtp_server:
+             smtp_url = smtp_server
+         self.mailer = Mailer(email_sender, smtp_url)
+         self.password_reset_timeout = 3600 * 24
+         self.session_domain = session_domain
+         self.session_key_name = session_key_name or 'beaker.session'
+-        self.preferred_hashing_algorithm = 'PBKDF2'
++        self.saltlength = { 'PBKDF2':32, 'scrypt':32, 'argon2':57 }
++        self.preferred_hashing_algorithm = preferred_hashing_algorithm
++        self.pbkdf2_iterations = pbkdf2_iterations
+ 
+         # Setup JsonBackend by default for backward compatibility.
+         if backend is None:
+@@ -612,16 +624,18 @@ class BaseCork(object):
+         if algo is None:
+             algo = self.preferred_hashing_algorithm
+ 
+-        if algo == 'PBKDF2':
+-            return self._hash_pbkdf2(username, pwd, salt=salt)
++        if algo == 'PBKDF2sha1':
++            return self._hash_pbkdf2_sha1(username, pwd, salt=salt)
++
++        if algo == 'PBKDF2sha256':
++            return self._hash_pbkdf2_sha256(username, pwd, salt=salt)
+ 
+         if algo == 'scrypt':
+             return self._hash_scrypt(username, pwd, salt=salt)
+ 
+         raise RuntimeError("Unknown hashing algorithm requested: %s" % algo)
+ 
+-    @staticmethod
+-    def _hash_scrypt(username, pwd, salt=None):
++    def _hash_scrypt(self, username, pwd, salt=None):
+         """Hash username and password, generating salt value if required
+         Use scrypt.
+ 
+@@ -632,9 +646,15 @@ class BaseCork(object):
+                             " Please install the scrypt library.")
+ 
+         if salt is None:
+-            salt = os.urandom(32)
++            salt = os.urandom(self.saltlength['scrypt'])
+ 
+-        assert len(salt) == 32, "Incorrect salt length"
++        assert len(salt) == self.saltlength['scrypt'], "Incorrect salt length"
++
++        username = username.encode('utf-8')
++        assert isinstance(username, bytes)
++
++        pwd = pwd.encode('utf-8')
++        assert isinstance(pwd, bytes)
+ 
+         cleartext = "%s\0%s" % (username, pwd)
+         h = scrypt.hash(cleartext, salt)
+@@ -643,18 +663,33 @@ class BaseCork(object):
+         hashed = b's' + salt + h
+         return b64encode(hashed)
+ 
+-    @staticmethod
+-    def _hash_pbkdf2(username, pwd, salt=None):
++    def _hash_pbkdf2_sha1(self, username, pwd, salt=None):
++        """Hash username and password, generating salt value if required
++        Use PBKDF2 wih sha1
++
++        :returns: base-64 encoded str.
++        """
++        return self.__hash_pbkdf2('sha1', b'p', username, pwd, salt)
++
++    def _hash_pbkdf2_sha256(self, username, pwd, salt=None):
++        """Hash username and password, generating salt value if required
++        Use PBKDF2 wih sha256
++
++        :returns: base-64 encoded str.
++        """
++        return self.__hash_pbkdf2('sha256', b'k', username, pwd, salt)
++
++    def __hash_pbkdf2(self, algo, prefix, username, pwd, salt):
+         """Hash username and password, generating salt value if required
+         Use PBKDF2 from Beaker
+ 
+         :returns: base-64 encoded str.
+         """
+         if salt is None:
+-            salt = os.urandom(32)
++            salt = os.urandom(self.saltlength['PBKDF2'])
+ 
+         assert isinstance(salt, bytes)
+-        assert len(salt) == 32, "Incorrect salt length"
++        assert len(salt) == self.saltlength['PBKDF2'], "Incorrect salt length"
+ 
+         username = username.encode('utf-8')
+         assert isinstance(username, bytes)
+@@ -663,14 +698,14 @@ class BaseCork(object):
+         assert isinstance(pwd, bytes)
+ 
+         cleartext = username + b'\0' + pwd
+-        h = hashlib.pbkdf2_hmac('sha1', cleartext, salt, 10, dklen=32)
++        h = hashlib.pbkdf2_hmac(algo, cleartext, salt, self.pbkdf2_iterations, dklen=32)
+ 
+         # 'p' for PBKDF2
+-        hashed = b'p' + salt + h
++        hashed = prefix + salt + h
+         return b64encode(hashed)
+ 
+     def _verify_password(self, username, pwd, salted_hash):
+-        """Verity username/password pair against a salted hash
++        """Verify username/password pair against a salted hash
+ 
+         :returns: bool
+         """
+@@ -682,8 +717,12 @@ class BaseCork(object):
+ 
+         salt = decoded[1:33]
+ 
+-        if hash_type == 'p':  # PBKDF2
+-            h = self._hash_pbkdf2(username, pwd, salt)
++        if hash_type == 'p':  # PBKDF2 with sha1
++            h = self._hash_pbkdf2_sha1(username, pwd, salt)
++            return salted_hash == h
++
++        if hash_type == 'k':  # PBKDF2 with sha256
++            h = self._hash_pbkdf2_sha256(username, pwd, salt)
+             return salted_hash == h
+ 
+         if hash_type == 's':  # scrypt
diff -Nru python-bottle-cork-0.12.0/debian/patches/series python-bottle-cork-0.12.0/debian/patches/series
--- python-bottle-cork-0.12.0/debian/patches/series	2016-08-31 21:13:24.000000000 +0200
+++ python-bottle-cork-0.12.0/debian/patches/series	2017-02-10 10:04:27.000000000 +0100
@@ -1 +1,2 @@
 0001-Serve-local-jquery.js.patch
+0002-Backported-fix-for-weak-hashing-defaults.patch

Reply to: