metasploit_data_models 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +8 -8
  2. data/app/models/mdm/host.rb +7 -0
  3. data/app/models/mdm/service.rb +30 -1
  4. data/app/models/mdm/tag.rb +10 -0
  5. data/app/models/metasploit_data_models/ip_address/v4/cidr.rb +14 -0
  6. data/app/models/metasploit_data_models/ip_address/v4/nmap.rb +14 -0
  7. data/app/models/metasploit_data_models/ip_address/v4/range.rb +12 -0
  8. data/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list.rb +126 -0
  9. data/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range.rb +12 -0
  10. data/app/models/metasploit_data_models/ip_address/v4/segment/single.rb +123 -0
  11. data/app/models/metasploit_data_models/ip_address/v4/segmented.rb +200 -0
  12. data/app/models/metasploit_data_models/ip_address/v4/single.rb +53 -0
  13. data/app/models/metasploit_data_models/search/operation/ip_address.rb +60 -0
  14. data/app/models/metasploit_data_models/search/operator/ip_address.rb +33 -0
  15. data/app/models/metasploit_data_models/search/visitor/attribute.rb +1 -0
  16. data/app/models/metasploit_data_models/search/visitor/includes.rb +1 -0
  17. data/app/models/metasploit_data_models/search/visitor/joins.rb +1 -0
  18. data/app/models/metasploit_data_models/search/visitor/where.rb +51 -0
  19. data/config/locales/en.yml +35 -4
  20. data/lib/metasploit_data_models/ip_address.rb +5 -0
  21. data/lib/metasploit_data_models/ip_address/cidr.rb +174 -0
  22. data/lib/metasploit_data_models/ip_address/range.rb +181 -0
  23. data/lib/metasploit_data_models/match/child.rb +48 -0
  24. data/lib/metasploit_data_models/match/parent.rb +103 -0
  25. data/lib/metasploit_data_models/version.rb +4 -4
  26. data/metasploit_data_models.gemspec +2 -1
  27. data/spec/app/models/mdm/cred_spec.rb +164 -31
  28. data/spec/app/models/mdm/service_spec.rb +33 -44
  29. data/spec/app/models/metasploit_data_models/ip_address/v4/cidr_spec.rb +121 -0
  30. data/spec/app/models/metasploit_data_models/ip_address/v4/nmap_spec.rb +151 -0
  31. data/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb +300 -0
  32. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb +278 -0
  33. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb +304 -0
  34. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb +29 -0
  35. data/spec/app/models/metasploit_data_models/ip_address/v4/segment/single_spec.rb +315 -0
  36. data/spec/app/models/metasploit_data_models/ip_address/v4/single_spec.rb +183 -0
  37. data/spec/app/models/metasploit_data_models/search/operation/ip_address_spec.rb +182 -0
  38. data/spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb +19 -0
  39. data/spec/app/models/metasploit_data_models/search/visitor/relation_spec.rb +229 -36
  40. data/spec/dummy/config/application.rb +1 -1
  41. data/spec/dummy/db/structure.sql +3011 -0
  42. data/spec/factories/mdm/services.rb +3 -1
  43. data/spec/lib/metasploit_data_models/ip_address/cidr_spec.rb +350 -0
  44. data/spec/lib/metasploit_data_models/ip_address/range_spec.rb +77 -0
  45. data/spec/lib/metasploit_data_models/match/child_spec.rb +61 -0
  46. data/spec/lib/metasploit_data_models/match/parent_spec.rb +155 -0
  47. data/spec/support/matchers/match_regex_exactly.rb +28 -0
  48. data/spec/support/shared/contexts/rex/text.rb +15 -0
  49. data/spec/support/shared/examples/metasploit_data_models/search/operation/ipaddress/match.rb +109 -0
  50. metadata +58 -9
  51. data/spec/dummy/db/schema.rb +0 -609
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::Search::Operation::IPAddress do
4
+ subject(:operation) {
5
+ described_class.new(
6
+ operator: operator,
7
+ value: formatted_value
8
+ )
9
+ }
10
+
11
+ let(:operator) {
12
+ MetasploitDataModels::Search::Operator::IPAddress.new
13
+ }
14
+
15
+ context 'validation' do
16
+ #
17
+ # lets
18
+ #
19
+
20
+ let(:blank_error) {
21
+ I18n.translate!('errors.messages.blank')
22
+ }
23
+
24
+ let(:invalid_error) {
25
+ I18n.translate!('errors.messages.invalid')
26
+ }
27
+
28
+ #
29
+ # Callbacks
30
+ #
31
+
32
+ before(:each) do
33
+ operation.valid?
34
+ end
35
+
36
+ context 'errors on #value' do
37
+ subject(:value_error) do
38
+ operation.errors[:value]
39
+ end
40
+
41
+ context 'with IPv4' do
42
+ context 'with CIDR' do
43
+ context 'with valid prefix_length' do
44
+ let(:formatted_value) {
45
+ '1.2.3.4/8'
46
+ }
47
+
48
+ it { should be_empty }
49
+ end
50
+
51
+ context 'without valid prefix_length' do
52
+ let(:formatted_value) {
53
+ '1.2.3.4/36'
54
+ }
55
+
56
+ it { should include invalid_error }
57
+ end
58
+ end
59
+
60
+ context 'with Nmap', pending: 'MSP-10712' do
61
+ context 'with valid segment range' do
62
+ let(:formatted_value) {
63
+ '1-2.3.4.5'
64
+ }
65
+
66
+ it { should be_empty }
67
+ end
68
+
69
+ context 'without valid segment range' do
70
+ let(:formatted_value) {
71
+ '2-1.3.4.5'
72
+ }
73
+
74
+ it { should include invalid_error }
75
+ end
76
+ end
77
+
78
+ context 'with Range' do
79
+ context 'with ordered range' do
80
+ let(:formatted_value) {
81
+ '2.2.2.2-1.1.1.1'
82
+ }
83
+
84
+ it { should include invalid_error }
85
+ end
86
+
87
+ context 'without ordered range' do
88
+ let(:formatted_value) {
89
+ '1.1.1.1-2.2.2.2'
90
+ }
91
+
92
+ it { should be_empty }
93
+ end
94
+ end
95
+
96
+ context 'with address' do
97
+ let(:formatted_value) {
98
+ '1.2.3.4'
99
+ }
100
+
101
+ it { be_empty }
102
+ end
103
+ end
104
+
105
+ context 'with nil' do
106
+ let(:formatted_value) {
107
+ nil
108
+ }
109
+
110
+ it { should include blank_error }
111
+ it { should_not include invalid_error }
112
+ end
113
+
114
+ context 'with empty string' do
115
+ let(:formatted_value) {
116
+ ''
117
+ }
118
+
119
+ it { should include blank_error }
120
+ it { should_not include invalid_error }
121
+ end
122
+
123
+ context 'without matching formatted value' do
124
+ let(:formatted_value) {
125
+ 'non_matching_value'
126
+ }
127
+
128
+ it { should include invalid_error }
129
+ end
130
+ end
131
+ end
132
+
133
+ context '#value' do
134
+ subject(:value) {
135
+ operation.value
136
+ }
137
+
138
+ context 'with IPv4' do
139
+ context 'with CIDR' do
140
+ let(:formatted_value) {
141
+ '1.2.3.4/8'
142
+ }
143
+
144
+ it { should be_a MetasploitDataModels::IPAddress::V4::CIDR }
145
+ end
146
+
147
+ context 'with Nmap', pending: 'MSP-10712' do
148
+ let(:formatted_value) {
149
+ '1.2.3.4-5'
150
+ }
151
+
152
+ it { should be_a MetasploitDataModels::IPAddress::V4::Nmap }
153
+ end
154
+
155
+ context 'with Range' do
156
+ let(:formatted_value) {
157
+ '1.1.1.1-2.2.2.2'
158
+ }
159
+
160
+ it { should be_a MetasploitDataModels::IPAddress::V4::Range }
161
+ end
162
+
163
+ context 'with address' do
164
+ let(:formatted_value) {
165
+ '1.2.3.4'
166
+ }
167
+
168
+ it { should be_a MetasploitDataModels::IPAddress::V4::Single }
169
+ end
170
+ end
171
+
172
+ context 'without support format' do
173
+ let(:formatted_value) {
174
+ 'unsupported_formated'
175
+ }
176
+
177
+ it 'is the passed formatted value' do
178
+ expect(value).to eq(formatted_value)
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::Search::Operator::IPAddress do
4
+ subject(:operator) {
5
+ described_class.new
6
+ }
7
+
8
+ context '#operate_on' do
9
+ subject(:operate_on) {
10
+ operator.operate_on(formatted_value)
11
+ }
12
+
13
+ let(:formatted_value) {
14
+ nil
15
+ }
16
+
17
+ it { should be_a MetasploitDataModels::Search::Operation::IPAddress }
18
+ end
19
+ end
@@ -158,46 +158,80 @@ describe MetasploitDataModels::Search::Visitor::Relation do
158
158
  context 'matching record' do
