Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes nexpose_connect login failure when user or password contains an @ symbol #14962

Merged
merged 1 commit into from
Mar 30, 2021

Conversation

cgranleese-r7
Copy link
Contributor

@cgranleese-r7 cgranleese-r7 commented Mar 29, 2021

This PR resolves #14865.

Previously if a user had an @ symbol present in their username or password, it would fail to login. This was down to the previous code calling .split on the string and this resulted in the string being split at the @ within the username/password.

Using .split method:

[9] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> args
=> ["admin:p@ssword@localhost:8000", "ok"]
[10] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> cred,targ = args[0].split('@', 2)
=> ["admin:p", "ssword@localhost:8000"]
[11] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> targ
=> "ssword@localhost:8000"
[12] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @user
=> "admin"
[13] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @pass
=> "p"
[14] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @host
=> "ssword@localhost"
[15] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @port
=> "8000"

This fixes now uses rpartition instead of split. This results in the right most @ symbol being where the string is split. The right most @ symbol should always be the last occurrence in our string, just before the target IP address.

rpartition docs.

Using .rpartition method:

Added a small code change. Added an additional variable called _split, that will be used to just take the @ symbol out of the equation.

Code change:

cred,_split,targ = args[0].rpartition('@')

Output:

[3] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> args
=> ["admin:p@ssword@localhost:8000", "ok"]
[4] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> cred,_split,targ = args[0].rpartition('@')
=> ["admin:p@ssword", "@", "localhost:8000"]
[5] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> cred
=> "admin:p@ssword"
[6] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> _split
=> "@"
[7] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> targ
=> "localhost:8000"
[8] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @user
=> "admin"
[9] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @pass
=> "p@ssword"
[10] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @host
=> "localhost"
[11] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @port
=> "8000"

Note

This has yet to be tested on a Nexpose server, hence why it is in draft. This fix has been tested by replicating @adfoster-r7's comment below.

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • Get a listener up and running in a separate tab ncat -lvnp 8000 --ssl
  • Run load nexpose
  • Verify the ncat response is returning the correct values
    e.g. output:
<LoginRequest password='p@ssword123' sync-id='0' user-id='admin'></LoginRequest>

@cgranleese-r7 cgranleese-r7 changed the title Fixes nexpose_connect login failure when user or password contains an @ symbol [Placeholder] Fixes nexpose_connect login failure when user or password contains an @ symbol Mar 29, 2021
@adfoster-r7
Copy link
Contributor

adfoster-r7 commented Mar 29, 2021

Verification steps in lieu of having a real nexpose running

Create a fake listener for nexpose:

ncat -lvnp 8000 --ssl

Trigger a login request

msfconsole
load nexpose
nexpose_connect admin:p@ssword123@localhost:8000 ok

Verify that the nexpose got the auth details.

Before

Request is sent the wrong credentials:

msf6 exploit(multi/http/werkzeug_debug_rce) > nexpose_connect admin:p@ssword123@localhost:8000 ok
[*] Connecting to Nexpose instance at ssword123@localhost:8000 with username admin...

Listener's log:

ncat -lvnp 8000 --ssl

Ncat: Version 7.91 ( https://nmap.org/ncat )
Ncat: Generating a temporary 2048-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.
Ncat: SHA-1 fingerprint: F936 050E 3998 7F32 C8BA F806 00D6 D262 D0D6 ED71
Ncat: Listening on :::8000
Ncat: Listening on 0.0.0.0:8000
Ncat: Connection from ::1.
Ncat: Connection from ::1:59127.
POST /api/1.1/xml HTTP/1.1
Content-Type: text/xml
Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: */*
User-Agent: Ruby
Connection: close
Host: localhost:8000
Content-Length: 70

<LoginRequest password='p' sync-id='0' user-id='admin'></LoginRequest>

After

It doesn't connect as expected:

> nexpose_connect admin:p@ssword123@localhost:8000 ok
[*] Connecting to Nexpose instance at @:3780 with username admin...
[-] Connection failed: Login Failed

And a break point shows the information isn't right either:

From: /Users/user/Documents/code/metasploit-framework/plugins/nexpose.rb:126 Msf::Plugin::Nexpose::NexposeCommandDispatcher#cmd_nexpose_connect:

    121:         @user,@pass = cred.split(':', 2)
    122:         targ ||= '127.0.0.1:3780'
    123:         @host,@port = targ.split(':', 2)
    124:         @port ||= '3780'
    125:         require 'pry'; binding.pry
 => 126:         unless args.length == 1
    127:           @trust_cert_file = args[1]
    128:           if File.exists? @trust_cert_file
    129:             @trust_cert = File.read(@trust_cert_file)
    130:           else
    131:             @sslv = @trust_cert_file

[1] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @user
=> "admin"
[2] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @pass
=> "p@ssword123"
[3] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @host
=> "@"
[4] pry(#<Msf::Plugin::Nexpose::NexposeCommandDispatcher>)> @port
=> "3780"

@cgranleese-r7 Looks like this needs a few more tweaks 👍

@adfoster-r7 adfoster-r7 self-assigned this Mar 29, 2021
@cgranleese-r7
Copy link
Contributor Author

@adfoster-r7, Ah I see, it's taking host as the @. Ok, I'll take a look at getting this sorted. Thanks for taking a look at this 👍

@cgranleese-r7
Copy link
Contributor Author

@adfoster-r7, got those changes added and tested using the method you outlined above, everything now seems to be working as expected 👍

@adfoster-r7
Copy link
Contributor

Retested the above scenarios and it seems to be sending valid login credentials now. Also verified that the login credentials are correctly escaped too

nexpose_connect admin:p@sswo\'rd123@localhost ok
<LoginRequest password='p@sswo&apos;rd123' sync-id='0' user-id='admin'></LoginRequest>

@adfoster-r7 adfoster-r7 marked this pull request as ready for review March 30, 2021 14:52
@adfoster-r7 adfoster-r7 merged commit fe61d92 into rapid7:master Mar 30, 2021
@adfoster-r7 adfoster-r7 changed the title [Placeholder] Fixes nexpose_connect login failure when user or password contains an @ symbol Fixes nexpose_connect login failure when user or password contains an @ symbol Mar 30, 2021
@adfoster-r7 adfoster-r7 added the rn-fix release notes fix label Mar 30, 2021
@adfoster-r7
Copy link
Contributor

adfoster-r7 commented Mar 30, 2021

Release Notes

Updated the nexpose_connect login functionality to correctly handle the @ symbol being present in the password.

@cgranleese-r7 cgranleese-r7 deleted the fix-nexpose-login-issue branch March 30, 2021 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rn-fix release notes fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

nexpose_connect with user or password containing @ failed failed to login
2 participants