CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/spec/lib/rex/proto/http/client_request_spec.rb
Views: 11789
1
# -*- coding:binary -*-
2
require 'spec_helper'
3
4
5
6
RSpec.shared_context "with no evasions" do
7
before(:example) do
8
client_request.opts['uri_dir_self_reference'] = false
9
client_request.opts['uri_fake_params_start'] = false
10
client_request.opts['uri_full_url'] = false
11
end
12
13
it "should return the unmodified uri" do
14
expect(client_request.send(:set_uri)).to eq "/"
15
end
16
end
17
18
19
RSpec.shared_context "with 'uri_dir_self_reference'" do
20
before(:example) do
21
client_request.opts['uri_dir_self_reference'] = true
22
end
23
24
it "should have a self reference" do
25
expect(client_request.send(:set_uri)).to include("/./")
26
expect(client_request.to_s).to include("/./")
27
end
28
end
29
30
31
RSpec.shared_context "with 'uri_dir_fake_relative'" do
32
before(:example) do
33
client_request.opts['uri_dir_fake_relative'] = true
34
end
35
36
it "should contain sequences of '../'" do
37
expect(client_request.send(:set_uri)).to include("../")
38
expect(client_request.to_s).to include("../")
39
end
40
41
end
42
43
44
RSpec.shared_context "with 'uri_full_url'" do
45
46
before(:example) do
47
client_request.opts['uri_full_url'] = true
48
end
49
50
before(:example) do
51
client_request.opts['vhost'] = host
52
end
53
54
context "with ipv4 host" do
55
let(:host) { '192.0.2.1' }
56
57
it_behaves_like "uri_full_url"
58
end
59
60
context "with ipv6 host" do
61
let(:host) { '2001:DB8::1' }
62
63
it_behaves_like "uri_full_url"
64
end
65
66
context "with dns host" do
67
let(:host) { 'www.example.com' }
68
69
it_behaves_like "uri_full_url"
70
end
71
72
end
73
74
RSpec.shared_examples "uri_full_url" do
75
76
it "#set_uri should have the host in the URI" do
77
expect(client_request.send(:set_uri)).to start_with("http://#{host}/")
78
end
79
80
end
81
82
83
RSpec.describe Rex::Proto::Http::ClientRequest do
84
85
default_options = {
86
# All of these should be what you get when you pass in empty
87
# options, but of course that would make it too easy
88
'uri' => '/',
89
'method' => "GET",
90
'proto' => "HTTP",
91
'connection' => "close",
92
'version' => "1.1",
93
'port' => 80,
94
}
95
96
[
97
[ "with reasonable default options",
98
default_options.merge({
99
'agent' => "Mozilla/4.0 (compatible; Metasploit RSPEC)",
100
'vhost' => 'www.example.com',
101
}),
102
{
103
:set_uri => { :result => "/" },
104
:set_method => { :result => "GET" },
105
:set_version => { :result => "HTTP/1.1\r\n" },
106
:set_uri_prepend => { :result => "" },
107
:set_uri_append => { :result => "" },
108
:set_agent_header => { :result => "User-Agent: Mozilla/4.0 (compatible; Metasploit RSPEC)\r\n" },
109
:set_host_header => { :result => "Host: www.example.com\r\n" },
110
:set_formatted_header => { :args => ["Foo\twith\tabs", "Bar"], :result => "Foo\twith\tabs: Bar\r\n" },
111
}
112
],
113
114
[ "with header folding",
115
default_options.merge({
116
'agent' => "Mozilla/4.0 (compatible; Metasploit RSPEC)",
117
'header_folding' => true,
118
}),
119
{
120
:set_uri => { :result => "/" },
121
:set_method => { :result => "GET" },
122
:set_version => { :result => "HTTP/1.1\r\n" },
123
:set_agent_header => { :result => "User-Agent:\r\n\tMozilla/4.0 (compatible; Metasploit RSPEC)\r\n" },
124
:set_cookie_header => { :result => "" },
125
:set_connection_header => { :result => "Connection:\r\n\tclose\r\n" },
126
:set_formatted_header => { :args => ["Foo\twith\tabs", "Bar"], :result => "Foo\twith\tabs:\r\n\tBar\r\n" },
127
}
128
],
129
130
[ "with ipv6 host",
131
default_options.merge({
132
'vhost' => "2001:DB8::1",
133
}),
134
{
135
:set_host_header => { :result => "Host: [2001:DB8::1]\r\n" },
136
}
137
],
138
139
[ "with ipv6 host and non-default port",
140
default_options.merge({
141
'port' => 1234,
142
'vhost' => "2001:DB8::1",
143
}),
144
{
145
:set_host_header => { :result => "Host: [2001:DB8::1]:1234\r\n" },
146
}
147
],
148
149
[
150
"with modified Content-Length header",
151
default_options.merge({
152
'headers' => { 'Content-Length' => 1337 }
153
}),
154
{
155
:set_content_len_header => { args: 0, result: ''}
156
}
157
],
158
159
[
160
"with 1024 bytes of Content-Length",
161
default_options,
162
{
163
:set_content_len_header => { args: 1024, result: "Content-Length: 1024\r\n"}
164
}
165
],
166
167
[
168
"with a POST request and no payload body",
169
default_options.merge({
170
'method' => 'POST'
171
}),
172
{
173
:set_content_len_header => { args: 0, result: "Content-Length: 0\r\n"}
174
}
175
],
176
177
].each do |c, opts, expectations|
178
context c do
179
subject(:client_request) { Rex::Proto::Http::ClientRequest.new(opts) }
180
181
expectations.each do |meth, things|
182
args = things[:args] || []
183
result = things[:result]
184
describe "##{meth}" do
185
it "should return #{result.inspect}" do
186
expect(client_request.send(meth, *args)).to eq result
187
end
188
end
189
end
190
191
end
192
end
193
194
subject(:client_request) { Rex::Proto::Http::ClientRequest.new(default_options) }
195
196
context "with GET parameters" do
197
subject(:client_request) {
198
options_with_params = default_options.merge({
199
'uri_encode_mode' => encode_mode,
200
'encode_params' => encode_params,
201
'encode' => false,
202
'vars_get' => vars_get,
203
})
204
Rex::Proto::Http::ClientRequest.new(options_with_params)
205
}
206
# default
207
let(:encode_mode) { 'hex-normal' }
208
209
let(:vars_get) do
210
{
211
'foo[]' => 'bar',
212
'bar' => 'baz',
213
'frobnicate' => 'the froozle?',
214
'foshizzle' => 'my/nizzle',
215
'asdf' => nil,
216
'test' => ''
217
}
218
end
219
220
context "with 'pad_get_params'" do
221
let(:encode_params) { true }
222
it "should ..." do
223
old = client_request.opts['pad_get_params']
224
client_request.opts['pad_get_params'] = true
225
226
client_request.opts['pad_get_params_count'] = 0
227
expect(client_request.to_s.split("&").length).to eq vars_get.length
228
229
client_request.opts['pad_get_params_count'] = 10
230
expect(client_request.to_s.split("&").length).to eq vars_get.length + 10
231
232
client_request.opts['pad_get_params'] = old
233
end
234
end
235
236
context "without 'encode_params'" do
237
let(:encode_params) { false }
238
it "should contain the unaltered params" do
239
str = client_request.to_s
240
expect(str).to include("foo[]=bar")
241
expect(str).to include("bar=baz")
242
expect(str).to include("frobnicate=the froozle?")
243
expect(str).to include("foshizzle=my/nizzle")
244
expect(str).to include("asdf&")
245
expect(str).to include("test=")
246
end
247
end
248
249
context "with 'encode_params'" do
250
let(:encode_params) { true }
251
context "and 'uri_encode_mode' = default (hex-normal)" do
252
it "should encode special chars" do
253
str = client_request.to_s
254
expect(str).to include("foo%5b%5d=bar")
255
expect(str).to include("bar=baz")
256
expect(str).to include("frobnicate=the%20froozle%3f")
257
expect(str).to include("foshizzle=my/nizzle")
258
expect(str).to include("asdf&")
259
expect(str).to include("test=")
260
end
261
end
262
263
context "and 'uri_encode_mode' = hex-noslashes" do
264
let(:encode_mode) { 'hex-noslashes' }
265
it "should encode all chars" do
266
str = client_request.to_s
267
expect(str).to include("%66%6f%6f%5b%5d=%62%61%72")
268
expect(str).to include("%62%61%72=%62%61%7a")
269
expect(str).to include("%66%72%6f%62%6e%69%63%61%74%65=%74%68%65%20%66%72%6f%6f%7a%6c%65%3f")
270
expect(str).to include("%66%6f%73%68%69%7a%7a%6c%65=%6d%79/%6e%69%7a%7a%6c%65")
271
end
272
end
273
274
context "and 'uri_encode_mode' = hex-all" do
275
let(:encode_mode) { 'hex-all' }
276
it "should encode all chars" do
277
str = client_request.to_s
278
expect(str).to include("%66%6f%6f%5b%5d=%62%61%72")
279
expect(str).to include("%62%61%72=%62%61%7a")
280
expect(str).to include("%66%72%6f%62%6e%69%63%61%74%65=%74%68%65%20%66%72%6f%6f%7a%6c%65%3f")
281
expect(str).to include("%66%6f%73%68%69%7a%7a%6c%65=%6d%79%2f%6e%69%7a%7a%6c%65")
282
end
283
end
284
285
describe "#to_s" do
286
it "should produce same values if called multiple times with same options" do
287
expect(client_request.to_s).to eq client_request.to_s
288
end
289
end
290
291
end
292
293
end
294
295
describe "#set_uri" do
296
it_behaves_like "with 'uri_full_url'"
297
it_behaves_like "with 'uri_dir_self_reference'"
298
it_behaves_like "with 'uri_dir_fake_relative'"
299
it_behaves_like "with no evasions"
300
end
301
302
end
303
304