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

Add FreeSwitch Login auxiliary module #16723

Merged

Conversation

krastanoel
Copy link
Contributor

This module is a login utility to find the password of the FreeSWITCH event socket service by bruteforcing the login interface. Note that this service does not require a username to log in; login is done purely via supplying a valid password.

Docker Installation

docker pull drachtio/drachtio-freeswitch-mrf
docker run -d --rm --name FS1 --net=host \
-v /home/deploy/log:/usr/local/freeswitch/log  \
-v /home/deploy/sounds:/usr/local/freeswitch/sounds \
-v /home/deploy/recordings:/usr/local/freeswitch/recordings \
drachtio/drachtio-freeswitch-mrf freeswitch --sip-port 5038 --tls-port 5039 --rtp-range-start 20000 --rtp-range-end 21000 --password hunter

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • use auxiliary/scanner/misc/freeswitch_event_socket_login
  • set RHOSTS [ips]
  • run
  • Verify if the login succeed

Demo

FreeSWITCH 1.10.7 Linux Debian 10 (buster)

msf6 > use auxiliary/scanner/misc/freeswitch_event_socket_login
msf6 auxiliary(scanner/misc/freeswitch_event_socket_login) > set RHOSTS 192.168.56.1
RHOSTS => 192.168.56.1
msf6 auxiliary(scanner/misc/freeswitch_event_socket_login) > set PASS_FILE /home/kali/passwords.txt
PASS_FILE => /home/kali/passwords.txt
msf6 auxiliary(scanner/misc/freeswitch_event_socket_login) > run

[!] 192.168.56.1:8021        - No active DB -- Credential data will not be saved!
[-] 192.168.56.1:8021        - 192.168.56.1:8021 - LOGIN FAILED: ClueCon (Incorrect: -ERR invalid)
[-] 192.168.56.1:8021        - 192.168.56.1:8021 - LOGIN FAILED: admin (Incorrect: -ERR invalid)
[-] 192.168.56.1:8021        - 192.168.56.1:8021 - LOGIN FAILED: 123456 (Incorrect: -ERR invalid)
[-] 192.168.56.1:8021        - 192.168.56.1:8021 - LOGIN FAILED: 12345 (Incorrect: -ERR invalid)
[-] 192.168.56.1:8021        - 192.168.56.1:8021 - LOGIN FAILED: 123456789 (Incorrect: -ERR invalid)
[-] 192.168.56.1:8021        - 192.168.56.1:8021 - LOGIN FAILED: password (Incorrect: -ERR invalid)
[+] 192.168.56.1:8021        - 192.168.56.1:8021 - Login Successful: hunter (Successful: +OK accepted)
[*] 192.168.56.1:8021        - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Copy link
Contributor

@cdelafuente-r7 cdelafuente-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @krastanoel for this contribution! I tested against a Docker installation and it works great! I also left a few comments/suggestions for you to review, when you get a chance.

@@ -0,0 +1,61 @@
## Description
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, could run msftidy_docs.rb and address what it reports?

ruby tools/dev/msftidy_docs.rb documentation/modules/auxiliary/scanner/misc/freeswitch_event_socket_login.md

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @cdelafuente-r7 for reviewing the module and thanks for the hint I didn't know this. I've run the msftidy docs and there are 5 warnings that I've corrected.

Comment on lines 61 to 67
@check = check_host(ip)
case @check.code
when 'safe'
fail_with(Failure::NoAccess, @check.reason)
when 'unknown'
fail_with(Failure::Unknown, @check.reason)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be handled automatically by the AutoCheck mixin, which calls the #check_host method and fails or continues according to the check code that is returned. You can remove these lines and just prepend the mixin at the beginning of the class definition:

  ...
  include Msf::Auxiliary::AuthBrute
  prepend Msf::Exploit::Remote::AutoCheck
Suggested change
@check = check_host(ip)
case @check.code
when 'safe'
fail_with(Failure::NoAccess, @check.reason)
when 'unknown'
fail_with(Failure::Unknown, @check.reason)
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks I forgot this mixin. Also added rescue when NoMethodError raised in case user use ForceExploit against unknown services.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Is there a specific location where this exception might be raised when scanning against unknown services?

Usually, NoMethodError exceptions are related to an issue in the code and should not happen. If such exception is raised, this means something needs to be fixed in the code to add the necessary checks or use the safe navigation operator to avoid it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you again for the hint! You're right the issue is in the code:

