CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/metasploit/framework/login_scanner/vnc.rb
Views: 1904
1
require 'metasploit/framework/tcp/client'
2
require 'metasploit/framework/login_scanner/base'
3
require 'metasploit/framework/login_scanner/rex_socket'
4
5
module Metasploit
6
module Framework
7
module LoginScanner
8
# This is the LoginScanner class for dealing with the VNC RFB protocol.
9
# It is responsible for taking a single target, and a list of credentials
10
# and attempting them. It then saves the results.
11
class VNC
12
include Metasploit::Framework::LoginScanner::Base
13
include Metasploit::Framework::LoginScanner::RexSocket
14
include Metasploit::Framework::Tcp::Client
15
16
17
#
18
# CONSTANTS
19
#
20
21
LIKELY_PORTS = (5900..5910).to_a
22
LIKELY_SERVICE_NAMES = [ 'vnc' ]
23
PRIVATE_TYPES = [ :password ]
24
REALM_KEY = nil
25
26
# Error indicating retry should occur for UltraVNC
27
ULTRA_VNC_RETRY_ERROR = 'connection has been rejected'
28
# Error indicating retry should occur for VNC 4 Server
29
VNC4_SERVER_RETRY_ERROR = 'Too many security failures'
30
# Known retry errors for all supported versions of VNC
31
RETRY_ERRORS = [
32
ULTRA_VNC_RETRY_ERROR,
33
VNC4_SERVER_RETRY_ERROR
34
]
35
36
# This method attempts a single login with a single credential against the target
37
# @param credential [Credential] The credential object to attempt to login with
38
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
39
def attempt_login(credential)
40
result_options = {
41
credential: credential,
42
host: host,
43
port: port,
44
protocol: 'tcp',
45
service_name: 'vnc'
46
}
47
48
begin
49
# Make our initial socket to the target
50
disconnect if self.sock
51
connect
52
53
# Create our VNC client overtop of the socket
54
vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false)
55
56
if vnc.handshake
57
type = vnc.negotiate_authentication
58
if type != Rex::Proto::RFB::AuthType::ARD
59
credential.public = nil
60
end
61
if vnc_auth(vnc,type,credential.public,credential.private)
62
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
63
else
64
result_options.merge!(
65
proof: vnc.error,
66
status: Metasploit::Model::Login::Status::INCORRECT
67
)
68
end
69
else
70
result_options.merge!(
71
proof: vnc.error,
72
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
73
)
74
end
75
rescue ::EOFError, Errno::ENOTCONN, Rex::ConnectionError, ::Timeout::Error => e
76
result_options.merge!(
77
proof: e.message,
78
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
79
)
80
ensure
81
disconnect
82
end
83
84
::Metasploit::Framework::LoginScanner::Result.new(result_options)
85
end
86
87
private
88
89
# Check the VNC error to see if we should wait and retry.
90
#
91
# @param error [String] The VNC error message received
92
# @return [false] don't retry
93
# @return [true] retry
94
def retry?(error)
95
RETRY_ERRORS.include?(error)
96
end
97
98
# This method sets the sane defaults for things
99
# like timeouts and TCP evasion options
100
def set_sane_defaults
101
self.connection_timeout ||= 30
102
self.port ||= 5900
103
self.max_send_size ||= 0
104
self.send_delay ||= 0
105
end
106
107
# This method attempts the actual VNC authentication. It has built in retries to handle
108
# delays built into the VNC RFB authentication.
109
# @param client [Rex::Proto::RFB::Client] The VNC client object to authenticate through
110
# @param type [Rex::Proto::RFB::AuthType] The VNC authentication type to attempt
111
# @param username [String] the username to attempt the authentication with
112
# @param password [String] the password to attempt the authentication with
113
def vnc_auth(client,type,username,password)
114
success = false
115
5.times do |n|
116
if client.authenticate_with_type(type,username,password)
117
success = true
118
break
119
end
120
break unless retry?(client.error)
121
122
# Wait for an increasing amount of time before retrying
123
delay = (2**(n+1)) + 1
124
::Rex.sleep(delay)
125
end
126
success
127
end
128
end
129
130
end
131
end
132
end
133
134