diff --git a/CHANGELOG.md b/CHANGELOG.md index ab9e6c198b1b5cd884b6b105beb51befa09c1eff..9b63cc78b20e441a9db4950828b0d01fb2b12a05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ This is the Developer Changelog for Piwik platform developers. All changes in ou The Product Changelog at **[piwik.org/changelog](http://piwik.org/changelog)** lets you see more details about any Piwik release, such as the list of new guides and FAQs, security fixes, and links to all closed issues. +## Piwik 3.0.3 + +### Breaking Changes +* New config setting `enable_plugin_upload` let's you enable plugin upload. This used to work without any changes before, but is disabled by default now for security reasons. + ## Piwik 3.0.2 ### New Features diff --git a/config/global.ini.php b/config/global.ini.php index af3eb6f7b8f796343d88e6eae038b427bd176b22..1dc2dda8252b797b54349db983df4f0ae1ebe8a6 100644 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -539,6 +539,10 @@ enable_load_data_infile = 1 ; - links to Uninstall themes will be disabled (but user can still enable/disable themes) enable_plugins_admin = 1 +; By setting this option to 1, it will be possible to upload plugin archives directly in Piwik +; Enabling this opens a remote code execution vulnarability, which yould be used by attackers gaining access to Piwik admin +enable_plugin_upload = 0 + ; By setting this option to 0, you can prevent Super User from editing the Geolocation settings. enable_geolocation_admin = 1 diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php index 13872a3793f0cdc02c35a681fbadbe21535808e8..5861ae0a71f8a3ba3879d9059e695569198502e9 100644 --- a/plugins/CorePluginsAdmin/Controller.php +++ b/plugins/CorePluginsAdmin/Controller.php @@ -88,6 +88,10 @@ class Controller extends Plugin\ControllerAdmin static::dieIfPluginsAdminIsDisabled(); Piwik::checkUserHasSuperUserAccess(); + if (!CorePluginsAdmin::isPluginUploadEnabled()) { + throw new \Exception('Plugin upload disabled by config'); + } + $nonce = Common::getRequestVar('nonce', null, 'string'); if (!Nonce::verifyNonce(MarketplaceController::INSTALL_NONCE, $nonce)) { diff --git a/plugins/CorePluginsAdmin/CorePluginsAdmin.php b/plugins/CorePluginsAdmin/CorePluginsAdmin.php index df8934519beed401c6791212bf4d549d8a05d2da..d1c0a3fee11bbc8057938f275d01a82234a633bb 100644 --- a/plugins/CorePluginsAdmin/CorePluginsAdmin.php +++ b/plugins/CorePluginsAdmin/CorePluginsAdmin.php @@ -36,6 +36,11 @@ class CorePluginsAdmin extends Plugin return (bool) Config::getInstance()->General['enable_plugins_admin']; } + public static function isPluginUploadEnabled() + { + return (bool) Config::getInstance()->General['enable_plugin_upload']; + } + public function getJsFiles(&$jsFiles) { $jsFiles[] = "libs/bower_components/jQuery.dotdotdot/src/js/jquery.dotdotdot.min.js"; diff --git a/plugins/Marketplace/Controller.php b/plugins/Marketplace/Controller.php index 986ee5cf9ac6171f11773cfc14f275fcfa5f4dd0..d04e374f74e7e4af346cdf2b19783187d303be3b 100644 --- a/plugins/Marketplace/Controller.php +++ b/plugins/Marketplace/Controller.php @@ -271,6 +271,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin $view->isPluginsAdminEnabled = CorePluginsAdmin::isPluginsAdminEnabled(); $view->isAutoUpdatePossible = SettingsPiwik::isAutoUpdatePossible(); $view->isAutoUpdateEnabled = SettingsPiwik::isAutoUpdateEnabled(); + $view->isPluginUploadEnabled = CorePluginsAdmin::isPluginUploadEnabled(); return $view->render(); } diff --git a/plugins/Marketplace/lang/en.json b/plugins/Marketplace/lang/en.json index 1278adf2c2860f490486fed32018f1f4c032b075..f27bfc16bd1a14807de527a4e83d1a006cda4e31 100644 --- a/plugins/Marketplace/lang/en.json +++ b/plugins/Marketplace/lang/en.json @@ -103,6 +103,7 @@ "Updated": "Updated", "UpdatingPlugin": "Updating %1$s", "UploadZipFile": "Upload ZIP file", + "PluginUploadDisabled": "Plugin upload is disabled in config file. In order to enable this feature please update your configuration or contact your administrator", "LicenseKeyExpiresSoon": "Your license key expires soon, please contact %1$s.", "LicenseKeyIsExpired": "Your license key is expired, please contact %1$s.", "MultiServerEnvironmentWarning": "You cannot install or update the plugin directly as you are using Piwik on multiple servers. The plugin would be only installed on one server. Instead download the plugin and deploy it manually to all your servers.", diff --git a/plugins/Marketplace/templates/overview.twig b/plugins/Marketplace/templates/overview.twig index 9541ab0a168a79b5c7e9c63ee03aa249c5c9a809..76123fc2a1b118d5f9865b902942e2c6378f12b6 100644 --- a/plugins/Marketplace/templates/overview.twig +++ b/plugins/Marketplace/templates/overview.twig @@ -31,6 +31,7 @@ <div class="ui-confirm" id="installPluginByUpload"> <h2>{{ 'Marketplace_TeaserExtendPiwikByUpload'|translate }}</h2> + {% if isPluginUploadEnabled %} <p class="description"> {{ 'Marketplace_AllowedUploadFormats'|translate }} </p> <form enctype="multipart/form-data" method="post" id="uploadPluginForm" @@ -39,6 +40,12 @@ <br /> <input class="startUpload btn" type="submit" value="{{ 'Marketplace_UploadZipFile'|translate }}"> </form> + {% else %} + <p class="description"> {{ 'Marketplace_PluginUploadDisabled'|translate|raw }} </p> + <pre>[General] +enable_plugin_upload = 1</pre> + <input role="yes" type="button" value="{{ 'General_Ok'|translate }}"/> + {% endif %} </div> <div class="row marketplaceActions" ng-controller="PiwikMarketplaceController as marketplace"> diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png b/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png index b4569d0fe7c006fa878da719d41a46e15e7c47bf..352b8887f70d3cb12a63956ceb835c6bdf69594d 100644 Binary files a/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png and b/tests/UI/expected-screenshots/UIIntegrationTest_admin_diagnostics_configfile.png differ