Piwik - Possible XSS in RDNS lookup function

The possible XSS vulnerability can be found in version 3.1.1 of the Piwik software itself. The getHostname() function in piwik/vendor/piwik/network/src/IP.php does not sanitize the hostname before returning the value. This results in a possible XSS if Piwik itself or any plugins use the output from the function without further sanitization.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# piwik\vendor\piwik\network\src\IP.php


104    public function getHostname()
105    {
106        $stringIp = $this->toString();
107
108        $host = strtolower(@gethostbyaddr($stringIp));
109
110        if ($host === '' || $host === $stringIp) {
111            return null;
112        }
113
114       return $host;
115    }

Attack steps

As described by another security researcher here, an attacker will need to be in control of an IP address where he can set the RDNS hostname to return JS script tags. After that, the attacker tunnels his traffic through that IP address and visits the target site. The getHostname() function will then resolve the IP address and obtain the JS code. Since it is not sanitized, any function which directly stores or displays the hostname will be susceptible to XSS.

Impact

Fortunately, to the best of my knowledge, none of the Piwik software itself directly stores or displays the hostname. Hence, Piwik software itself is not vulnerable. However, at least one Piwik marketplace plugin is vulnerable. The IP 2 Hostname plugin (https://plugins.piwik.org/Ip2Hostname) will directly store the JS code into the database. If it is displayed in a twig template with |raw filter, the code will be executed. I have not tested all plugins, hence I do not know if there are other plugins which are also vulnerable.

Testing

Due to the difficulty in obtaining an IP address with the possibility of setting valid JS as the RDNS hostname, it can be tested by poisoning the /etc/hosts file on the machine running Piwik. In the case below, visiting a website with Piwik and the IP 2 Hostname plugin activated from a machine with IP 192.168.1.100 will cause the hostname to be resolved as the JS code and stored into the database.

1
2
3
cat /etc/hosts
127.0.0.1       localhost
192.168.1.100   <script>alert("1");</script> 

image

Remediation

Since it does not seem to have any direct impact, the piwik team have decided to create a public issue in the repository of the project here and will address the issue in future.