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

Bug#806166: marked as done (wheezy-pu: package zendframework/1.11.13-1.1+deb7u5)



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 #806166,
regarding wheezy-pu: package zendframework/1.11.13-1.1+deb7u5
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.)


-- 
806166: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=806166
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,

As per #806165 (Jessie pu request), this update aims to fix a security
issue in zendframework:

  * Backport security fix from 1.12.17:
    - ZF2015-09: Fixed entropy issue in word CAPTCHA
      http://framework.zend.com/security/advisory/ZF2015-09

Thanks in advance for considering.

Regards

David
diff --git a/debian/changelog b/debian/changelog
index 5e5e8cf..4b3947c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+zendframework (1.11.13-1.1+deb7u5) wheezy; urgency=medium
+
+  * Backport security fix from 1.12.17
+    - ZF2015-09: Fixed entropy issue in word CAPTCHA
+      http://framework.zend.com/security/advisory/ZF2015-09
+
+ -- David Prévot <taffit@debian.org>  Tue, 24 Nov 2015 18:28:53 -0400
+
 zendframework (1.11.13-1.1+deb7u4) wheezy-security; urgency=high
 
   * Backport security fixes from 1.12.16
diff --git a/debian/patches/0015-ZF2015-09-Fixed-entropy-issue-in-word-CAPTCHA.patch b/debian/patches/0015-ZF2015-09-Fixed-entropy-issue-in-word-CAPTCHA.patch
new file mode 100644
index 0000000..718f86e
--- /dev/null
+++ b/debian/patches/0015-ZF2015-09-Fixed-entropy-issue-in-word-CAPTCHA.patch
@@ -0,0 +1,337 @@
+From: Enrico Zimuel <e.zimuel@gmail.com>
+Date: Mon, 9 Nov 2015 17:26:45 +0100
+Subject: ZF2015-09: Fixed entropy issue in word CAPTCHA
+
+This patch fixes a potential entropy fixation vector with `Zend_Captcha_Word`.
+Prior to the fix, when selecting letters for the CAPTCHA, `array_rand()` was
+used, which does not use sufficient entropy during randomization. The patch
+backports randomization routines from ZF2 in order to provide a more
+cryptographically secure RNG.
+
+Origin: upstream, https://github.com/zendframework/zf1/commit/4a41392f89bf510a8ab801eacb117fe7ea25b575
+---
+ library/Zend/Captcha/Word.php |  29 +++++++-----
+ library/Zend/Crypt/Math.php   | 100 +++++++++++++++++++++++++++++++++++++++---
+ tests/Zend/Crypt/MathTest.php |  72 +++++++++++++++++++++++++++++-
+ 3 files changed, 182 insertions(+), 19 deletions(-)
+
+diff --git a/library/Zend/Captcha/Word.php b/library/Zend/Captcha/Word.php
+index 310cd2e..e0ddfe0 100644
+--- a/library/Zend/Captcha/Word.php
++++ b/library/Zend/Captcha/Word.php
+@@ -22,6 +22,9 @@
+ /** @see Zend_Captcha_Base */
+ require_once 'Zend/Captcha/Base.php';
+ 
++/** @see Zend_Crypt_Math */
++require_once 'Zend/Crypt/Math.php';
++
+ /**
+  * Word-based captcha adapter
+  *
+@@ -39,10 +42,10 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+     /**#@+
+      * @var array Character sets
+      */
+-    static $V  = array("a", "e", "i", "o", "u", "y");
+-    static $VN = array("a", "e", "i", "o", "u", "y","2","3","4","5","6","7","8","9");
+-    static $C  = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z");
+-    static $CN = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z","2","3","4","5","6","7","8","9");
++    static public $V  = array("a", "e", "i", "o", "u", "y");
++    static public $VN = array("a", "e", "i", "o", "u", "y","2","3","4","5","6","7","8","9");
++    static public $C  = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z");
++    static public $CN = array("b","c","d","f","g","h","j","k","m","n","p","q","r","s","t","u","v","w","x","z","2","3","4","5","6","7","8","9");
+     /**#@-*/
+ 
+     /**
+@@ -175,7 +178,7 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+      *
+      * @return string
+      */
+-    public function getId ()
++    public function getId()
+     {
+         if (null === $this->_id) {
+             $this->_setId($this->_generateRandomId());
+@@ -189,7 +192,7 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+      * @param string $id
+      * return Zend_Captcha_Word
+      */
+-    protected function _setId ($id)
++    protected function _setId($id)
+     {
+         $this->_id = $id;
+         return $this;
+@@ -250,7 +253,7 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+         $this->_useNumbers = $_useNumbers;
+         return $this;
+     }
+-    
++
+     /**
+      * Get session object
+      *
+@@ -280,7 +283,7 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+     public function setSession(Zend_Session_Namespace $session)
+     {
+         $this->_session = $session;
+-        if($session) {
++        if ($session) {
+             $this->_keepSession = true;
+         }
+         return $this;
+@@ -326,10 +329,12 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+         $vowels     = $this->_useNumbers ? self::$VN : self::$V;
+         $consonants = $this->_useNumbers ? self::$CN : self::$C;
+ 
++        $totIndexCon = count($consonants) - 1;
++        $totIndexVow = count($vowels) - 1;
+         for ($i=0; $i < $wordLen; $i = $i + 2) {
+             // generate word with mix of vowels and consonants
+-            $consonant = $consonants[array_rand($consonants)];
+-            $vowel     = $vowels[array_rand($vowels)];
++            $consonant = $consonants[Zend_Crypt_Math::randInteger(0, $totIndexCon, true)];
++            $vowel     = $vowels[Zend_Crypt_Math::randInteger(0, $totIndexVow, true)];
+             $word     .= $consonant . $vowel;
+         }
+ 
+@@ -347,7 +352,7 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+      */
+     public function generate()
+     {
+-        if(!$this->_keepSession) {
++        if (!$this->_keepSession) {
+             $this->_session = null;
+         }
+         $id = $this->_generateRandomId();
+@@ -359,7 +364,7 @@ abstract class Zend_Captcha_Word extends Zend_Captcha_Base
+ 
+     protected function _generateRandomId()
+     {
+-        return md5(mt_rand(0, 1000) . microtime(true));
++        return md5(Zend_Crypt_Math::randBytes(32));
+     }
+ 
+     /**
+diff --git a/library/Zend/Crypt/Math.php b/library/Zend/Crypt/Math.php
+index 5b0ea9f..43f9167 100644
+--- a/library/Zend/Crypt/Math.php
++++ b/library/Zend/Crypt/Math.php
+@@ -57,21 +57,109 @@ class Zend_Crypt_Math extends Zend_Crypt_Math_BigInteger
+         }
+         $rand = '';
+         $i2 = strlen($maximum) - 1;
+-        for ($i = 1;$i < $i2;$i++) {
+-            $rand .= mt_rand(0,9);
++        for ($i = 1; $i < $i2; $i++) {
++            $rand .= mt_rand(0, 9);
+         }
+-        $rand .= mt_rand(0,9);
++        $rand .= mt_rand(0, 9);
+         return $rand;
+     }
+ 
+     /**
++     * Return a random strings of $length bytes
++     *
++     * @param  integer $length
++     * @param  boolean $strong
++     * @return string
++     */
++    public static function randBytes($length, $strong = false)
++    {
++        $length = (int) $length;
++        if ($length <= 0) {
++            return false;
++        }
++        if (function_exists('openssl_random_pseudo_bytes')) {
++            $bytes = openssl_random_pseudo_bytes($length, $usable);
++            if ($strong === $usable) {
++                return $bytes;
++            }
++        }
++        if (function_exists('mcrypt_create_iv')) {
++            $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
++            if ($bytes !== false && strlen($bytes) === $length) {
++                return $bytes;
++            }
++        }
++        if (file_exists('/dev/urandom') && is_readable('/dev/urandom')) {
++            $frandom = fopen('/dev/urandom', 'r');
++            if ($frandom !== false) {
++                return fread($frandom, $length);
++            }
++        }
++        if (true === $strong) {
++            require_once 'Zend/Crypt/Exception.php';
++            throw new Zend_Crypt_Exception(
++                'This PHP environment doesn\'t support secure random number generation. ' .
++                'Please consider installing the OpenSSL and/or Mcrypt extensions'
++            );
++        }
++        $rand = '';
++        for ($i = 0; $i < $length; $i++) {
++            $rand .= chr(mt_rand(0, 255));
++        }
++        return $rand;
++    }
++
++    /**
++     * Return a random integer between $min and $max
++     *
++     * @param  integer $min
++     * @param  integer $max
++     * @param  boolean $strong
++     * @return integer
++     */
++    public static function randInteger($min, $max, $strong = false)
++    {
++        if ($min > $max) {
++            require_once 'Zend/Crypt/Exception.php';
++            throw new Zend_Crypt_Exception(
++                'The min parameter must be lower than max parameter'
++            );
++        }
++        $range = $max - $min;
++        if ($range == 0) {
++            return $max;
++        } elseif ($range > PHP_INT_MAX || is_float($range)) {
++            require_once 'Zend/Crypt/Exception.php';
++            throw new Zend_Crypt_Exception(
++                'The supplied range is too great to generate'
++            );
++        }
++        // calculate number of bits required to store range on this machine
++        $r = $range;
++        $bits = 0;
++        while ($r) {
++            $bits++;
++            $r >>= 1;
++        }
++        $bits   = (int) max($bits, 1);
++        $bytes  = (int) max(ceil($bits / 8), 1);
++        $filter = (int) ((1 << $bits) - 1);
++        do {
++            $rnd  = hexdec(bin2hex(self::randBytes($bytes, $strong)));
++            $rnd &= $filter;
++        } while ($rnd > $range);
++        return ($min + $rnd);
++    }
++
++    /**
+      * Get the big endian two's complement of a given big integer in
+      * binary notation
+      *
+      * @param string $long
+      * @return string
+      */
+-    public function btwoc($long) {
++    public function btwoc($long)
++    {
+         if (ord($long[0]) > 127) {
+             return "\x00" . $long;
+         }
+@@ -84,7 +172,8 @@ class Zend_Crypt_Math extends Zend_Crypt_Math_BigInteger
+      * @param string $binary
+      * @return string
+      */
+-    public function fromBinary($binary) {
++    public function fromBinary($binary)
++    {
+         return $this->_math->binaryToInteger($binary);
+     }
+ 
+@@ -98,5 +187,4 @@ class Zend_Crypt_Math extends Zend_Crypt_Math_BigInteger
+     {
+         return $this->_math->integerToBinary($integer);
+     }
+-
+ }
+diff --git a/tests/Zend/Crypt/MathTest.php b/tests/Zend/Crypt/MathTest.php
+index d097186..f825cc9 100644
+--- a/tests/Zend/Crypt/MathTest.php
++++ b/tests/Zend/Crypt/MathTest.php
+@@ -21,7 +21,7 @@
+  */
+ 
+ require_once 'Zend/Crypt/Math.php';
+-
++require_once 'Zend/Crypt/Exception.php';
+ 
+ /**
+  * @category   Zend
+@@ -54,4 +54,74 @@ class Zend_Crypt_MathTest extends PHPUnit_Framework_TestCase
+         $this->assertTrue(bccomp($result, $lower) !== '-1');
+     }
+ 
++    public function testRandBytes()
++    {
++        for ($length = 1; $length < 4096; $length++) {
++            $rand = Zend_Crypt_Math::randBytes($length);
++            $this->assertTrue(false !== $rand);
++            $this->assertEquals($length, strlen($rand));
++        }
++    }
++
++    public function testRandInteger()
++    {
++        for ($i = 0; $i < 1024; $i++) {
++            $min = rand(1, PHP_INT_MAX/2);
++            $max = $min + rand(1, PHP_INT_MAX/2 - 1);
++            $rand = Zend_Crypt_Math::randInteger($min, $max);
++            $this->assertGreaterThanOrEqual($min, $rand);
++            $this->assertLessThanOrEqual($max, $rand);
++        }
++    }
++
++    public static function provideRandInt()
++    {
++        return [
++            [2, 1, 10000, 100, 0.9, 1.1, false],
++            [2, 1, 10000, 100, 0.8, 1.2, true]
++        ];
++    }
++
++    /**
++     * A Monte Carlo test that generates $cycles numbers from 0 to $tot
++     * and test if the numbers are above or below the line y=x with a
++     * frequency range of [$min, $max]
++     *
++     * @dataProvider provideRandInt
++     */
++    public function testMontecarloRandInteger($num, $valid, $cycles, $tot, $min, $max, $strong)
++    {
++        try {
++            $test = Zend_Crypt_Math::randBytes(1, $strong);
++        } catch (Zend_Crypt_Exception $e) {
++            $this->markTestSkipped($e->getMessage());
++        }
++
++        $i     = 0;
++        $count = 0;
++        do {
++            $up   = 0;
++            $down = 0;
++            for ($i = 0; $i < $cycles; $i++) {
++                $x = Zend_Crypt_Math::randInteger(0, $tot, $strong);
++                $y = Zend_Crypt_Math::randInteger(0, $tot, $strong);
++                if ($x > $y) {
++                    $up++;
++                } elseif ($x < $y) {
++                    $down++;
++                }
++            }
++            $this->assertGreaterThan(0, $up);
++            $this->assertGreaterThan(0, $down);
++            $ratio = $up / $down;
++            if ($ratio > $min && $ratio < $max) {
++                $count++;
++            }
++            $i++;
++        } while ($i < $num && $count < $valid);
++
++        if ($count < $valid) {
++            $this->fail('The random number generator failed the Monte Carlo test');
++        }
++    }
+ }
diff --git a/debian/patches/series b/debian/patches/series
index dc960a0..8f3a09e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -12,3 +12,4 @@
 0012-ZF2015-06-Fix-potential-XXE-vector-via-BOM-detection.patch
 0013-ZF2015-07-Use-umask-of-0002.patch
 0014-ZF2015-08-Fix-null-byte-injection-for-PDO-MsSql.patch
+0015-ZF2015-09-Fixed-entropy-issue-in-word-CAPTCHA.patch

Attachment: signature.asc
Description: PGP signature


--- 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: