From a1538dc3b2b83f8cf2370347ee25b055b1a97cfb Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 7 May 2020 12:17:51 +0200 Subject: [statistics] Stricter verification of IP addresses --- .../statistics/inc/statisticsfilter.inc.php | 34 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/modules-available/statistics/inc/statisticsfilter.inc.php b/modules-available/statistics/inc/statisticsfilter.inc.php index a038f076..e741652f 100644 --- a/modules-available/statistics/inc/statisticsfilter.inc.php +++ b/modules-available/statistics/inc/statisticsfilter.inc.php @@ -530,16 +530,44 @@ class IpStatisticsFilter extends StatisticsFilter parent::__construct('clientip', self::OP_NOMINAL, '1.2.3.4, 1.2.3.*, 1.2.3/24'); } - public function whereClause(string $operator, $argument, array &$args, array &$joins) + public function whereClause(string $operator, $argument, array &$args, array &$joins) : string { - $argument = preg_replace('#[^0-9.:/*]#', '', $argument); - if (strpos($argument, '/') !== false) { + $argument = strtolower(preg_replace('#[^0-9a-f.:/*]#i', '', $argument)); + if (filter_var($argument, FILTER_VALIDATE_IP) !== false) { + // Valid \o/ - do nothing to $argument + } elseif (strpos($argument, '/') !== false) { + // TODO: IPv6 CIDR $range = IpUtil::parseCidr($argument); if ($range === false) { Message::addError('invalid-cidr-notion', $argument); return '0'; } return 'INET_ATON(clientip) BETWEEN ' . $range['start'] . ' AND ' . $range['end']; + } elseif (($num = substr_count($argument, ':')) !== 0 && $num <= 7) { + // IPv6, not yet in DB but let's prepare + if ($num > 7 || strpos($argument, '::') !== false) { // Too many :, or invalid compressed format + Message::addError('invalid-ip-address', $argument); + return '0'; + } elseif ($num <= 7 && substr($argument, -1) === ':') { + $argument .= '*'; + } elseif ($num < 7) { + $argument .= ':*'; + } else { + Message::addError('invalid-ip-address', $argument); + return '0'; + } + } elseif (($num = substr_count($argument, '.')) !== 0 && $num <= 3) { + if (substr($argument, -1) === '.') { + $argument .= '*'; + } elseif ($num < 3) { + $argument .= '.*'; + } else { + Message::addError('invalid-ip-address', $argument); + return '0'; + } + } else { + Message::addError('invalid-ip-address', $argument); + return '0'; } return "clientip LIKE '" . str_replace('*', '%', $argument) . "'"; } -- cgit v1.2.3-55-g7522