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/response_spec.rb
Views: 11788
1
require 'nokogiri'
2
3
RSpec.describe Rex::Proto::Http::Response do
4
5
let(:get_cookies_test_no_cookies) do
6
<<-HEREDOC.gsub(/^ {6}/, '')
7
HTTP/1.1 200 OK
8
Date: Fri, 26 Apr 2013 12:43:12 GMT
9
Server: Apache/2.2.22 (Ubuntu)
10
X-Powered-By: PHP/5.4.6-1ubuntu1.2
11
Expires: Thu, 19 Nov 1981 08:52:00 GMT
12
Cache-Control: private, max-age=10800, pre-check=10800
13
Last-Modified: Fri, 26 Apr 2013 12:01:52 GMT
14
Vary: Accept-Encoding
15
Content-Length: 63951
16
Keep-Alive: timeout=5, max=100
17
Connection: Keep-Alive
18
Content-Type: text/html
19
20
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">'
21
HEREDOC
22
end
23
24
let(:get_cookies_test_five_cookies) do
25
<<-HEREDOC.gsub(/^ {6}/, '')
26
HTTP/1.1 200 OK
27
Date: Fri, 26 Apr 2013 08:44:54 GMT
28
Server: Apache/2.2.22 (Ubuntu)
29
X-Powered-By: PHP/5.4.6-1ubuntu1.2
30
Set-Cookie: phpMyAdmin=gpjif0gtpqbvfion91ddtrq8p8vgjtue; path=/phpmyadmin/; HttpOnly
31
Expires: Thu, 19 Nov 1981 08:52:00 GMT
32
Cache-Control: private, max-age=10800, pre-check=10800
33
Last-Modified: Sun, 12 Aug 2012 13:38:18 GMT
34
Set-Cookie: pma_lang=en; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
35
Set-Cookie: pma_collation_connection=utf8_general_ci; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
36
Set-Cookie: pma_mcrypt_iv=mF1NmTE64IY%3D; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
37
Set-Cookie: phpMyAdmin=fmilioji5cn4m8bo5vjrrr6q9cada954; path=/phpmyadmin/; HttpOnly
38
Vary: Accept-Encoding
39
Content-Length: 7356
40
Keep-Alive: timeout=5, max=100
41
Connection: Keep-Alive
42
Content-Type: text/html; charset=utf-8
43
44
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
45
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
46
HEREDOC
47
end
48
49
let (:get_cookies_test_five_ordered_cookies) do
50
<<-HEREDOC.gsub(/^ {6}/, '')
51
HTTP/1.1 200 OK
52
Date: Fri, 26 Apr 2013 08:44:54 GMT
53
Server: Apache/2.2.22 (Ubuntu)
54
X-Powered-By: PHP/5.4.6-1ubuntu1.2
55
Expires: Thu, 19 Nov 1981 08:52:00 GMT
56
Cache-Control: private, max-age=10800, pre-check=10800
57
Last-Modified: Sun, 12 Aug 2012 13:38:18 GMT
58
Set-Cookie: pma_lang=en; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
59
Set-Cookie: pma_collation_connection=utf8_general_ci; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
60
Set-Cookie: pma_mcrypt_iv=mF1NmTE64IY%3D; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
61
Set-Cookie: phpMyAdmin=fmilioji5cn4m8bo5vjrrr6q9cada954; path=/phpmyadmin/; HttpOnly
62
Set-Cookie: superC00kie!=stupidcookie; Path=/parp/; domain=.foo.com; HttpOnly; Expires=Wed, 13-Jan-2012 22:23:01 GMT; Secure
63
Vary: Accept-Encoding
64
Content-Length: 7356
65
Keep-Alive: timeout=5, max=100
66
Connection: Keep-Alive
67
Content-Type: text/html; charset=utf-8
68
69
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
70
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
71
HEREDOC
72
end
73
74
let (:get_cookies_test_with_empty_cookie) do
75
<<-HEREDOC.gsub(/^ {6}/, '')
76
HTTP/1.1 200 OK
77
Date: Fri, 26 Apr 2013 08:44:54 GMT
78
Server: Apache/2.2.22 (Ubuntu)
79
X-Powered-By: PHP/5.4.6-1ubuntu1.2
80
Set-Cookie: phpMyAdmin=gpjif0gtpqbvfion91ddtrq8p8vgjtue; path=/phpmyadmin/; HttpOnly
81
Expires: Thu, 19 Nov 1981 08:52:00 GMT
82
Cache-Control: private, max-age=10800, pre-check=10800
83
Last-Modified: Sun, 12 Aug 2012 13:38:18 GMT
84
Set-Cookie: pma_lang=en; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
85
Set-Cookie: pma_collation_connection=utf8_general_ci; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
86
Set-Cookie: pma_mcrypt_iv=mF1NmTE64IY%3D; expires=Sun, 26-May-2013 08:44:54 GMT; path=/phpmyadmin/; httponly
87
Set-Cookie: phpMyAdmin=; path=/phpmyadmin/; HttpOnly
88
Vary: Accept-Encoding
89
Content-Length: 7356
90
Keep-Alive: timeout=5, max=100
91
Connection: Keep-Alive
92
Content-Type: text/html; charset=utf-8
93
94
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
95
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
96
HEREDOC
97
end
98
99
let (:get_cookies_test_one_set_cookie_header) do
100
<<-HEREDOC.gsub(/^ {6}/, '')
101
HTTP/1.1 200 OK
102
Date: Wed, 25 Sep 2013 20:29:23 GMT
103
Server: Apache/2.2.22 (Ubuntu)
104
X-Powered-By: PHP/5.4.9-4ubuntu2.2
105
Expires: Wed, 11 Jan 1984 05:00:00 GMT
106
Last-Modified: Wed, 25 Sep 2013 20:29:23 GMT
107
Cache-Control: no-cache, must-revalidate, max-age=0
108
Pragma: no-cache
109
Set-Cookie: wordpressuser_a97c5267613d6de70e821ff82dd1ab94=admin; path=/wordpress-2.0/, wordpresspass_a97c5267613d6de70e821ff82dd1ab94=c3284d0f94606de1fd2af172aba15bf3; path=/wordpress-2.0/
110
Vary: Accept-Encoding
111
Content-Length: 0
112
Content-Type: text/html; charset=UTF-8
113
114
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
115
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
116
HEREDOC
117
end
118
119
let (:get_cookies_comma_separated) do
120
<<-HEREDOC.gsub(/^ {6}/, '')
121
HTTP/1.1 200 OK
122
Expires: Thu, 26 Oct 1978 00:00:00 GMT
123
Content-Length: 8556
124
Server: CherryPy/3.1.2
125
Date: Sun, 06 Jul 2014 20:09:28 GMT
126
Cache-Control: no-store, max-age=0, no-cache, must-revalidate
127
Content-Type: text/html;charset=utf-8
128
Set-Cookie: cval=880350187, session_id_8000=83466b1a1a7a27ce13d35f78155d40ca3a1e7a28; expires=Mon, 07 Jul 2014 20:09:28 GMT; httponly; Path=/, uid=348637C4-9B10-485A-BFA9-5E892432FCFD; expires=Fri, 05-Jul-2019 20:09:28 GMT
129
130
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
131
<!--[if lt IE 7]> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://www.splunk.com/xhtml-extensions/1.0" xml:lang="en" lang="en" class="no-js lt-ie9 lt-ie8 lt-
132
HEREDOC
133
end
134
135
let (:get_cookies_spaces_and_missing_semicolon) do
136
<<-HEREDOC.gsub(/^ {6}/, '')
137
HTTP/1.1 200 OK
138
Set-Cookie: k1=v1; k2=v2;k3=v3
139
140
HEREDOC
141
end
142
143
let (:meta_name) do
144
'META_NAME'
145
end
146
147
let (:meta_content) do
148
'META_CONTENT'
149
end
150
151
let (:get_html_body) do
152
%Q|
153
<html>
154
<head>
155
<title>TEST</title>
156
<meta name="#{meta_name}" content="#{meta_content}">
157
</head>
158
<body>
159
<form action="test.php">
160
<input name="input_1" type="hidden" value="some_value_1" />
161
</form>
162
<form>
163
<input name="input_0" type="text" value="Not a hidden input" />
164
<input name="input_1" type="hidden" value="some_value_1" />
165
<INPUT name="input_2" type="hidden" value="" />
166
</form>
167
<script>
168
function test() {
169
alert("hello, world!");
170
}
171
</script>
172
</body>
173
</htm>
174
|
175
end
176
177
let (:get_xml_body) do
178
%Q|<?xml version="1.0"?>
179
<catalog>
180
<book id="bk101">
181
<author>Gambardella, Matthew</author>
182
<title>XML Developer's Guide</title>
183
<genre>Computer</genre>
184
<price>44.95</price>
185
<publish_date>2000-10-01</publish_date>
186
<description>An in-depth look at creating applications
187
with XML.</description>
188
</book>
189
</catalog>
190
|
191
end
192
193
let (:get_json_body) do
194
%Q|{ "firstName": "John" }|
195
end
196
197
def cookie_sanity_check(meth)
198
resp = described_class.new()
199
resp.parse(self.send meth)
200
cookies = resp.get_cookies
201
expect(cookies).not_to be_nil
202
expect(cookies).not_to be ''
203
cookies.split(';').map(&:strip)
204
end
205
206
describe 'HTML parsing' do
207
let(:response) do
208
res = Rex::Proto::Http::Response.new(200, 'OK')
209
res.body = get_html_body
210
res
211
end
212
213
subject do
214
cli = Rex::Proto::Http::Client.new('127.0.0.1')
215
cli.connect
216
req = cli.request_cgi({'uri'=>'/'})
217
res = cli.send_recv(req)
218
res
219
end
220
221
before(:example) do
222
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:request_cgi).with(any_args)
223
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:send_recv).with(any_args).and_return(response)
224
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:set_config).with(any_args)
225
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:close)
226
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:connect)
227
end
228
229
describe '#get_html_document' do
230
context 'when a response is received' do
231
it 'returns a Nokogiri::HTML::Document object' do
232
expect(subject.get_html_document).to be_kind_of(Nokogiri::HTML::Document)
233
end
234
end
235
end
236
237
describe '#get_xml_document' do
238
let(:response) do
239
res = Rex::Proto::Http::Response.new(200, 'OK')
240
res.body = get_xml_body
241
res
242
end
243
244
before(:example) do
245
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:send_recv).with(any_args).and_return(response)
246
end
247
248
context 'when a response is received' do
249
it 'returns a Nokogiri::XML::Document object' do
250
expect(subject.get_xml_document).to be_kind_of(Nokogiri::XML::Document)
251
end
252
end
253
end
254
255
describe '#get_json_document' do
256
let(:response) do
257
res = Rex::Proto::Http::Response.new(200, 'OK')
258
res.body = get_json_body
259
res
260
end
261
262
before(:example) do
263
allow_any_instance_of(Rex::Proto::Http::Client).to receive(:send_recv).with(any_args).and_return(response)
264
end
265
266
context 'when a response is received' do
267
it 'returns a Hash object' do
268
expect(subject.get_json_document).to be_kind_of(Hash)
269
end
270
end
271
end
272
273
describe '#get_html_meta_elements' do
274
let(:meta_elements) do
275
subject.get_html_meta_elements
276
end
277
278
context 'when there is a meta tag in the HTML body' do
279
it 'returns one Nokogiri::XML::Element object' do
280
expect(meta_elements.length).to eq(1)
281
end
282
283
it 'returns the meta tag name' do
284
expect(meta_elements.first.attributes['name'].value).to eq(meta_name)
285
end
286
287
it 'returns the meta tag content' do
288
expect(meta_elements.first.attributes['content'].value).to eq(meta_content)
289
end
290
end
291
end
292
293
describe '#get_html_scripts' do
294
let(:script_elements) do
295
subject.get_html_scripts
296
end
297
298
context 'when there is a script block' do
299
it 'returns one RKelly::Nodes::SourceElementsNode object' do
300
expect(script_elements.length).to eq(1)
301
expect(script_elements.first).to be_kind_of(RKelly::Nodes::SourceElementsNode)
302
end
303
end
304
end
305
306
describe '#get_hidden_inputs' do
307
context 'when an HTML page contains two forms containing hidden inputs' do
308
it 'returns an array' do
309
expect(subject.get_hidden_inputs).to be_kind_of(Array)
310
end
311
312
it 'returns hashes in the array' do
313
subject.get_hidden_inputs.each do |form|
314
expect(form).to be_kind_of(Hash)
315
end
316
end
317
318
it 'returns \'some_value_1\' in the input_1 hidden input from the first element' do
319
expect(subject.get_hidden_inputs[0]['input_1']).to eq('some_value_1')
320
end
321
322
it 'returns two hidden inputs in the second element' do
323
expect(subject.get_hidden_inputs[1].length).to eq(2)
324
end
325
326
it 'returns an empty string for the input_2 hidden input from the second element' do
327
expect(subject.get_hidden_inputs[1]['input_2']).to be_empty
328
end
329
end
330
end
331
end
332
333
334
context "#get_cookies" do
335
336
it 'returns empty string for no Set-Cookies' do
337
resp = described_class.new()
338
resp.parse(get_cookies_test_no_cookies)
339
expect(resp.get_cookies).to eq('')
340
end
341
342
it 'returns 5 cookies when given 5 cookies non-sequentially' do
343
cookies_array = cookie_sanity_check(:get_cookies_test_five_cookies)
344
expect(cookies_array.count).to eq(5)
345
expect(cookies_array).to match_array %w(
346
pma_lang=en
347
pma_collation_connection=utf8_general_ci
348
pma_mcrypt_iv=mF1NmTE64IY%3D
349
phpMyAdmin=fmilioji5cn4m8bo5vjrrr6q9cada954
350
phpMyAdmin=gpjif0gtpqbvfion91ddtrq8p8vgjtue
351
)
352
end
353
354
it 'returns and parses 5 cookies when given 5 ordered cookies' do
355
cookies_array = cookie_sanity_check(:get_cookies_test_five_ordered_cookies)
356
expect(cookies_array.count).to eq(5)
357
expected_cookies = %w{
358
pma_lang=en
359
pma_collation_connection=utf8_general_ci
360
pma_mcrypt_iv=mF1NmTE64IY%3D
361
phpMyAdmin=fmilioji5cn4m8bo5vjrrr6q9cada954
362
superC00kie!=stupidcookie
363
}
364
expected_cookies.shuffle!
365
expect(cookies_array).to include(*expected_cookies)
366
end
367
368
it 'parses an empty cookie value' do
369
cookies_array = cookie_sanity_check(:get_cookies_test_with_empty_cookie)
370
expect(cookies_array.count).to eq(5)
371
expected_cookies = %w{
372
pma_lang=en
373
pma_collation_connection=utf8_general_ci
374
pma_mcrypt_iv=mF1NmTE64IY%3D
375
phpMyAdmin=
376
phpMyAdmin=gpjif0gtpqbvfion91ddtrq8p8vgjtue
377
}
378
expected_cookies.shuffle!
379
expect(cookies_array).to include(*expected_cookies)
380
381
end
382
383
it 'parses multiple cookies in one Set-Cookie header' do
384
cookies_array = cookie_sanity_check(:get_cookies_test_one_set_cookie_header)
385
expect(cookies_array.count).to eq(2)
386
expected_cookies = %w{
387
wordpressuser_a97c5267613d6de70e821ff82dd1ab94=admin
388
wordpresspass_a97c5267613d6de70e821ff82dd1ab94=c3284d0f94606de1fd2af172aba15bf3
389
}
390
expected_cookies.shuffle!
391
expect(cookies_array).to include(*expected_cookies)
392
end
393
394
it 'parses comma separated cookies' do
395
cookies_array = cookie_sanity_check(:get_cookies_comma_separated)
396
expect(cookies_array.count).to eq(3)
397
expected_cookies = %w{
398
cval=880350187
399
session_id_8000=83466b1a1a7a27ce13d35f78155d40ca3a1e7a28
400
uid=348637C4-9B10-485A-BFA9-5E892432FCFD
401
}
402
expected_cookies.shuffle!
403
expect(cookies_array).to include(*expected_cookies)
404
end
405
406
it 'parses cookies with inconsistent spacing and a missing trailing semicolons' do
407
resp = described_class.new()
408
resp.parse(self.send :get_cookies_spaces_and_missing_semicolon)
409
cookies = resp.get_cookies_parsed
410
names = cookies.keys.sort
411
values = []
412
cookies.each do |_, parsed|
413
parsed.value.each do |value|
414
values << value
415
end
416
end
417
values.sort!
418
expect(names).to eq(%w(k1 k2 k3))
419
expect(values).to eq(%w(v1 v2 v3))
420
end
421
422
end
423
424
end
425
426
427