CVE-2016-9134: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: Exponent CMS 2.3.9 suffers from a SQL injection vulnerability in "/expPaginator.php" affecting the order parameter. Impact is Information Disclosure.
CWE description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
CVSS v3 base score: 7.5
Published: 2016-11-03T10:59Z
Repository: https://github.com/exponentcms/exponent-cms
Language: PHP
Files changed: framework/core/subsystems/expPaginator.php
Commit date: 2016-10-25 08:36:04 -0400
Commit message: regression fix last vulnerability fix for sanitizing order/direction params

Diff: diff --git a/framework/core/subsystems/expPaginator.php b/framework/core/subsystems/expPaginator.php
index 3db6b07c5b..2b504cf468 100755
--- a/framework/core/subsystems/expPaginator.php
+++ b/framework/core/subsystems/expPaginator.php
@@ -116,11 +116,12 @@ class expPaginator {
         $this->page = empty($params['page']) ? 1 : intval($params['page']);
 		$this->action = empty($params['action']) ? '' : $params['action'];
 		$this->controller = empty($params['controller']) ? '' : $params['controller'];
 		$this->sql = empty($params['sql']) ? '' : $params['sql'];
         $this->count_sql = empty($params['count_sql']) ? '' : $params['count_sql'];
-        $this->order = empty($params['order']) ? 'id' : preg_replace('/[^a-z\_]/i','',$params['order']);
+//        $this->order = empty($params['order']) ? 'id' : preg_replace('/[^a-zAZ_]/','',$params['order']);
+        $this->order = empty($params['order']) ? 'id' : expString::escape($params['order']);
 		$this->dir = empty($params['dir']) || !in_array($params['dir'], array('ASC', 'DESC')) ? 'ASC' : $params['dir'];
 		$this->src = empty($params['src']) ? null : expString::escape($params['src']);
         $this->categorize = empty($params['categorize']) ? false : $params['categorize'];
         $this->uncat = !empty($params['uncat']) ? $params['uncat'] : gt('Not Categorized');
         $this->groups = !empty($params['groups']) ? $params['groups'] : array();
@@ -178,11 +179,12 @@ class expPaginator {
         if (strstr($this->order," ")) {
             $orderby = explode(" ",$this->order);
             $this->order = $orderby[0];
             $this->order_direction = $orderby[1];
         }
-        if(!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $this->order))
+        // filter out invalid order & direction
+        if(preg_match('/[^a-zA-Z_][^a-zA-Z0-9_]*/', $this->order))
             $this->order = 'id';
         if (!in_array($this->order_direction, array('ASC', 'DESC')))
             $this->order_direction = 'ASC';
         if ($this->dontsort)
             $sort = null;

Vulnerable code:         $this->order = empty($params['order']) ? 'id' : preg_replace('/[^a-z\_]/i','',$params['order']);
        if(!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $this->order))
Fixed code: //        $this->order = empty($params['order']) ? 'id' : preg_replace('/[^a-zAZ_]/','',$params['order']);
        $this->order = empty($params['order']) ? 'id' : expString::escape($params['order']);
        // filter out invalid order & direction
        if(preg_match('/[^a-zA-Z_][^a-zA-Z0-9_]*/', $this->order))