159
159
  context 'Metasploit::Model::Search::Query#klass' do
160
160
  context 'with Mdm::Service' do
161
+ include_context 'Rex::Text'
162
+
163
+ #
164
+ # lets
165
+ #
166
+
161
167
  let(:klass) {
162
168
  Mdm::Service
163
169
  }
164
170
 
165
- let(:matching_ports) {
166
- [
167
- 1,
168
- 2
169
- ]
171
+ #
172
+ # Don't use factories to prevent prefix aliasing when sequences go from 1 to 10 or 10 to 100
173
+ #
174
+
175
+ let(:non_matching_info) {
176
+ 'mdm_service_info_c'
170
177
  }
171
178
 
172
- let(:matching_records) {
173
- matching_record_by_port.values
179
+ let(:non_matching_name) {
180
+ 'mdm_service_name_c'
174
181
  }
175
182
 
176
183
  let(:non_matching_port) {
177
184
  3
178
185
  }
179
186
 
187
+ let(:non_matching_proto) {
188
+ 'udp'
189
+ }
190
+
180
191
  #
181
192
  # let!s
182
193
  #
183
194
 
184
- let!(:matching_record_by_port) {
185
- matching_ports.each_with_object({}) { |matching_port, matching_record_by_port|
186
- matching_record_by_port[matching_port] = FactoryGirl.create(
187
- :mdm_service,
188
- port: matching_port
189
- )
190
- }
191
- }
192
-
193
195
  let!(:non_matching_record) {
194
196
  FactoryGirl.create(
195
197
  :mdm_service,
196
- port: non_matching_port
198
+ info: non_matching_info,
199
+ name: non_matching_name,
200
+ port: non_matching_port,
201
+ proto: non_matching_proto
197
202
  )
198
203
  }
204
+ p
199
205
 
200
206
  context 'with port' do
207
+ #
208
+ # lets
209
+ #
210
+
211
+ let(:matching_ports) {
212
+ [
213
+ 1,
214
+ 2
215
+ ]
216
+ }
217
+
218
+ let(:matching_records) {
219
+ matching_record_by_port.values
220
+ }
221
+
222
+ #
223
+ # let!s
224
+ #
225
+
226
+ let!(:matching_record_by_port) {
227
+ matching_ports.each_with_object({}) { |matching_port, matching_record_by_port|
228
+ matching_record_by_port[matching_port] = FactoryGirl.create(
229
+ :mdm_service,
230
+ port: matching_port
231
+ )
232
+ }
233
+ }
234
+
201
235
  context 'with single port number' do
202
236
  let(:formatted) {
203
237
  "port:#{matching_port}"
@@ -251,26 +285,77 @@ describe MetasploitDataModels::Search::Visitor::Relation do
251
285
  end
252
286
  end
253
287
 
254
- context 'with all operators' do
255
- let(:formatted) {
256
- %Q{port:#{matching_port}}
288
+ context 'with single matching record' do
289
+ #
290
+ # lets
291
+ #
292
+
293
+ #
294
+ # Don't use factories to prevent prefix aliasing when sequences go from 1 to 10 or 10 to 100
295
+ #
296
+
297
+ let(:matching_info) {
298
+ 'mdm_service_info_a'
299
+ }
300
+
301
+ let(:matching_name) {
302
+ 'mdm_service_name_a'
303
+ }
304
+
305
+ let(:matching_port) {
306
+ 1
307
+ }
308
+
309
+ let(:matching_proto) {
310
+ 'tcp'
311
+ }
312
+
313
+ #
314
+ # let!s
315
+ #
316
+
317
+ let!(:matching_record) {
318
+ FactoryGirl.create(
319
+ :mdm_service,
320
+ info: matching_info,
321
+ name: matching_name,
322
+ port: matching_port,
323
+ proto: matching_proto
324
+ )
257
325
  }
326
+
327
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
328
+ attribute: :info
329
+
330
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
331
+ attribute: :name
332
+
333
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
334
+ attribute: :proto
335
+
336
+ context 'with all operators' do
337
+ let(:formatted) {
338
+ %Q{name:#{matching_name} port:#{matching_port} proto:#{matching_proto}}
339
+ }
340
+
341
+ it 'finds only matching record' do
342
+ expect(visit).to match_array([matching_record])
343
+ end
344
+ end
258
345
  end
259
346
  end
260
347
 
261
348
  context 'with Mdm::Host' do
262
349
  #
263
350
  # lets
264
- #
265
-
266
- let(:klass) {
267
- Mdm::Host
268
- }
269
-
270
351
  #
271
352
  # Don't use factories to prevent prefix aliasing when sequences go from 1 to 10 or 10 to 100
272
353
  #
273
354
 
355
+ let(:matching_record_address) {
356
+ '1.2.3.4'
357
+ }
358
+
274
359
  let(:matching_record_os_flavor) {
275
360
  'mdm_host_os_flavor_a'
276
361
  }
@@ -283,10 +368,6 @@ describe MetasploitDataModels::Search::Visitor::Relation do
283
368
  'mdm_host_os_sp_a'
284
369
  }
285
370
 
286
- let(:matching_service_name) {
287
- 'mdm_service_name_a'
288
- }
289
-
290
371
  let(:matching_record_name) {
291
372
  'mdm_host_name_a'
292
373
  }
@@ -295,6 +376,10 @@ describe MetasploitDataModels::Search::Visitor::Relation do
295
376
  'mdm_service_name_a'
296
377
  }
297
378
 
379
+ let(:non_matching_record_address) {
380
+ '5.6.7.8'
381
+ }
382
+
298
383
  let(:non_matching_record_os_flavor) {
299
384
  'mdm_host_os_flavor_b'
300
385
  }
@@ -307,10 +392,6 @@ describe MetasploitDataModels::Search::Visitor::Relation do
307
392
  'mdm_host_os_sp_b'
308
393
  }
309
394
 
310
- let(:non_matching_service_name) {
311
- 'mdm_service_name_b'
312
- }
313
-
314
395
  let(:non_matching_record_name) {
315
396
  'mdm_host_name_b'
316
397
  }
@@ -326,6 +407,7 @@ describe MetasploitDataModels::Search::Visitor::Relation do
326
407
  let!(:matching_record) do
327
408
  FactoryGirl.build(
328
409
  :mdm_host,
410
+ address: matching_record_address,
329
411
  name: matching_record_name,
330
412
  os_flavor: matching_record_os_flavor,
331
413
  os_name: matching_record_os_name,
@@ -344,6 +426,7 @@ describe MetasploitDataModels::Search::Visitor::Relation do
344
426
  let!(:non_matching_record) do
345
427
  FactoryGirl.build(
346
428
  :mdm_host,
429
+ address: non_matching_record_address,
347
430
  name: non_matching_record_name,
348
431
  os_flavor: non_matching_record_os_flavor,
349
432
  os_name: non_matching_record_os_name,
@@ -359,6 +442,42 @@ describe MetasploitDataModels::Search::Visitor::Relation do
359
442
  )
360
443
  end
361
444
 
445
+ context 'with address operator' do
446
+ let(:formatted) do
447
+ "address:#{formatted_address}"
448
+ end
449
+
450
+ context 'with CIDR' do
451
+ let(:formatted_address) {
452
+ '1.3.4.5/8'
453
+ }
454
+
455
+ it 'should find only matching record' do
456
+ expect(visit).to match_array([matching_record])
457
+ end
458
+ end
459
+
460
+ context 'with Range' do
461
+ let(:formatted_address) {
462
+ '1.1.1.1-5.6.7.7'
463
+ }
464
+
465
+ it 'should find only matching record' do
466
+ expect(visit).to match_array([matching_record])
467
+ end
468
+ end
469
+
470
+ context 'with single' do
471
+ let(:formatted_address) {
472
+ '1.2.3.4'
473
+ }
474
+
475
+ it 'should find only matching record' do
476
+ expect(visit).to match_array([matching_record])
477
+ end
478
+ end
479
+ end
480
+
362
481
  it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
363
482
  :attribute => :name
364
483
 
@@ -425,7 +544,17 @@ describe MetasploitDataModels::Search::Visitor::Relation do
425
544
 
426
545
  context 'with all operators' do
427
546
  let(:formatted) {
428
- %Q{name:"#{matching_record_name}" os:"#{matching_record_os_name} #{matching_record_os_flavor} #{matching_record_os_sp}" os_flavor:"#{matching_record_os_flavor}" os_name:"#{matching_record_os_name}" os_sp:"#{matching_record_os_sp}" services.name:"#{matching_service_name}"}
547
+ %Q{
548
+ address:1.3.4.5/8
549
+ address:1.1.1.1-5.6.7.7
550
+ address:1.2.3.4
551
+ name:"#{matching_record_name}"
552
+ os:"#{matching_record_os_name} #{matching_record_os_flavor} #{matching_record_os_sp}"
553
+ os_flavor:"#{matching_record_os_flavor}"
554
+ os_name:"#{matching_record_os_name}"
555
+ os_sp:"#{matching_record_os_sp}"
556
+ services.name:"#{matching_service_name}"
557
+ }
429
558
  }
430
559
 
431
560
  it 'should find only matching record' do
@@ -437,6 +566,70 @@ describe MetasploitDataModels::Search::Visitor::Relation do
437
566
  end
438
567
  end
439
568
  end
569
+
570
+
571
+ end
572
+
573
+ context 'with Mdm::Tag' do
574
+ #
575
+ # lets
576
+ #
577
+
578
+ let(:klass) {
579
+ Mdm::Tag
580
+ }
581
+
582
+ let(:matching_desc) {
583
+ 'This is a description'
584
+ }
585
+
586
+ let(:matching_name) {
587
+ 'matching.tag'
588
+ }
589
+
590
+ let(:non_matching_desc) {
591
+ 'This could be a description'
592
+ }
593
+
594
+ let(:non_matching_name) {
595
+ 'tag.does.not.match'
596
+ }
597
+
598
+ #
599
+ # let!s
600
+ #
601
+
602
+ let!(:matching_record) {
603
+ FactoryGirl.create(
604
+ :mdm_tag,
605
+ desc: matching_desc,
606
+ name: matching_name
607
+ )
608
+ }
609
+
610
+ let!(:non_matching_record) {
611
+ FactoryGirl.create(
612
+ :mdm_tag,
613
+ desc: non_matching_desc,
614
+ name: non_matching_name
615
+ )
616
+ }
617
+
618
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
619
+ attribute: :desc
620
+
621
+ it_should_behave_like 'MetasploitDataModels::Search::Visitor::Relation#visit matching record',
622
+ attribute: :name
623
+
624
+ context 'with all operators' do
625
+ let(:formatted) {
626
+ %Q{desc:"#{matching_desc}" name:"#{matching_name}"}
627
+ }
628
+
629
+ it 'should find only matching record' do
630
+ expect(visit).to match_array([matching_record])
631
+ end
632
+ end
440
633
  end
441
634
  end
442
635
  end
@@ -460,4 +653,4 @@ describe MetasploitDataModels::Search::Visitor::Relation do
460
653
  its([:includes]) { should == MetasploitDataModels::Search::Visitor::Includes }
461
654
  its([:where]) { should == MetasploitDataModels::Search::Visitor::Where }
462
655
  end
463
- end
656
+ end