diff options
author | Stefan Giehl <stefan@matomo.org> | 2021-01-19 06:46:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-19 06:46:00 +0300 |
commit | 1a053135be3cf7267e970530235e5267160cd62c (patch) | |
tree | 0a24d95611ed0f1624eccfe31e7d40b7ff331a77 /plugins/GeoIp2 | |
parent | 4e55cd0ee759a73dd3479530ab1500ef2ba16488 (diff) |
Limit GeoIP downloads to certain hosts only (#17097)
* Limit GeoIP downloads to certains hosts only
* make geoip error message translatable
* apply review feedback
Diffstat (limited to 'plugins/GeoIp2')
-rw-r--r-- | plugins/GeoIp2/GeoIP2AutoUpdater.php | 40 | ||||
-rw-r--r-- | plugins/GeoIp2/lang/en.json | 2 | ||||
-rw-r--r-- | plugins/GeoIp2/tests/Unit/GeoIP2AutoUpdaterTest.php | 45 |
3 files changed, 81 insertions, 6 deletions
diff --git a/plugins/GeoIp2/GeoIP2AutoUpdater.php b/plugins/GeoIp2/GeoIP2AutoUpdater.php index bacc6fd660..5fd92541cb 100644 --- a/plugins/GeoIp2/GeoIP2AutoUpdater.php +++ b/plugins/GeoIp2/GeoIP2AutoUpdater.php @@ -11,6 +11,7 @@ namespace Piwik\Plugins\GeoIp2; use Exception; use GeoIp2\Database\Reader; use Piwik\Common; +use Piwik\Config; use Piwik\Container\StaticContainer; use Piwik\Date; use Piwik\Http; @@ -424,9 +425,9 @@ class GeoIP2AutoUpdater extends Task $url = $options[$optionKey]; $url = self::removeDateFromUrl($url); - if (!empty($url) && strpos(Common::mb_strtolower($url), 'https://') !== 0 && strpos(Common::mb_strtolower($url), 'http://') !== 0) { - throw new Exception('Invalid download URL for geoip ' . $optionKey . ': ' . $url); - } + + self::checkGeoIPUpdateUrl($url); + Option::set($optionName, $url); } @@ -452,6 +453,37 @@ class GeoIP2AutoUpdater extends Task } } + protected static function checkGeoIPUpdateUrl($url) + { + if (empty($url)) { + return; + } + + $parsedUrl = @parse_url($url); + $schema = $parsedUrl['scheme'] ?? ''; + $host = $parsedUrl['host'] ?? ''; + + if (empty($schema) || empty($host) || !in_array(Common::mb_strtolower($schema), ['http', 'https'])) { + throw new Exception(Piwik::translate('GeoIp2_MalFormedUpdateUrl', '<i>'.$url.'</i>')); + } + + $validHosts = Config::getInstance()->General['geolocation_download_from_trusted_hosts']; + $isValidHost = false; + + foreach ($validHosts as $validHost) { + if (preg_match('/(^|\.)' . preg_quote($validHost) . '$/i', $host)) { + $isValidHost = true; + break; + } + } + + if (true !== $isValidHost) { + throw new Exception(Piwik::translate('GeoIp2_InvalidGeoIPUpdateHost', [ + '<i>'.$url.'</i>', '<i>'.implode(', ', $validHosts).'</i>', '<i>geolocation_download_from_trusted_hosts</i>' + ])); + } + } + /** * Returns true if the auto-updater is setup to update at least one type of * database. False if otherwise. @@ -642,7 +674,7 @@ class GeoIP2AutoUpdater extends Task } // get the current filename for the DB and an available new one to rename it to - list($oldPath, $newPath) = $this->getOldAndNewPathsForBrokenDb($customNames[$type]); + [$oldPath, $newPath] = $this->getOldAndNewPathsForBrokenDb($customNames[$type]); // rename the DB so tracking will not fail if ($oldPath !== false diff --git a/plugins/GeoIp2/lang/en.json b/plugins/GeoIp2/lang/en.json index 4f57ee1665..b414ba4f92 100644 --- a/plugins/GeoIp2/lang/en.json +++ b/plugins/GeoIp2/lang/en.json @@ -44,6 +44,8 @@ "LocationProviderDesc_Php_WithExtension": "This location provider is speeded up by the installed %1$smaxminddb%2$s extension.", "LocationProviderDesc_ServerModule": "This location provider uses the GeoIP 2 module that has been installed in your HTTP server. This provider is fast and accurate, but %1$scan only be used with normal browser tracking.%2$s", "LocationProviderDesc_ServerModule2": "If you have to import log files or do something else that requires setting IP addresses, use the %3$sPHP GeoIP 2 implementation%4$s and install %1$smaxminddb extension%2$s.", + "MalFormedUpdateUrl": "The url %1$s seems invalid. Please ensure to input a valid url starting with http:// or https://", + "InvalidGeoIPUpdateHost": "The host of the GeoIP update url %1$s is not trusted. To allow downloading GeoIP updates from hosts other than %2$s please adjust the setting for %3$s in config. ", "NotManagingGeoIPDBs": "Matomo is currently not managing any DBIP or MaxMind databases.", "UnsupportedArchiveType": "Encountered unsupported archive type %1$s.", "UpdaterHasNotBeenRun": "The updater has never been run.", diff --git a/plugins/GeoIp2/tests/Unit/GeoIP2AutoUpdaterTest.php b/plugins/GeoIp2/tests/Unit/GeoIP2AutoUpdaterTest.php index 007c719756..3c9be2cd5c 100644 --- a/plugins/GeoIp2/tests/Unit/GeoIP2AutoUpdaterTest.php +++ b/plugins/GeoIp2/tests/Unit/GeoIP2AutoUpdaterTest.php @@ -8,8 +8,7 @@ namespace Piwik\Plugins\GeoIp2\tests\Unit; -use Piwik\DataTable; -use Piwik\DataTable\Row; +use Piwik\Config; use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater; class public_GeoIP2AutoUpdater extends GeoIP2AutoUpdater @@ -23,6 +22,10 @@ class public_GeoIP2AutoUpdater extends GeoIP2AutoUpdater { return parent::fetchPaidDbIpUrl($url); } + + public static function checkGeoIPUpdateUrl($url) { + return parent::checkGeoIPUpdateUrl($url); + } } /** @@ -146,4 +149,42 @@ class GeoIP2AutoUpdaterTest extends \PHPUnit\Framework\TestCase $this->assertEquals('https://download.db-ip.com/key/ad446bf4cb9a44e4fff3f215deabc710f12f3.mmdb', $determinedUrl); } + + /** + * @dataProvider getUpdaterUrlOptions + */ + public function testInvalidUpdateOptions($url, $valid) + { + if (!$valid) { + $this->expectException(\Exception::class); + } else { + $this->expectNotToPerformAssertions(); + } + public_GeoIP2AutoUpdater::checkGeoIPUpdateUrl($url); + } + + public function getUpdaterUrlOptions() + { + return [ + ['https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-ASN&license_key=YOUR_LICENSE_KEY&suffix=tar.gz', true], + ['https://download.db-ip.com/key/ad446bf4cb9a44e4fff3f215deabc710f12f3.mmdb', true], + ['https://download.db-ip.com/free/dbip-city-lite-2020-01.mmdb.gz', true], + ['https://db-ip.com/account/ad446bf4cb9a44e5ff3f215deabc710f12f3/db/ip-to-country/mmdb', true], + ['https://www.ip2location.com/download/?token={DOWNLOAD_TOKEN}&file={DATABASE_CODE}', true], + ['https://download.maxmind.com.fake.org/app/geoip_download?edition_id=GeoLite2-ASN&license_key=YOUR_LICENSE_KEY&suffix=tar.gz', false], + ['https://fakemaxmind.com/ad446bf4cb9a44e4fff3f215deabc710f12f3.mmdb', false], + ['https://fake-db-ip.com/account/ad446bf4cb9a44e5ff3f215deabc710f12f3/db/ip-to-country/mmdb', false], + ['http://my.custom.host/download.tar.gz', false], + ['phar://local/input.file', false], + ['ftp://db-ip.com/account/ad446bf4cb9a44e4fff3f215deabc710f12f3/db/ip-to-country/mmdb', false], + ['http://matomo.org/download/geoip.mmdb', false], + ]; + } + + public function testsAdditionalGeoIPHostConfig() + { + $this->expectNotToPerformAssertions(); + Config::getInstance()->General['geolocation_download_from_trusted_hosts'][] = 'matomo.org'; + public_GeoIP2AutoUpdater::checkGeoIPUpdateUrl('http://matomo.org/download/geoip.mmdb'); + } } |