Package: release.debian.org Severity: normal User: release.debian....@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) <umlae...@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?= + <umlae...@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