diff --git a/composer.lock b/composer.lock
index 96d6552370..45d304926a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -89,16 +89,16 @@
},
{
"name": "matthiasmullie/minify",
- "version": "1.3.52",
+ "version": "1.3.55",
"source": {
"type": "git",
"url": "https://github.com/matthiasmullie/minify.git",
- "reference": "134b25a63d83a80ae128aedc9a99987e064b4382"
+ "reference": "21084eb9e6c117f5236969532d00ed2750cd1617"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/134b25a63d83a80ae128aedc9a99987e064b4382",
- "reference": "134b25a63d83a80ae128aedc9a99987e064b4382",
+ "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/21084eb9e6c117f5236969532d00ed2750cd1617",
+ "reference": "21084eb9e6c117f5236969532d00ed2750cd1617",
"shasum": ""
},
"require": {
@@ -107,7 +107,7 @@
"php": ">=5.3.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "~1.0",
+ "friendsofphp/php-cs-fixer": "~2.0",
"matthiasmullie/scrapbook": "~1.0",
"phpunit/phpunit": "~4.8"
},
@@ -136,7 +136,7 @@
"role": "Developer"
}
],
- "description": "CSS & JS minifier",
+ "description": "CSS & JavaScript minifier, in PHP. Removes whitespace, strips comments, combines files (incl. @import statements and small assets in CSS files), and optimizes/shortens a few common programming patterns.",
"homepage": "http://www.minifier.org",
"keywords": [
"JS",
@@ -145,7 +145,7 @@
"minifier",
"minify"
],
- "time": "2017-09-15T13:02:11+00:00"
+ "time": "2017-10-25T11:13:12+00:00"
},
{
"name": "matthiasmullie/path-converter",
@@ -349,16 +349,16 @@
},
{
"name": "simplepie/simplepie",
- "version": "1.5",
+ "version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
- "reference": "5de5551953f95feef12cf355a7a26a70f94aa3ab"
+ "reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/simplepie/simplepie/zipball/5de5551953f95feef12cf355a7a26a70f94aa3ab",
- "reference": "5de5551953f95feef12cf355a7a26a70f94aa3ab",
+ "url": "https://api.github.com/repos/simplepie/simplepie/zipball/db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
+ "reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"shasum": ""
},
"require": {
@@ -405,7 +405,7 @@
"feeds",
"rss"
],
- "time": "2017-04-17T07:29:31+00:00"
+ "time": "2017-11-12T02:03:34+00:00"
},
{
"name": "swiftmailer/swiftmailer",
diff --git a/system/config/constants.php b/system/config/constants.php
index 1daeae46bd..459ef048aa 100644
--- a/system/config/constants.php
+++ b/system/config/constants.php
@@ -13,7 +13,7 @@
* Core version
*/
define('VERSION', '3.5');
-define('BUILD', '30');
+define('BUILD', '31');
define('LONG_TERM_SUPPORT', true);
diff --git a/system/docs/CHANGELOG.md b/system/docs/CHANGELOG.md
index 21f79a09b7..94eeefeafa 100644
--- a/system/docs/CHANGELOG.md
+++ b/system/docs/CHANGELOG.md
@@ -1,6 +1,13 @@
Contao Open Source CMS changelog
================================
+Version 3.5.31 (2017-11-15)
+---------------------------
+
+### Fixed
+Prevent SQL injections in the back end search panel (see CVE-2017-16558).
+
+
Version 3.5.30 (2017-10-06)
---------------------------
diff --git a/system/modules/calendar/languages/pl/default.xlf b/system/modules/calendar/languages/pl/default.xlf
index cfd0330f7c..a219eb69ba 100644
--- a/system/modules/calendar/languages/pl/default.xlf
+++ b/system/modules/calendar/languages/pl/default.xlf
@@ -15,6 +15,7 @@
+ –
diff --git a/system/modules/core/drivers/DC_Table.php b/system/modules/core/drivers/DC_Table.php
index 4baef3ffca..7494c3feab 100644
--- a/system/modules/core/drivers/DC_Table.php
+++ b/system/modules/core/drivers/DC_Table.php
@@ -4943,23 +4943,33 @@ protected function searchMenu()
// Store search value in the current session
if (\Input::post('FORM_SUBMIT') == 'tl_filters')
{
- $session['search'][$this->strTable]['value'] = '';
- $session['search'][$this->strTable]['field'] = \Input::post('tl_field', true);
+ $strField = \Input::post('tl_field', true);
+ $strKeyword = ltrim(\Input::postRaw('tl_value'), '*');
+
+ if ($strField && !in_array($strField, $searchFields, true))
+ {
+ $strField = '';
+ $strKeyword = '';
+ }
// Make sure the regular expression is valid
- if (\Input::postRaw('tl_value') != '')
+ if ($strField && $strKeyword)
{
try
{
- $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE " . \Input::post('tl_field', true) . " REGEXP ?")
+ $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE " . $strField . " REGEXP ?")
->limit(1)
- ->execute(\Input::postRaw('tl_value'));
-
- $session['search'][$this->strTable]['value'] = \Input::postRaw('tl_value');
+ ->execute($strKeyword);
+ }
+ catch (\Exception $e)
+ {
+ $strKeyword = '';
}
- catch (\Exception $e) {}
}
+ $session['search'][$this->strTable]['field'] = $strField;
+ $session['search'][$this->strTable]['value'] = $strKeyword;
+
$this->Session->setData($session);
}
@@ -5060,7 +5070,7 @@ protected function sortMenu()
$strSort = \Input::post('tl_sort');
// Validate the user input (thanks to aulmn) (see #4971)
- if (in_array($strSort, $sortingFields))
+ if (in_array($strSort, $sortingFields, true))
{
$session['sorting'][$this->strTable] = in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$strSort]['flag'], array(2, 4, 6, 8, 10, 12)) ? "$strSort DESC" : $strSort;
$this->Session->setData($session);
diff --git a/system/modules/core/languages/pl/tl_files.xlf b/system/modules/core/languages/pl/tl_files.xlf
index 772510129c..9a7d8621af 100644
--- a/system/modules/core/languages/pl/tl_files.xlf
+++ b/system/modules/core/languages/pl/tl_files.xlf
@@ -151,7 +151,7 @@
- Nowy szablon
+ Nowy folder
diff --git a/system/modules/core/languages/pl/tl_settings.xlf b/system/modules/core/languages/pl/tl_settings.xlf
index 1287e89564..3bbbf7430f 100644
--- a/system/modules/core/languages/pl/tl_settings.xlf
+++ b/system/modules/core/languages/pl/tl_settings.xlf
@@ -335,6 +335,7 @@
+ Jeśli szerokość obrazka lub filmu przekroczy tą wartość, element zostanie automatycznie dostosowany. Wprowadź 0, aby wyłączyć limit.
diff --git a/system/modules/core/library/Contao/StringUtil.php b/system/modules/core/library/Contao/StringUtil.php
index 940a99fc8e..29bd89c3d8 100644
--- a/system/modules/core/library/Contao/StringUtil.php
+++ b/system/modules/core/library/Contao/StringUtil.php
@@ -605,13 +605,13 @@ function (array $matches) use ($arrData)
$blnCurrent = $arrStack[count($arrStack) - 1];
$blnCurrentIf = $arrIfStack[count($arrIfStack) - 1];
- if (strncmp($strTag, '{if', 3) === 0)
+ if (strncmp($strTag, '{if ', 4) === 0)
{
$blnExpression = $evaluateExpression(substr($strTag, 4, -1));
$arrStack[] = $blnCurrent && $blnExpression;
$arrIfStack[] = $blnExpression;
}
- elseif (strncmp($strTag, '{elseif', 7) === 0)
+ elseif (strncmp($strTag, '{elseif ', 8) === 0)
{
$blnExpression = $evaluateExpression(substr($strTag, 8, -1));
array_pop($arrStack);
diff --git a/system/modules/listing/modules/ModuleListing.php b/system/modules/listing/modules/ModuleListing.php
index 97032510d5..d4038f27bd 100644
--- a/system/modules/listing/modules/ModuleListing.php
+++ b/system/modules/listing/modules/ModuleListing.php
@@ -96,39 +96,42 @@ protected function compile()
return;
}
-
- /**
- * Add the search menu
- */
+ // Add the search menu
$strWhere = '';
$varKeyword = '';
$strOptions = '';
+ $strSearch = \Input::get('search');
+ $strFor = \Input::get('for');
+ $arrFields = trimsplit(',', $this->list_fields);
+ $arrSearchFields = trimsplit(',', $this->list_search);
$this->Template->searchable = false;
- $arrSearchFields = trimsplit(',', $this->list_search);
if (!empty($arrSearchFields) && is_array($arrSearchFields))
{
$this->Template->searchable = true;
- if (\Input::get('search') && \Input::get('for'))
+ if ($strSearch && !in_array($strSearch, $arrSearchFields, true))
+ {
+ $strSearch = '';
+ $strFor = '';
+ }
+
+ if ($strSearch && $strFor)
{
- $varKeyword = '%' . \Input::get('for') . '%';
- $strWhere = (!$this->list_where ? " WHERE " : " AND ") . \Input::get('search') . " LIKE ?";
+ $varKeyword = '%' . $strFor . '%';
+ $strWhere = (!$this->list_where ? " WHERE " : " AND ") . $strSearch . " LIKE ?";
}
foreach ($arrSearchFields as $field)
{
- $strOptions .= ' ' . "\n";
+ $strOptions .= ' ' . "\n";
}
}
$this->Template->search_fields = $strOptions;
-
- /**
- * Get the total number of records
- */
+ // Get the total number of records
$strQuery = "SELECT COUNT(*) AS count FROM " . $this->list_table;
if ($this->list_where)
@@ -136,16 +139,13 @@ protected function compile()
$strQuery .= " WHERE (" . $this->list_where . ")";
}
- $strQuery .= $strWhere;
+ $strQuery .= $strWhere;
$objTotal = $this->Database->prepare($strQuery)->execute($varKeyword);
-
- /**
- * Validate the page count
- */
+ // Validate the page count
$id = 'page_l' . $this->id;
- $page = (\Input::get($id) !== null) ? \Input::get($id) : 1;
- $per_page = \Input::get('per_page') ?: $this->perPage;
+ $page = (\Input::get($id) !== null) ? (int) \Input::get($id) : 1;
+ $per_page = (int) \Input::get('per_page') ?: $this->perPage;
// Thanks to Hagen Klemp (see #4485)
if ($per_page > 0 && ($page < 1 || $page > max(ceil($objTotal->count/$per_page), 1)))
@@ -158,10 +158,7 @@ protected function compile()
$objHandler->generate($objPage->id);
}
-
- /**
- * Get the selected records
- */
+ // Get the selected records
$strQuery = "SELECT " . $this->strPk . "," . $this->list_fields;
if ($this->list_info_where)
@@ -183,16 +180,30 @@ protected function compile()
return $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['eval']['rgxp'] == 'date' || $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['eval']['rgxp'] == 'time' || $GLOBALS['TL_DCA'][$this->list_table]['fields'][$field]['eval']['rgxp'] == 'datim';
};
+ $order_by = \Input::get('order_by');
+
+ if ($order_by && !in_array($order_by, $arrFields, true))
+ {
+ $order_by = '';
+ }
+
+ $sort = \Input::get('sort');
+
+ if ($sort && !in_array($sort, array('asc', 'desc')))
+ {
+ $sort = '';
+ }
+
// Order by
- if (\Input::get('order_by'))
+ if ($order_by)
{
- if ($isInt(\Input::get('order_by')))
+ if ($isInt($order_by))
{
- $strQuery .= " ORDER BY CAST(" . \Input::get('order_by') . " AS SIGNED) " . \Input::get('sort');
+ $strQuery .= " ORDER BY CAST(" . $order_by . " AS SIGNED) " . $sort;
}
else
{
- $strQuery .= " ORDER BY " . \Input::get('order_by') . ' ' . \Input::get('sort');
+ $strQuery .= " ORDER BY " . $order_by . ' ' . $sort;
}
}
elseif ($this->list_sort)
@@ -210,9 +221,9 @@ protected function compile()
$objDataStmt = $this->Database->prepare($strQuery);
// Limit
- if (\Input::get('per_page'))
+ if ($per_page)
{
- $objDataStmt->limit(\Input::get('per_page'), (($page - 1) * $per_page));
+ $objDataStmt->limit($per_page, (($page - 1) * $per_page));
}
elseif ($this->perPage)
{
@@ -221,10 +232,7 @@ protected function compile()
$objData = $objDataStmt->execute($varKeyword);
-
- /**
- * Prepare the URL
- */
+ // Prepare the URL
$strUrl = preg_replace('/\?.*$/', '', \Environment::get('request'));
$blnQuery = false;
@@ -240,13 +248,9 @@ protected function compile()
$this->Template->url = $strUrl;
$strVarConnector = ($blnQuery || \Config::get('disableAlias')) ? '&' : '?';
-
- /**
- * Prepare the data arrays
- */
+ // Prepare the data arrays
$arrTh = array();
$arrTd = array();
- $arrFields = trimsplit(',', $this->list_fields);
// THEAD
for ($i=0, $c=count($arrFields); $i<$c; $i++)
@@ -262,10 +266,10 @@ protected function compile()
$strField = strlen($label = $GLOBALS['TL_DCA'][$this->list_table]['fields'][$arrFields[$i]]['label'][0]) ? $label : $arrFields[$i];
// Add a CSS class to the order_by column
- if (\Input::get('order_by') == $arrFields[$i])
+ if ($order_by == $arrFields[$i])
{
- $sort = (\Input::get('sort') == 'asc') ? 'desc' : 'asc';
- $class = ' sorted ' . \Input::get('sort');
+ $sort = ($sort == 'asc') ? 'desc' : 'asc';
+ $class = ' sorted ' . $sort;
}
$arrTh[] = array
@@ -310,7 +314,7 @@ protected function compile()
$arrTd[$class][$k] = array
(
'raw' => $v,
- 'content' => ($value ? $value : ' '),
+ 'content' => $value ?: ' ',
'class' => 'col_' . $j . (($j++ == 0) ? ' col_first' : '') . ($this->list_info ? '' : (($j >= (count($arrRows[$i]) - 1)) ? ' col_last' : '')),
'id' => $arrRows[$i][$this->strPk],
'field' => $k,
@@ -323,29 +327,23 @@ protected function compile()
$this->Template->thead = $arrTh;
$this->Template->tbody = $arrTd;
-
- /**
- * Pagination
- */
+ // Pagination
$objPagination = new \Pagination($objTotal->count, $per_page, \Config::get('maxPaginationLinks'), $id);
$this->Template->pagination = $objPagination->generate("\n ");
$this->Template->per_page = $per_page;
$this->Template->total = $objTotal->count;
-
- /**
- * Template variables
- */
+ // Template variables
$this->Template->action = \Environment::get('indexFreeRequest');
- $this->Template->details = ($this->list_info != '') ? true : false;
+ $this->Template->details = (bool) $this->list_info;
$this->Template->search_label = specialchars($GLOBALS['TL_LANG']['MSC']['search']);
$this->Template->per_page_label = specialchars($GLOBALS['TL_LANG']['MSC']['list_perPage']);
$this->Template->fields_label = $GLOBALS['TL_LANG']['MSC']['all_fields'][0];
$this->Template->keywords_label = $GLOBALS['TL_LANG']['MSC']['keywords'];
- $this->Template->search = \Input::get('search');
- $this->Template->for = \Input::get('for');
- $this->Template->order_by = \Input::get('order_by');
- $this->Template->sort = \Input::get('sort');
+ $this->Template->search = $strSearch;
+ $this->Template->for = $strFor;
+ $this->Template->order_by = $order_by;
+ $this->Template->sort = $sort;
$this->Template->col_last = 'col_' . $j;
}
diff --git a/system/modules/repository/classes/RepositorySettings.php b/system/modules/repository/classes/RepositorySettings.php
index 0cd0e40cf5..02aefd8c6a 100644
--- a/system/modules/repository/classes/RepositorySettings.php
+++ b/system/modules/repository/classes/RepositorySettings.php
@@ -17,6 +17,7 @@
// valid core versions in descending order
define('REPOSITORY_COREVERSIONS',
+ '30050319,30050319;'. // 3.5.31
'30050309,30050309;'. // 3.5.30
'30050299,30050299;'. // 3.5.29
'30050289,30050289;'. // 3.5.28