Class: Metasploit::Framework::LoginScanner::Ivanti
- Defined in:
- lib/metasploit/framework/login_scanner/ivanti_login.rb
Overview
Ivanti Login Scanner supporting
-
User Login
-
Admin Login
Constant Summary collapse
- DEFAULT_SSL_PORT =
443
- LIKELY_PORTS =
[443]
- LIKELY_SERVICE_NAMES =
[ 'Ivanti Connect Secure' ]
- PRIVATE_TYPES =
[:password]
- REALM_KEY =
nil
Constants inherited from HTTP
HTTP::AUTHORIZATION_HEADER, HTTP::DEFAULT_HTTP_NOT_AUTHED_CODES, HTTP::DEFAULT_HTTP_SUCCESS_CODES, HTTP::DEFAULT_PORT, HTTP::DEFAULT_REALM
Instance Attribute Summary
Attributes inherited from HTTP
#digest_auth_iis, #evade_header_folding, #evade_method_random_case, #evade_method_random_invalid, #evade_method_random_valid, #evade_pad_fake_headers, #evade_pad_fake_headers_count, #evade_pad_get_params, #evade_pad_get_params_count, #evade_pad_method_uri_count, #evade_pad_method_uri_type, #evade_pad_post_params, #evade_pad_post_params_count, #evade_pad_uri_version_count, #evade_pad_uri_version_type, #evade_shuffle_get_params, #evade_shuffle_post_params, #evade_uri_dir_fake_relative, #evade_uri_dir_self_reference, #evade_uri_encode_mode, #evade_uri_fake_end, #evade_uri_fake_params_start, #evade_uri_full_url, #evade_uri_use_backslashes, #evade_version_random_invalid, #evade_version_random_valid, #http_password, #http_success_codes, #http_username, #keep_connection_alive, #kerberos_authenticator_factory, #method, #ntlm_domain, #ntlm_send_lm, #ntlm_send_ntlm, #ntlm_send_spn, #ntlm_use_lm_key, #ntlm_use_ntlmv2, #ntlm_use_ntlmv2_session, #uri, #user_agent, #vhost
Instance Method Summary collapse
-
#attempt_login(credential) ⇒ Result
Attempts to login to the server.
- #check_setup ⇒ Object
- #create_admin_request(username, password, token, protocol, peer) ⇒ Object
- #create_user_request(username, password, protocol, peer) ⇒ Object
- #do_admin_login(username, password) ⇒ Object
- #do_admin_logout(cookies) ⇒ Object
- #do_login(username, password) ⇒ Object
- #do_logout(cookies) ⇒ Object
- #get_token ⇒ Object
-
#initialize(scanner_config, admin) ⇒ Ivanti
constructor
A new instance of Ivanti.
Methods inherited from HTTP
#authentication_required?, #send_request
Constructor Details
#initialize(scanner_config, admin) ⇒ Ivanti
Returns a new instance of Ivanti.
19 20 21 22 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 19 def initialize(scanner_config, admin) @admin = admin super(scanner_config) end |
Instance Method Details
#attempt_login(credential) ⇒ Result
Attempts to login to the server.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 171 def attempt_login(credential) # focus on creating Result object, pass it to #login routine and return Result object = { credential: credential, host: @host, port: @port, protocol: 'tcp', service_name: 'ivanti' } if @admin login_result = do_admin_login(credential.public, credential.private) else login_result = do_login(credential.public, credential.private) end .merge!(login_result) Result.new() end |
#check_setup ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 24 def check_setup request_params = { 'method' => 'GET', 'uri' => normalize_uri('/dana-na/auth/url_default/welcome.cgi') } res = send_request(request_params) if res && res.code == 200 && res.body&.include?('Ivanti Connect Secure') return false end 'Application might not be Ivanti Connect Secure, please check' end |
#create_admin_request(username, password, token, protocol, peer) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 39 def create_admin_request(username, password, token, protocol, peer) { 'method' => 'POST', 'uri' => normalize_uri('/dana-na/auth/url_admin/login.cgi'), 'ctype' => 'application/x-www-form-urlencoded', 'headers' => { 'Origin' => "#{protocol}://#{peer}", 'Referer' => "#{protocol}://#{peer}/dana-na/auth/url_admin/welcome.cgi" }, 'vars_post' => { tz_offset: '60', xsauth_token: token, username: username, password: password, realm: 'Admin+Users', btnSubmit: 'Sign+In' }, 'encode_params' => false } end |
#create_user_request(username, password, protocol, peer) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 111 def create_user_request(username, password, protocol, peer) { 'method' => 'POST', 'uri' => normalize_uri('/dana-na/auth/url_default/login.cgi'), 'ctype' => 'application/x-www-form-urlencoded', 'headers' => { 'Origin' => "#{protocol}://#{peer}", 'Referer' => "#{protocol}://#{peer}/dana-na/auth/url_default/welcome.cgi" }, 'vars_post' => { tz_offset: '', win11: '', clientMAC: '', username: username, password: password, realm: 'Users', btnSubmit: 'Sign+In' }, 'encode_params' => false } end |
#do_admin_login(username, password) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 83 def do_admin_login(username, password) token = get_token return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if token.blank? protocol = ssl ? 'https' : 'http' peer = "#{host}:#{port}" admin_req = create_admin_request(username, password, token, protocol, peer) begin res = send_request(admin_req) rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error, ::EOFError => e return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e } end return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if res.nil? return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: "Received an unexpected status code: #{res.code}" } if res.code != 302 return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unexpected response' } if !res.headers&.key?('location') return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s } if res.headers['location'] == '/dana-na/auth/url_admin/welcome.cgi?p=admin%2Dconfirm' if res.headers['location'] == '/dana-admin/misc/admin.cgi' do_admin_logout(res.) return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s } end return { status: ::Metasploit::Model::Login::Status::INCORRECT, proof: res.to_s } end |
#do_admin_logout(cookies) ⇒ Object
62 63 64 65 66 67 68 69 70 71 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 62 def do_admin_logout() admin_page_res = send_request({ 'method' => 'GET', 'uri' => normalize_uri('/dana-admin/misc/admin.cgi?'), 'cookie' => }) admin_page_s = admin_page_res.to_s re = /xsauth=[a-z0-9]{32}/ xsauth = re.match(admin_page_s) return nil if xsauth.nil? send_request({ 'method' => 'GET', 'uri' => normalize_uri('/dana-na/auth/logout.cgi?' + xsauth[0]), 'cookie' => }) end |
#do_login(username, password) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 139 def do_login(username, password) protocol = ssl ? 'https' : 'http' peer = "#{host}:#{port}" user_req = create_user_request(username, password, protocol, peer) begin res = send_request(user_req) rescue ::Rex::ConnectionError, ::Rex::ConnectionProxyError, ::Errno::ECONNRESET, ::Errno::EINTR, ::Rex::TimeoutError, ::Timeout::Error, ::EOFError => e return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e } end return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if res.nil? return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: "Received an unexpected status code: #{res.code}" } if res.code != 302 return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unexpected response' } if !res.headers&.key?('location') if res.headers['location'] == '/dana-na/auth/url_default/welcome.cgi?p=ip%2Dblocked' sleep(2 * 60) # 2 minutes res = send_request(user_req) end return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s } if res.headers['location'] == '/dana-na/auth/url_default/welcome.cgi?p=user%2Dconfirm' if res.headers['location'] == '/dana/home/starter0.cgi?check=yes' do_logout(res.) return { status: ::Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.to_s } else return { status: ::Metasploit::Model::Login::Status::INCORRECT, proof: res.to_s } end end |
#do_logout(cookies) ⇒ Object
135 136 137 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 135 def do_logout() send_request({ 'uri' => normalize_uri('/dana-na/auth/logout.cgi?delivery=psal'), 'cookie' => }) end |
#get_token ⇒ Object
73 74 75 76 77 78 79 80 81 |
# File 'lib/metasploit/framework/login_scanner/ivanti_login.rb', line 73 def get_token res = send_request({ 'uri' => normalize_uri('/dana-na/auth/url_admin/welcome.cgi') }) return { status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to the Ivanti service' } if res.nil? html_document = res.get_html_document html_document.xpath('//input[@id="xsauth_token"]/@value')&.text end |