diff --git a/README.md b/README.md index 4d6cf4837c..e9ceded9b8 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,18 @@ Master: [![Build Status](https://api.travis-ci.org/zendframework/zf1.png?branch= RELEASE INFORMATION =================== -Zend Framework 1.12.19dev Release. -Released on MMM DD, YYYY. +Zend Framework 1.12.19 Release. +Released on July 13, 2016. IMPORTANT FIXES FOR 1.12.19 --------------------------- +This release contains security fixes: + +- **ZF2016-02**: The implementation of `ORDER BY` and `GROUP BY` in + `Zend_Db_Select` contained potential SQL injection vulnerabilities, + and have been patched. + See http://framework.zend.com/changelog for full details. NEW FEATURES diff --git a/library/Zend/Db/Select.php b/library/Zend/Db/Select.php index a2aa487aa7..76278f21de 100644 --- a/library/Zend/Db/Select.php +++ b/library/Zend/Db/Select.php @@ -81,7 +81,9 @@ class Zend_Db_Select const SQL_ASC = 'ASC'; const SQL_DESC = 'DESC'; - const REGEX_COLUMN_EXPR = '/^([\w]*\s*\(([^\(\)]|(?1))*\))$/'; + const REGEX_COLUMN_EXPR = '/^([\w]*\s*\(([^\(\)]|(?1))*\))$/'; + const REGEX_COLUMN_EXPR_ORDER = '/^([\w]+\s*\(([^\(\)]|(?1))*\))$/'; + const REGEX_COLUMN_EXPR_GROUP = '/^([\w]+\s*\(([^\(\)]|(?1))*\))$/'; /** * Bind variables for query @@ -511,7 +513,7 @@ public function group($spec) } foreach ($spec as $val) { - if (preg_match(self::REGEX_COLUMN_EXPR, (string) $val)) { + if (preg_match(self::REGEX_COLUMN_EXPR_GROUP, (string) $val)) { $val = new Zend_Db_Expr($val); } $this->_parts[self::GROUP][] = $val; @@ -603,7 +605,7 @@ public function order($spec) $val = trim($matches[1]); $direction = $matches[2]; } - if (preg_match(self::REGEX_COLUMN_EXPR, (string) $val)) { + if (preg_match(self::REGEX_COLUMN_EXPR_ORDER, (string) $val)) { $val = new Zend_Db_Expr($val); } $this->_parts[self::ORDER][] = array($val, $direction); diff --git a/library/Zend/Version.php b/library/Zend/Version.php index 46cd0520fd..8df26b239e 100644 --- a/library/Zend/Version.php +++ b/library/Zend/Version.php @@ -32,7 +32,7 @@ final class Zend_Version /** * Zend Framework version identification - see compareVersion() */ - const VERSION = '1.12.19dev'; + const VERSION = '1.12.19'; /** * The latest stable version Zend Framework available diff --git a/tests/Zend/Db/Select/StaticTest.php b/tests/Zend/Db/Select/StaticTest.php index b72a55d522..a045b45fa8 100644 --- a/tests/Zend/Db/Select/StaticTest.php +++ b/tests/Zend/Db/Select/StaticTest.php @@ -834,6 +834,10 @@ public function testSqlInjectionWithOrder() $select = $this->_db->select(); $select->from(array('p' => 'products'))->order('MD5(1);drop table products; -- )'); $this->assertEquals('SELECT "p".* FROM "products" AS "p" ORDER BY "MD5(1);drop table products; -- )" ASC', $select->assemble()); + + $select = $this->_db->select(); + $select->from('p')->order("MD5(\";(\");DELETE FROM p2; SELECT 1 #)"); + $this->assertEquals('SELECT "p".* FROM "p" ORDER BY "MD5("";("");DELETE FROM p2; SELECT 1 #)" ASC', $select->assemble()); } public function testSqlInjectionWithGroup() @@ -845,6 +849,10 @@ public function testSqlInjectionWithGroup() $select = $this->_db->select(); $select->from(array('p' => 'products'))->group('MD5(1); drop table products; -- )'); $this->assertEquals('SELECT "p".* FROM "products" AS "p" GROUP BY "MD5(1); drop table products; -- )"', $select->assemble()); + + $select = $this->_db->select(); + $select->from('p')->group("MD5(\";(\");DELETE FROM p2; SELECT 1 #)"); + $this->assertEquals('SELECT "p".* FROM "p" GROUP BY "MD5("";("");DELETE FROM p2; SELECT 1 #)"', $select->assemble()); } public function testSqlInjectionInColumn()