Skip to content

Commit 9808172

Browse files
committed
Address OPNSense login scanner PR feedback
1 parent 2b0d9b4 commit 9808172

File tree

3 files changed

+32
-31
lines changed

3 files changed

+32
-31
lines changed

documentation/modules/auxiliary/scanner/http/opnsense_login.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This module was specifically tested on version 25.1 and 21.1, with older version
66

77
Note:
88

9-
By default, OPNSense comes with a built-in account named ```root``` with the password being ```opnsense```.
9+
By default, OPNSense comes with a built-in account named `root` with the password being `opnsense`.
1010

1111
When performing too many login attempts, OPNSense will drop all packets coming from your IP, until the router is either:
1212
- Restarted
@@ -21,7 +21,12 @@ When performing too many login attempts, OPNSense will drop all packets coming f
2121
1. `set pass_file ...`
2222
1. `set user_file ...`
2323
1. `run`
24-
1. or, using some example inline options: `run pass_file=data/wordlists/default_pass_for_services_unhash.txt user_file=data/wordlists/default_pass_for_services_unhash.txt STOP_ON_SUCCESS=true SSL=true rport=443`
24+
1. or, using some example inline options:
25+
```
26+
run pass_file=data/wordlists/default_pass_for_services_unhash.txt \
27+
user_file=data/wordlists/default_pass_for_services_unhash.txt \
28+
STOP_ON_SUCCESS=true SSL=true rport=443
29+
```
2530
1. Verify you get a login:
2631
```
2732
[+] 192.168.207.158:443 - Login Successful: root:opnsense

lib/metasploit/framework/login_scanner/opnsense.rb

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,14 @@ module LoginScanner
99
# and attempting them. It then saves the results.
1010
class OPNSense < HTTP
1111

12+
# Retrieve the wanted cookie value by name from the HTTP response.
13+
#
14+
# @param [Rex::Proto::Http::Response] response The response from which to extract cookie values
15+
# @param [String] wanted_cookie_name The cookie name for which to get the value
1216
def get_cookie_value(response, wanted_cookie_name)
1317
response.get_cookies.split('; ').find { |cookie| cookie.start_with?(wanted_cookie_name) }.split('=').last
1418
end
1519

16-
# Sends a HTTP request with Rex
17-
#
18-
# @param (see Rex::Proto::Http::Request#request_raw)
19-
# @return [Rex::Proto::Http::Response] The HTTP response
20-
def send_request(opts, keep_cookies = false)
21-
res = super(opts)
22-
23-
if keep_cookies && res
24-
@php_sessid = get_cookie_value(res, 'PHPSESSID')
25-
@cookie_test = get_cookie_value(res, 'cookie_test')
26-
end
27-
28-
res
29-
end
30-
31-
# include Msf::Exploit::Remote::HTTP::OPNSense::Login
32-
# include Msf::Exploit::Remote::HTTP::HttpClient
33-
# define_method :send_request_cgi, Msf::Exploit::Remote::HttpClient.instance_method(:send_request_cgi)
3420
# Checks if the target is OPNSense. The login module should call this.
3521
#
3622
# @return [Boolean, String] FalseClass if target is OPNSense, otherwise String
@@ -48,13 +34,16 @@ def check_setup
4834
"Unable to locate \"Login | OPNsense\" in body. (Is this really OPNSense?)"
4935
end
5036

51-
def query_magic_value
37+
# Query the magic value and cookies from the OPNSense login page.
38+
#
39+
# @return [Hash<Symbol, Object>] A hash of the status and error or result.
40+
def query_magic_value_and_cookies
5241
request_params = {
5342
'method' => 'GET',
5443
'uri' => normalize_uri(@uri.to_s)
5544
}
5645

57-
res = send_request(request_params, keep_cookies = true)
46+
res = send_request(request_params)
5847

5948
if res.nil?
6049
return { status: :failure, error: 'Did not receive response to a GET request' }
@@ -75,17 +64,25 @@ def query_magic_value
7564
return { status: :failure, error: 'Could not find hidden magic field in the login form.' }
7665
end
7766

78-
{ status: :success, result: { name: magic_field['name'], value: magic_field['value'] } }
67+
magic_value = { name: magic_field['name'], value: magic_field['value'] }
68+
cookies = "PHPSESSID=#{get_cookie_value(res, 'PHPSESSID')}; cookie_test=#{get_cookie_value(res, 'cookie_test')}"
69+
{ status: :success, result: { magic_value: magic_value, cookies: cookies } }
7970
end
8071

8172
# Each individual login needs their own magic name and value.
82-
# This magic value comes from the login form received in response to a GET request to the login page
83-
def try_login(username, password, magic_value)
73+
# This magic value comes from the login form received in response to a GET request to the login page.
74+
# Each login attempt also requires specific cookies to be set, otherwise an error is returned.
75+
#
76+
# @param username Username
77+
# @param password Password
78+
# @param magic_value A hash containing the magic_value name and value
79+
# @param cookies A cookie string
80+
def try_login(username, password, magic_value, cookies)
8481
request_params =
8582
{
8683
'method' => 'POST',
8784
'uri' => normalize_uri(@uri.to_s),
88-
'cookie' => "PHPSESSID=#{@php_sessid}; cookie_test=#{@cookie_test}",
85+
'cookie' => cookies,
8986
'vars_post' => {
9087
magic_value[:name] => magic_value[:value],
9188
'usernamefld' => username,
@@ -107,14 +104,14 @@ def attempt_login(credential)
107104
}
108105

109106
# Each login needs its own magic name and value
110-
magic_value = query_magic_value
107+
magic_value_and_cookies = query_magic_value_and_cookies
111108

112-
if magic_value[:status] != :success
113-
result_options.merge!(status: ::Metasploit::Model::Login::Status::UNTRIED, proof: magic_value[:error])
109+
if magic_value_and_cookies[:status] != :success
110+
result_options.merge!(status: ::Metasploit::Model::Login::Status::UNTRIED, proof: magic_value_and_cookies[:error])
114111
return Result.new(result_options)
115112
end
116113

117-
login_result = try_login(credential.public, credential.private, magic_value[:result])
114+
login_result = try_login(credential.public, credential.private, magic_value_and_cookies[:result][:magic_value], magic_value_and_cookies[:result][:cookies])
118115

119116
if login_result[:result].nil?
120117
result_options.merge!(status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to OPNSense')

modules/auxiliary/scanner/http/opnsense_login.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ def run_host(ip)
8989
connection_timeout: datastore['HttpClientTimeout'] || 5,
9090
framework: framework,
9191
framework_module: self,
92-
http_success_codes: [302],
9392
method: 'POST',
9493
ssl: datastore['SSL']
9594
)

0 commit comments

Comments
 (0)