aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Alexander <admin@m-a-styles.de>2016-12-28 22:53:59 +0100
committerMarc Alexander <admin@m-a-styles.de>2016-12-28 22:53:59 +0100
commitd63b644b2b976b6b067f779af91cc7699c4bd522 (patch)
treeb7f19ef4f4dbe16156a99428b19f3dee6423d612
parent442d21ace2b5d33e328917d7e7ac536709ba4d5c (diff)
parent90a77ba9d3e97718e9da7d1ee95ece4e756d26b7 (diff)
downloadforums-d63b644b2b976b6b067f779af91cc7699c4bd522.tar
forums-d63b644b2b976b6b067f779af91cc7699c4bd522.tar.gz
forums-d63b644b2b976b6b067f779af91cc7699c4bd522.tar.bz2
forums-d63b644b2b976b6b067f779af91cc7699c4bd522.tar.xz
forums-d63b644b2b976b6b067f779af91cc7699c4bd522.zip
Merge branch 'ticket/security-203' into ticket/security-203-rhea
-rw-r--r--phpBB/includes/functions.php5
-rw-r--r--phpBB/language/en/acp/common.php19
-rw-r--r--phpBB/phpbb/version_helper.php111
-rw-r--r--tests/version/version_helper_remote_test.php105
4 files changed, 200 insertions, 40 deletions
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 39d22254a2..f4e0ac8b26 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -2815,6 +2815,11 @@ function get_preg_expression($mode)
case 'path_remove_dot_trailing_slash':
return '#^(?:(\.)?)+(?:(.+)?)+(?:([\\/\\\])$)#';
break;
+
+ case 'semantic_version':
+ // Regular expression to match semantic versions by http://rgxdb.com/
+ return '/(?<=^[Vv]|^)(?:(?<major>(?:0|[1-9](?:(?:0|[1-9])+)*))[.](?<minor>(?:0|[1-9](?:(?:0|[1-9])+)*))[.](?<patch>(?:0|[1-9](?:(?:0|[1-9])+)*))(?:-(?<prerelease>(?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:0|[1-9](?:(?:0|[1-9])+)*))(?:[.](?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:0|[1-9](?:(?:0|[1-9])+)*)))*))?(?:[+](?<build>(?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:(?:0|[1-9])+))(?:[.](?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:(?:0|[1-9])+)))*))?)$/';
+ break;
}
return '';
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index acd9776dd7..6e28266e64 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -439,16 +439,19 @@ $lang = array_merge($lang, array(
'UPLOAD_DIR_SIZE' => 'Size of posted attachments',
'USERS_PER_DAY' => 'Users per day',
- 'VALUE' => 'Value',
- 'VERSIONCHECK_FAIL' => 'Failed to obtain latest version information.',
- 'VERSIONCHECK_FORCE_UPDATE' => 'Re-Check version',
- 'VERSION_CHECK' => 'Version check',
- 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.',
+ 'VALUE' => 'Value',
+ 'VERSIONCHECK_FAIL' => 'Failed to obtain latest version information.',
+ 'VERSIONCHECK_FORCE_UPDATE' => 'Re-Check version',
+ 'VERSION_CHECK' => 'Version check',
+ 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.',
+ 'VERSIONCHECK_INVALID_ENTRY' => 'Latest version information contains an unsupported entry.',
+ 'VERSIONCHECK_INVALID_URL' => 'Latest version information contains invalid URL.',
+ 'VERSIONCHECK_INVALID_VERSION' => 'Latest version information contains an invalid version.',
'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.<br />Below is a link to the release announcement, which contains more information as well as instructions on updating.',
'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.',
- 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.',
- 'VIEW_ADMIN_LOG' => 'View administrator log',
- 'VIEW_INACTIVE_USERS' => 'View inactive users',
+ 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.',
+ 'VIEW_ADMIN_LOG' => 'View administrator log',
+ 'VIEW_INACTIVE_USERS' => 'View inactive users',
'WELCOME_PHPBB' => 'Welcome to phpBB',
'WRITABLE_CONFIG' => 'Your config file (config.php) is currently world-writable. We strongly encourage you to change the permissions to 640 or at least to 644 (for example: <a href="http://en.wikipedia.org/wiki/Chmod" rel="external">chmod</a> 640 config.php).',
diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php
index 17caaa4a60..1d0583b960 100644
--- a/phpBB/phpbb/version_helper.php
+++ b/phpBB/phpbb/version_helper.php
@@ -60,6 +60,23 @@ class version_helper
/** @var \phpbb\file_downloader */
protected $file_downloader;
+ protected $version_schema = array(
+ 'stable' => array(
+ 'current' => 'version',
+ 'download' => 'url',
+ 'announcement' => 'url',
+ 'eol' => 'url',
+ 'security' => 'bool',
+ ),
+ 'unstable' => array(
+ 'current' => 'version',
+ 'download' => 'url',
+ 'announcement' => 'url',
+ 'eol' => 'url',
+ 'security' => 'bool',
+ ),
+ );
+
/**
* Constructor
*
@@ -223,7 +240,7 @@ class version_helper
*
* @param bool $force_update Ignores cached data. Defaults to false.
* @param bool $force_cache Force the use of the cache. Override $force_update.
- * @return string Version info
+ * @return array Version info
* @throws version_check_exception
*/
public function get_versions_matching_stability($force_update = false, $force_cache = false)
@@ -286,9 +303,101 @@ class version_helper
$info['stable'] = (empty($info['stable'])) ? array() : $info['stable'];
$info['unstable'] = (empty($info['unstable'])) ? $info['stable'] : $info['unstable'];
+ $info = $this->validate_versions($info);
+
$this->cache->put($cache_file, $info, 86400); // 24 hours
}
return $info;
}
+
+ /**
+ * Validate versions info input
+ *
+ * @param array $versions_info Decoded json data array. Will be modified
+ * and cleaned by this method
+ *
+ * @return array Versions info array
+ * @throws version_check_exception
+ */
+ public function validate_versions($versions_info)
+ {
+ $array_diff = array_diff_key($versions_info, array($this->version_schema));
+
+ // Remove excessive data
+ if (count($array_diff) > 0)
+ {
+ $old_versions_info = $versions_info;
+ $versions_info = array(
+ 'stable' => !empty($old_versions_info['stable']) ? $old_versions_info['stable'] : array(),
+ 'unstable' => !empty($old_versions_info['unstable']) ? $old_versions_info['unstable'] : array(),
+ );
+ unset($old_versions_info);
+ }
+
+ foreach ($versions_info as $stability_type => &$versions_data)
+ {
+ foreach ($versions_data as $branch => &$version_data)
+ {
+ if (!preg_match('/^[0-9a-z\-\.]+$/i', $branch))
+ {
+ unset($versions_data[$branch]);
+ continue;
+ }
+
+ $stability_diff = array_diff_key($version_data, $this->version_schema[$stability_type]);
+
+ if (count($stability_diff) > 0)
+ {
+ $old_version_data = $version_data;
+ $version_data = array();
+ foreach ($this->version_schema[$stability_type] as $key => $value)
+ {
+ if (isset($old_version_data[$key]))
+ {
+ $version_data[$key] = $old_version_data[$key];
+ }
+ }
+ unset($old_version_data);
+ }
+
+ foreach ($version_data as $key => &$value)
+ {
+ if (!isset($this->version_schema[$stability_type][$key]))
+ {
+ unset($version_data[$key]);
+ throw new version_check_exception('VERSIONCHECK_INVALID_ENTRY');
+ }
+
+ switch ($this->version_schema[$stability_type][$key])
+ {
+ case 'bool':
+ $value = (bool) $value;
+ break;
+
+ case 'url':
+ if (!empty($value) && !preg_match('#^' . get_preg_expression('url') . '$#iu', $value) &&
+ !preg_match('#^' . get_preg_expression('www_url') . '$#iu', $value))
+ {
+ throw new version_check_exception('VERSIONCHECK_INVALID_URL');
+ }
+ break;
+
+ case 'version':
+ if (!empty($value) && !preg_match(get_preg_expression('semantic_version'), $value))
+ {
+ throw new version_check_exception('VERSIONCHECK_INVALID_VERSION');
+ }
+ break;
+
+ default:
+ // Shouldn't be possible to trigger this
+ throw new version_check_exception('VERSIONCHECK_INVALID_ENTRY');
+ }
+ }
+ }
+ }
+
+ return $versions_info;
+ }
}
diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php
index fa383d487f..35c3d92a3a 100644
--- a/tests/version/version_helper_remote_test.php
+++ b/tests/version/version_helper_remote_test.php
@@ -51,8 +51,8 @@ class version_helper_remote_test extends \phpbb_test_case
public function provider_get_versions()
{
return array(
- array('', false),
- array('foobar', false),
+ array('', false, '', 'VERSIONCHECK_FAIL'),
+ array('foobar', false, '', 'VERSIONCHECK_FAIL'),
array('{
"stable": {
"1.0": {
@@ -93,7 +93,7 @@ class version_helper_remote_test extends \phpbb_test_case
"security": false
}
}
-}', false),
+}', false, '', 'VERSIONCHECK_FAIL'),
array('{
"stable": {
"1.0": {
@@ -104,26 +104,7 @@ class version_helper_remote_test extends \phpbb_test_case
"security": "<script>alert(\'foo\');</script>"
}
}
-}', true, array (
- 'stable' => array (
- '1.0' => array (
- 'current' => '1.0.1&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'download' => 'https://www.phpbb.com/customise/db/download/104136&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'eol' => '&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'security' => '&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- ),
- ),
- 'unstable' => array (
- '1.0' => array (
- 'current' => '1.0.1&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'download' => 'https://www.phpbb.com/customise/db/download/104136&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'eol' => '&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'security' => '&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- ),
- ),
- )),
+}', false, null, 'VERSIONCHECK_INVALID_VERSION'),
array('{
"unstable": {
"1.0": {
@@ -134,25 +115,87 @@ class version_helper_remote_test extends \phpbb_test_case
"security": "<script>alert(\'foo\');</script>"
}
}
+}', false, null, 'VERSIONCHECK_INVALID_VERSION'),
+ array('{
+ "unstable": {
+ "1.0<script>alert(\'foo\');</script>": {
+ "current": "1.0.1",
+ "download": "https://www.phpbb.com/customise/db/download/104136",
+ "announcement": "https://www.phpbb.com/customise/db/extension/boardrules/",
+ "eol": "",
+ "security": ""
+ }
+ }
+}', false, array('stable' => array(), 'unstable' => array()), 'VERSIONCHECK_INVALID_VERSION'),
+ array('{
+ "\"\n<script>alert(\'foo\');</script>\n": "test",
+ "stable": {
+ "1.0": {
+ "current": "1.0.1",
+ "download": "https://www.phpbb.com/customise/db/download/104136",
+ "announcement": "https://www.phpbb.com/customise/db/extension/boardrules/",
+ "eol": null,
+ "security": false
+ }
+ }
}', true, array (
+ 'stable' => array (
+ '1.0' => array (
+ 'current' => '1.0.1',
+ 'download' => 'https://www.phpbb.com/customise/db/download/104136',
+ 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/',
+ 'eol' => NULL,
+ 'security' => false,
+ ),
+ ),
'unstable' => array (
'1.0' => array (
- 'current' => '1.0.1&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'download' => 'https://www.phpbb.com/customise/db/download/104136&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'eol' => '&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
- 'security' => '&lt;script&gt;alert(\'foo\');&lt;/script&gt;',
+ 'current' => '1.0.1',
+ 'download' => 'https://www.phpbb.com/customise/db/download/104136',
+ 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/',
+ 'eol' => NULL,
+ 'security' => false,
),
),
- 'stable' => array(),
)),
+ array('{
+ "unstable": {
+ "1.0": {
+ "current": "1.0.1",
+ "download": "https://www.phpbb.com/customise/db/download/104136",
+ "announcement": "https://www.phpbb.com/customise/db/extension/boardrules/",
+ "eol": null,
+ "security": false,
+ "foobar": "<script>alert(\'test\');<script>"
+ }
+ }
+}', true, array('stable' => array(), 'unstable' => array('1.0' => array(
+ 'current' => '1.0.1',
+ 'download' => 'https://www.phpbb.com/customise/db/download/104136',
+ 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/',
+ 'security' => false,
+ ))), 'VERSIONCHECK_INVALID_ENTRY'),
+ array('{
+ "unstable": {
+ "1.0": {
+ "current<script>alert(\'foo\');</script>": "1.0.1",
+ "download2": "https://www.phpbb.com/customise/db/download/104136",
+ "bannouncement": "https://www.phpbb.com/customise/db/extension/boardrules/",
+ "eol": null,
+ "security": false,
+ "foobar": "<script>alert(\'test\');<script>"
+ }
+ }
+}', true, array('stable' => array(), 'unstable' => array('1.0' => array(
+ 'security' => false,
+ ))), 'VERSIONCHECK_INVALID_ENTRY'),
);
}
/**
* @dataProvider provider_get_versions
*/
- public function test_get_versions($input, $valid_data, $expected_return = '')
+ public function test_get_versions($input, $valid_data, $expected_return = '', $expected_exception = '')
{
$this->file_downloader->set($input);
@@ -161,7 +204,7 @@ class version_helper_remote_test extends \phpbb_test_case
try {
$return = $this->version_helper->get_versions();
} catch (\phpbb\exception\runtime_exception $e) {
- $this->assertEquals((string)$e->getMessage(), 'VERSIONCHECK_FAIL');
+ $this->assertEquals((string)$e->getMessage(), $expected_exception);
}
}
else