[*] 192.168.56.1:4444          - Running automatic check ("set AutoCheck false" to disable)
[!] 192.168.56.1:4444          - Cannot reliably check exploitability. Unable to determine the service fingerprint ForceExploit is enabled, proceeding with exploitation.
[-] 192.168.56.1:4444          - Auxiliary failed: NoMethodError undefined method `strip' for nil:NilClass
[-] 192.168.56.1:4444          - Call stack:
[-] 192.168.56.1:4444          -   /home/git/metasploit-framework/modules/auxiliary/scanner/misc/freeswitch_event_socket_login.rb:96:in `block in run_host'

I didn't pay attention on the error message for the strip method to use the safe navigation operator.

Comment on lines +69 to +72
cred_collection = Metasploit::Framework::PrivateCredentialCollection.new(
password: datastore['PASSWORD'],
pass_file: datastore['PASS_FILE']
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one potential issue when using the LoginScanner with credentials without usernames. During the scan, scan! will iterate around the credentials and keep track of successful login in successful_users data structure. Since there is no username, nil will be stored. The next iterations will check if the user's password has been already found by checking if the username (also nil) is present in successful_users. Since the unique username is nil, this will skip all the subsequent credentials.

As a result of this, all the credentials after the one that has been successful will be skipped. This means the datastore option STOP_ON_SUCCESS has no effect, even if it is set to false. This is something we could improve in Framework, but in the meantime, it might be a good idea to document this behavior and deregister the datastore option STOP_ON_SUCCESS to avoid confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know this, I've deregister the STOP_ON_SUCCESS option but not sure where and how to document this behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! You can add a line to documentation/modules/auxiliary/scanner/misc/freeswitch_event_socket_login.md, in the Description section, saying that the module stops as soon as a valid password is found. It will be fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this option is still used by the module line 73 and should also be removed. The stop_on_success attribute cannot be removed entirely, otherwise the scanner validation routine will fail. So, setting this attribute to true should be fine. Also, that would be a good idea to add a comment explaining this attribute will have no effect due to the scanner behavior when scanning without usernames.

    scanner = Metasploit::Framework::LoginScanner::FreeswitchEventSocket.new(
      host: ip,
      port: rport,
      cred_details: cred_collection,
      stop_on_success: true,
      connection_timeout: 10
    )

krastanoel and others added 7 commits June 30, 2022 11:38
Use include instead of regex and rescue stream closed error

Co-authored-by: cdelafuente-r7 <56716719+cdelafuente-r7@users.noreply.github.com>
this attribute is needed by LoginScanner module but will have no effect
Copy link
Contributor

@cdelafuente-r7 cdelafuente-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for updating this @krastanoel! Everything looks good now. I tested against a docker installation of FreeSwitch and verified the brute force attack worked. I'll go ahead and land it. This is a great module, thank you for your contribution!

Example output

msf6 auxiliary(scanner/misc/freeswitch_event_socket_login) > rerun verbose=true RHOSTS=127.0.0.1 PASS_FILE=/home/msf/tmp/password_list.txt RPORT=8022
[*] Reloading module...

[*] 127.0.0.1:8022        - Running automatic check ("set AutoCheck false" to disable)
[+] 127.0.0.1:8022        - The target appears to be vulnerable.
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: ClueCon (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: password (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 123456 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 12345678 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 1234 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: qwerty (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 12345 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: dragon (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: pussy (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: baseball (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: football (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: letmein (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: monkey (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 696969 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: abc123 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: mustang (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: michael (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: shadow (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: master (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: jennifer (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 111111 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 2000 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: jordan (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: superman (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: harley (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: 1234567 (Incorrect: -ERR invalid)
[-] 127.0.0.1:8022        - 127.0.0.1:8022 - LOGIN FAILED: fuckme (Incorrect: -ERR invalid)
[+] 127.0.0.1:8022        - 127.0.0.1:8022 - Login Successful: hunter (Successful: +OK accepted)
[*] 127.0.0.1:8022        - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/misc/freeswitch_event_socket_login) > creds
Credentials
===========

host       origin     service                public  private  realm  private_type  JtR Format
----       ------     -------                ------  -------  -----  ------------  ----------
127.0.0.1  127.0.0.1  8022/tcp (freeswitch)          hunter          Password

@cdelafuente-r7 cdelafuente-r7 added the rn-modules release notes for new or majorly enhanced modules label Jul 1, 2022
@cdelafuente-r7 cdelafuente-r7 merged commit b40dd95 into rapid7:master Jul 1, 2022
@cdelafuente-r7
Copy link
Contributor

Release Notes

This add an auxiliary scanner module that bruteforces the FreeSwitch's event socket service login interface to guess the password.

krastanoel added a commit to krastanoel/msf that referenced this pull request Jul 2, 2022
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants