2
2
3
3
module Msf
4
4
5
- class Plugin ::HTTPRequests < Msf ::Plugin
5
+ class Plugin ::Requests < Msf ::Plugin
6
6
7
7
class ConsoleCommandDispatcher
8
8
include Msf ::Ui ::Console ::CommandDispatcher
9
9
10
10
def name
11
- 'HTTP Requests '
11
+ 'Request '
12
12
end
13
13
14
14
def commands
15
15
{
16
- 'httpr ' => 'Make an HTTP request'
16
+ 'request ' => 'Make a request of the specified type' ,
17
17
}
18
18
end
19
19
20
- def parse_args ( args )
21
- help_line = 'Usage: httpr [options] uri'
20
+ def types
21
+ # dynamically figure out what types are supported based on parse_args_*
22
+ parse_methods = self . public_methods . select { |m | m . to_s =~ /^parse_args_/ }
23
+ parse_methods . collect { |m | m . to_s . split ( '_' ) . slice ( 2 ..-1 ) . join ( '_' ) }
24
+ end
25
+
26
+ def cmd_request ( *args )
27
+ # grab and validate the first arg as type, which will affect how the
28
+ # remaining args are parsed
29
+ type = args . shift
30
+ # short circuit the whole deal if they need help
31
+ return help if ( !type || type =~ /^-?-h(?:elp)?$/ )
32
+ type . downcase!
33
+ opts , opt_parser = parse_args ( type , args )
34
+ if opts && opt_parser
35
+ if opts [ :output_file ]
36
+ begin
37
+ opts [ :output_file ] = File . new ( opts [ :output_file ] , 'w' )
38
+ rescue ::Errno ::EACCES , Errno ::EISDIR , Errno ::ENOTDIR
39
+ return help ( opt_parser , 'Failed to open the specified file for output' )
40
+ end
41
+ end
42
+ handler_method = "handle_request_#{ type } " . to_sym
43
+ if self . respond_to? ( handler_method )
44
+ # call the appropriate request handler
45
+ self . send ( handler_method , opts , opt_parser )
46
+ else
47
+ help ( opt_parser , "No request handler found for type (#{ type . to_s } )." )
48
+ end
49
+ else
50
+ help ( opt_parser , "No valid options provided for request #{ type } " )
51
+ end
52
+ end
53
+
54
+ def parse_args ( type , args )
55
+ type . downcase!
56
+ #print_line "type is #{type}"
57
+ parse_method = "parse_args_#{ type } " . to_sym
58
+ if self . respond_to? ( parse_method )
59
+ self . send ( parse_method , args , type )
60
+ else
61
+ print_line ( 'Unrecognized type.' )
62
+ help
63
+ end
64
+ end
65
+
66
+ def parse_args_http ( args = [ ] , type = 'http' )
22
67
opt_parser = Rex ::Parser ::Arguments . new (
23
68
'-0' => [ false , 'Use HTTP 1.0' ] ,
24
69
'-1' => [ false , 'Use TLSv1 (SSL)' ] ,
@@ -37,15 +82,10 @@ def parse_args(args)
37
82
)
38
83
39
84
options = {
40
- :auth_password => nil ,
41
- :auth_username => nil ,
42
- :headers => { } ,
85
+ :headers => { } ,
43
86
:print_body => true ,
44
87
:print_headers => false ,
45
- :method => nil ,
46
- :output_file => nil ,
47
88
:ssl_version => 'Auto' ,
48
- :uri => nil ,
49
89
:user_agent => Rex ::Proto ::Http ::Client ::DefaultUserAgent ,
50
90
:version => '1.1'
51
91
}
@@ -68,11 +108,9 @@ def parse_args(args)
68
108
when '-G'
69
109
options [ :method ] = 'GET'
70
110
when '-h'
71
- print_line ( help_line )
72
- print_line ( opt_parser . usage )
73
- return
111
+ return help ( opt_parser , "Usage: request #{ type } [options] uri" )
74
112
when '-H'
75
- name , _ , value = val . partition ( ':' )
113
+ name , _ , value = val . split ( ':' )
76
114
options [ :headers ] [ name ] = value . strip
77
115
when '-i'
78
116
options [ :print_headers ] = true
@@ -83,54 +121,24 @@ def parse_args(args)
83
121
when '-o'
84
122
options [ :output_file ] = File . expand_path ( val )
85
123
when '-u'
86
- val = val . partition ( ':' )
87
- options [ :auth_username ] = val [ 0 ]
88
- options [ :auth_password ] = val [ 2 ]
124
+ options [ :auth_username ] = val
125
+ when '-p'
126
+ options [ :auth_password ] = val
89
127
when '-X'
90
128
options [ :method ] = val
91
129
else
92
130
options [ :uri ] = val
93
131
end
94
132
end
95
-
96
- if options [ :uri ] . nil?
97
- print_line ( help_line )
98
- print_line ( opt_parser . usage )
99
- return
133
+ unless options [ :uri ]
134
+ return help ( opt_parser , "Usage: request #{ type } [options] uri" )
100
135
end
101
-
102
136
options [ :method ] ||= 'GET'
103
137
options [ :uri ] = URI ( options [ :uri ] )
104
- options
105
- end
106
-
107
- def output_line ( opts , line )
108
- if opts [ :output_file ] . nil?
109
- if line [ -2 ..-1 ] == "\r \n "
110
- print_line ( line [ 0 ..-3 ] )
111
- elsif line [ -1 ] == "\n "
112
- print_line ( line [ 0 ..-2 ] )
113
- else
114
- print_line ( line )
115
- end
116
- else
117
- opts [ :output_file ] . write ( line )
118
- end
138
+ [ options , opt_parser ]
119
139
end
120
140
121
- def cmd_httpr ( *args )
122
- opts = parse_args ( args )
123
- return unless opts
124
-
125
- unless opts [ :output_file ] . nil?
126
- begin
127
- opts [ :output_file ] = File . new ( opts [ :output_file ] , 'w' )
128
- rescue ::Errno ::EACCES , Errno ::EISDIR , Errno ::ENOTDIR
129
- print_error ( 'Failed to open the specified file for output' )
130
- return
131
- end
132
- end
133
-
141
+ def handle_request_http ( opts , opt_parser )
134
142
uri = opts [ :uri ]
135
143
http_client = Rex ::Proto ::Http ::Client . new (
136
144
uri . host ,
@@ -140,8 +148,8 @@ def cmd_httpr(*args)
140
148
opts [ :ssl_version ]
141
149
)
142
150
143
- unless opts [ :auth_username ] . nil?
144
- auth_str = opts [ :auth_username ] . to_s + ':' + opts [ :auth_password ] . to_s
151
+ if opts [ :auth_username ]
152
+ auth_str = opts [ :auth_username ] + ':' + opts [ :auth_password ]
145
153
auth_str = 'Basic ' + Rex ::Text . encode_base64 ( auth_str )
146
154
opts [ :headers ] [ 'Authorization' ] = auth_str
147
155
end
@@ -150,7 +158,7 @@ def cmd_httpr(*args)
150
158
151
159
begin
152
160
http_client . connect
153
- request = http_client . request_cgi (
161
+ req = http_client . request_cgi (
154
162
'agent' => opts [ :user_agent ] ,
155
163
'data' => opts [ :data ] ,
156
164
'headers' => opts [ :headers ] ,
@@ -162,7 +170,7 @@ def cmd_httpr(*args)
162
170
'version' => opts [ :version ]
163
171
)
164
172
165
- response = http_client . send_recv ( request )
173
+ response = http_client . send_recv ( req )
166
174
rescue ::OpenSSL ::SSL ::SSLError
167
175
print_error ( 'Encountered an SSL error' )
168
176
rescue ::Errno ::ECONNRESET => ex
@@ -176,8 +184,8 @@ def cmd_httpr(*args)
176
184
end
177
185
178
186
unless response
179
- opts [ :output_file ] . close unless opts [ :output_file ] . nil?
180
- return
187
+ opts [ :output_file ] . close if opts [ :output_file ]
188
+ return nil
181
189
end
182
190
183
191
if opts [ :print_headers ]
@@ -186,11 +194,35 @@ def cmd_httpr(*args)
186
194
end
187
195
188
196
output_line ( opts , response . body ) if opts [ :print_body ]
189
- unless opts [ :output_file ] . nil?
197
+ if opts [ :output_file ]
190
198
print_status ( "Wrote #{ opts [ :output_file ] . tell } bytes to #{ opts [ :output_file ] . path } " )
191
199
opts [ :output_file ] . close
192
200
end
193
201
end
202
+
203
+ def output_line ( opts , line )
204
+ if opts [ :output_file ] . nil?
205
+ if line [ -2 ..-1 ] == "\r \n "
206
+ print_line ( line [ 0 ..-3 ] )
207
+ elsif line [ -1 ] == "\n "
208
+ print_line ( line [ 0 ..-2 ] )
209
+ else
210
+ print_line ( line )
211
+ end
212
+ else
213
+ opts [ :output_file ] . write ( line )
214
+ end
215
+ end
216
+
217
+ def help ( opt_parser = nil , msg = 'Usage: request type [options]' )
218
+ print_line ( msg )
219
+ if opt_parser
220
+ print_line ( opt_parser . usage )
221
+ else
222
+ print_line ( "Valid types are: #{ types . join ( ', ' ) } " )
223
+ end
224
+ end
225
+
194
226
end
195
227
196
228
def initialize ( framework , opts )
@@ -199,18 +231,17 @@ def initialize(framework, opts)
199
231
end
200
232
201
233
def cleanup
202
- remove_console_dispatcher ( 'HTTP Requests ' )
234
+ remove_console_dispatcher ( 'Request ' )
203
235
end
204
236
205
237
def name
206
- 'HTTP Requests '
238
+ 'Request '
207
239
end
208
240
209
241
def desc
210
- 'Make HTTP requests from within Metasploit.'
242
+ 'Make requests from within Metasploit using various protocols .'
211
243
end
212
244
213
- protected
214
- end
245
+ end # end class
215
246
216
- end
247
+ end # end module
0 commit comments