metasploit_data_models 0.15.2 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/Gemfile +2 -0
  2. data/app/models/mdm/client.rb +0 -1
  3. data/app/models/mdm/cred.rb +1 -1
  4. data/app/models/mdm/exploited_host.rb +0 -1
  5. data/app/models/mdm/listener.rb +2 -1
  6. data/app/models/mdm/nexpose_console.rb +2 -2
  7. data/app/models/mdm/session.rb +5 -1
  8. data/app/models/mdm/workspace.rb +0 -1
  9. data/db/migrate/20130525015035_remove_campaign_id_from_clients.rb +9 -0
  10. data/db/migrate/20130525212420_drop_table_imported_creds.rb +14 -0
  11. data/db/migrate/20130531144949_making_host_tags_a_real_ar_model.rb +6 -0
  12. data/lib/mdm/host/operating_system_normalization.rb +4 -4
  13. data/lib/metasploit_data_models/version.rb +1 -1
  14. data/spec/app/models/mdm/client_spec.rb +43 -0
  15. data/spec/app/models/mdm/cred_spec.rb +211 -0
  16. data/spec/app/models/mdm/events_spec.rb +85 -0
  17. data/spec/app/models/mdm/exploit_attempt_spec.rb +60 -0
  18. data/spec/app/models/mdm/exploited_host_spec.rb +44 -0
  19. data/spec/app/models/mdm/host_detail_spec.rb +49 -0
  20. data/spec/app/models/mdm/host_spec.rb +468 -0
  21. data/spec/app/models/mdm/host_tag_spec.rb +26 -0
  22. data/spec/app/models/mdm/listener_spec.rb +108 -0
  23. data/spec/app/models/mdm/loot_spec.rb +77 -0
  24. data/spec/app/models/mdm/nexpose_console_spec.rb +128 -0
  25. data/spec/app/models/mdm/note_spec.rb +84 -0
  26. data/spec/app/models/mdm/ref_spec.rb +13 -0
  27. data/spec/app/models/mdm/report_spec.rb +104 -0
  28. data/spec/app/models/mdm/report_template_spec.rb +52 -0
  29. data/spec/app/models/mdm/route_spec.rb +36 -0
  30. data/spec/app/models/mdm/service_spec.rb +70 -15
  31. data/spec/app/models/mdm/session_event_spec.rb +42 -0
  32. data/spec/app/models/mdm/session_spec.rb +114 -0
  33. data/spec/app/models/mdm/tag_spec.rb +104 -0
  34. data/spec/app/models/mdm/task_creds_spec.rb +32 -0
  35. data/spec/app/models/mdm/task_host_spec.rb +33 -0
  36. data/spec/app/models/mdm/task_service_spec.rb +33 -0
  37. data/spec/app/models/mdm/task_spec.rb +59 -5
  38. data/spec/app/models/mdm/user_spec.rb +51 -0
  39. data/spec/app/models/mdm/vuln_attempt_spec.rb +54 -0
  40. data/spec/app/models/mdm/vuln_details_spec.rb +66 -0
  41. data/spec/app/models/mdm/vuln_ref_spec.rb +24 -0
  42. data/spec/app/models/mdm/vuln_spec.rb +25 -0
  43. data/spec/app/models/mdm/web_form_spec.rb +47 -0
  44. data/spec/app/models/mdm/web_page_spec.rb +55 -0
  45. data/spec/app/models/mdm/web_site_spec.rb +86 -0
  46. data/spec/app/models/mdm/web_vuln_spec.rb +12 -0
  47. data/spec/app/models/mdm/workspace_spec.rb +567 -0
  48. data/spec/dummy/db/schema.rb +5 -13
  49. data/spec/factories/mdm/addresses.rb +5 -0
  50. data/spec/factories/mdm/clients.rb +8 -0
  51. data/spec/factories/mdm/events.rb +15 -0
  52. data/spec/factories/mdm/exploit_attempts.rb +8 -0
  53. data/spec/factories/mdm/exploited_hosts.rb +7 -0
  54. data/spec/factories/mdm/fingerprints/nessus_fingerprints.rb +6 -0
  55. data/spec/factories/mdm/fingerprints/nexpose_fingerprints.rb +6 -0
  56. data/spec/factories/mdm/fingerprints/nmap_fingerprints.rb +6 -0
  57. data/spec/factories/mdm/fingerprints/retina_fingerprints.rb +6 -0
  58. data/spec/factories/mdm/fingerprints/session_fingerprints.rb +6 -0
  59. data/spec/factories/mdm/host_details.rb +8 -0
  60. data/spec/factories/mdm/listeners.rb +12 -0
  61. data/spec/factories/mdm/loots.rb +11 -0
  62. data/spec/factories/mdm/nexpose_consoles.rb +15 -0
  63. data/spec/factories/mdm/notes.rb +12 -0
  64. data/spec/factories/mdm/report_templates.rb +8 -0
  65. data/spec/factories/mdm/reports.rb +13 -0
  66. data/spec/factories/mdm/routes.rb +36 -0
  67. data/spec/factories/mdm/session_events.rb +8 -0
  68. data/spec/factories/mdm/sessions.rb +13 -0
  69. data/spec/factories/mdm/vuln_attempts.rb +8 -0
  70. data/spec/factories/mdm/vuln_details.rb +8 -0
  71. data/spec/factories/mdm/web_forms.rb +33 -0
  72. data/spec/factories/mdm/web_pages.rb +64 -0
  73. metadata +95 -5
  74. data/app/models/mdm/imported_cred.rb +0 -10
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::ExploitAttempt do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:host).class_name('Mdm::Host') }
7
+ end
8
+
9
+ context 'database' do
10
+
11
+ context 'timestamps'do
12
+ it { should have_db_column(:attempted_at).of_type(:datetime) }
13
+ end
14
+
15
+ context 'columns' do
16
+ it { should have_db_column(:host_id).of_type(:integer) }
17
+ it { should have_db_column(:service_id).of_type(:integer) }
18
+ it { should have_db_column(:vuln_id).of_type(:integer) }
19
+ it { should have_db_column(:exploited).of_type(:boolean) }
20
+ it { should have_db_column(:fail_reason).of_type(:string) }
21
+ it { should have_db_column(:username).of_type(:string) }
22
+ it { should have_db_column(:module).of_type(:text) }
23
+ it { should have_db_column(:session_id).of_type(:integer) }
24
+ it { should have_db_column(:loot_id).of_type(:integer) }
25
+ it { should have_db_column(:port).of_type(:integer) }
26
+ it { should have_db_column(:proto).of_type(:string) }
27
+ it { should have_db_column(:fail_detail).of_type(:text) }
28
+ end
29
+ end
30
+
31
+ context '#destroy' do
32
+ it 'should successfully destroy the object and all dependent objects' do
33
+ exploit_attempt = FactoryGirl.create(:mdm_exploit_attempt)
34
+ expect {
35
+ exploit_attempt.destroy
36
+ }.to_not raise_error
37
+ expect {
38
+ exploit_attempt.reload
39
+ }.to raise_error(ActiveRecord::RecordNotFound)
40
+
41
+ end
42
+ end
43
+
44
+ context 'validations' do
45
+ it 'should only be valid with a host_id' do
46
+ orphaned_attempt = FactoryGirl.build(:mdm_exploit_attempt, :host => nil)
47
+ orphaned_attempt.should_not be_valid
48
+ orphaned_attempt.errors[:host_id].should include("can't be blank")
49
+ propper_attempt = FactoryGirl.build(:mdm_exploit_attempt)
50
+ propper_attempt.should be_valid
51
+ end
52
+ end
53
+
54
+ context 'factory' do
55
+ it 'should be valid' do
56
+ exploit_attempt = FactoryGirl.build(:mdm_exploit_attempt)
57
+ exploit_attempt.should be_valid
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::ExploitedHost do
4
+ context 'associations' do
5
+ it { should belong_to(:host).class_name('Mdm::Host') }
6
+ it { should belong_to(:service).class_name('Mdm::Service') }
7
+ end
8
+
9
+ context 'database' do
10
+
11
+ context 'timestamps'do
12
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
13
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
14
+ end
15
+
16
+ context 'columns' do
17
+ it { should have_db_column(:host_id).of_type(:integer).with_options(:null => false) }
18
+ it { should have_db_column(:service_id).of_type(:integer) }
19
+ it { should have_db_column(:name).of_type(:string) }
20
+ it { should have_db_column(:session_uuid).of_type(:string) }
21
+ it { should have_db_column(:payload).of_type(:string) }
22
+ end
23
+ end
24
+
25
+ context '#destroy' do
26
+ it 'should successfully destroy the object and all dependent objects' do
27
+ exploited_host = FactoryGirl.create(:mdm_exploited_host)
28
+ expect {
29
+ exploited_host.destroy
30
+ }.to_not raise_error
31
+ expect {
32
+ exploited_host.reload
33
+ }.to raise_error(ActiveRecord::RecordNotFound)
34
+ end
35
+ end
36
+
37
+ context 'factory' do
38
+ it 'should be valid' do
39
+ exploited_host = FactoryGirl.build(:mdm_exploited_host)
40
+ exploited_host.should be_valid
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::HostDetail do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:host).class_name('Mdm::Host') }
7
+ end
8
+
9
+ context 'database' do
10
+ it { should have_db_column(:host_id).of_type(:integer) }
11
+ it { should have_db_column(:nx_console_id).of_type(:integer) }
12
+ it { should have_db_column(:nx_device_id).of_type(:integer) }
13
+ it { should have_db_column(:src).of_type(:string) }
14
+ it { should have_db_column(:nx_site_name).of_type(:string) }
15
+ it { should have_db_column(:nx_site_importance).of_type(:string) }
16
+ it { should have_db_column(:src).of_type(:string) }
17
+ it { should have_db_column(:nx_site_name).of_type(:string) }
18
+ it { should have_db_column(:nx_scan_template).of_type(:string) }
19
+ it { should have_db_column(:nx_risk_score).of_type(:float) }
20
+ end
21
+
22
+ context 'validations' do
23
+ it 'should only be valid with a host_id' do
24
+ orphan_detail = FactoryGirl.build(:mdm_host_detail, :host => nil)
25
+ orphan_detail.should_not be_valid
26
+ orphan_detail.errors[:host_id].should include("can't be blank")
27
+ end
28
+ end
29
+
30
+ context 'factory' do
31
+ it 'should be valid' do
32
+ host_detail = FactoryGirl.build(:mdm_host_detail)
33
+ host_detail.should be_valid
34
+ end
35
+ end
36
+
37
+ context '#destroy' do
38
+ it 'should successfully destroy the object' do
39
+ detail = FactoryGirl.create(:mdm_host_detail)
40
+ expect{
41
+ detail.destroy
42
+ }.to_not raise_error
43
+ expect {
44
+ detail.reload
45
+ }.to raise_error(ActiveRecord::RecordNotFound)
46
+ end
47
+ end
48
+
49
+ end
@@ -37,6 +37,63 @@ describe Mdm::Host do
37
37
  ]
38
38
  end
39
39
 
40
+ context 'factory' do
41
+ it 'should be valid' do
42
+ host = FactoryGirl.build(:mdm_host)
43
+ host.should be_valid
44
+ end
45
+ end
46
+
47
+ context '#destroy' do
48
+ it 'should successfully destroy the object and the dependent objects' do
49
+ host = FactoryGirl.create(:mdm_host)
50
+ exploit_attempt = FactoryGirl.create(:mdm_exploit_attempt, :host => host)
51
+ exploited_host = FactoryGirl.create(:mdm_exploited_host, :host => host)
52
+ host_detail = FactoryGirl.create(:mdm_host_detail, :host => host)
53
+ loot = FactoryGirl.create(:mdm_loot, :host => host)
54
+ task_host = FactoryGirl.create(:mdm_task_host, :host => host)
55
+ note = FactoryGirl.create(:mdm_note, :host => host)
56
+ svc = FactoryGirl.create(:mdm_service, :host => host)
57
+ session = FactoryGirl.create(:mdm_session, :host => host)
58
+ vuln = FactoryGirl.create(:mdm_vuln, :host => host)
59
+
60
+
61
+ expect {
62
+ host.destroy
63
+ }.to_not raise_error
64
+ expect {
65
+ host.reload
66
+ }.to raise_error(ActiveRecord::RecordNotFound)
67
+ expect {
68
+ exploit_attempt.reload
69
+ }.to raise_error(ActiveRecord::RecordNotFound)
70
+ expect {
71
+ exploited_host.reload
72
+ }.to raise_error(ActiveRecord::RecordNotFound)
73
+ expect {
74
+ host_detail.reload
75
+ }.to raise_error(ActiveRecord::RecordNotFound)
76
+ expect {
77
+ loot.reload
78
+ }.to raise_error(ActiveRecord::RecordNotFound)
79
+ expect {
80
+ task_host.reload
81
+ }.to raise_error(ActiveRecord::RecordNotFound)
82
+ expect {
83
+ note.reload
84
+ }.to raise_error(ActiveRecord::RecordNotFound)
85
+ expect {
86
+ svc.reload
87
+ }.to raise_error(ActiveRecord::RecordNotFound)
88
+ expect {
89
+ session.reload
90
+ }.to raise_error(ActiveRecord::RecordNotFound)
91
+ expect {
92
+ vuln.reload
93
+ }.to raise_error(ActiveRecord::RecordNotFound)
94
+ end
95
+ end
96
+
40
97
  context 'associations' do
41
98
  it { should have_many(:creds).class_name('Mdm::Cred').through(:services) }
42
99
  it { should have_many(:exploit_attempts).class_name('Mdm::ExploitAttempt').dependent(:destroy) }
@@ -415,4 +472,415 @@ describe Mdm::Host do
415
472
  end
416
473
  end
417
474
  end
475
+
476
+ context 'os normalization' do
477
+ context '#get_arch_from_string' do
478
+ context "should return 'x64'" do
479
+ it "when the string contains 'x64'" do
480
+ host.send(:get_arch_from_string, 'blahx64blah').should == 'x64'
481
+ end
482
+
483
+ it "when the string contains 'X64'" do
484
+ host.send(:get_arch_from_string, 'blahX64blah').should == 'x64'
485
+ end
486
+
487
+ it "when the string contains 'x86_64'" do
488
+ host.send(:get_arch_from_string, 'blahx86_64blah').should == 'x64'
489
+ end
490
+
491
+ it "when the string contains 'X86_64'" do
492
+ host.send(:get_arch_from_string, 'blahX86_64blah').should == 'x64'
493
+ end
494
+
495
+ it "when the string contains 'amd64'" do
496
+ host.send(:get_arch_from_string, 'blahamd64blah').should == 'x64'
497
+ end
498
+
499
+ it "when the string contains 'AMD64'" do
500
+ host.send(:get_arch_from_string, 'blahAMD64blah').should == 'x64'
501
+ end
502
+
503
+ it "when the string contains 'aMd64'" do
504
+ host.send(:get_arch_from_string, 'blahamd64blah').should == 'x64'
505
+ end
506
+ end
507
+
508
+ context "should return 'x86'" do
509
+ it "when the string contains 'x86'" do
510
+ host.send(:get_arch_from_string, 'blahx86blah').should == 'x86'
511
+ end
512
+
513
+ it "when the string contains 'X86'" do
514
+ host.send(:get_arch_from_string, 'blahX86blah').should == 'x86'
515
+ end
516
+
517
+ it "when the string contains 'i386'" do
518
+ host.send(:get_arch_from_string, 'blahi386blah').should == 'x86'
519
+ end
520
+
521
+ it "when the string contains 'I386'" do
522
+ host.send(:get_arch_from_string, 'blahI386blah').should == 'x86'
523
+ end
524
+
525
+ it "when the string contains 'i486'" do
526
+ host.send(:get_arch_from_string, 'blahi486blah').should == 'x86'
527
+ end
528
+
529
+ it "when the string contains 'i586'" do
530
+ host.send(:get_arch_from_string, 'blahi586blah').should == 'x86'
531
+ end
532
+
533
+ it "when the string contains 'i686'" do
534
+ host.send(:get_arch_from_string, 'blahi386blah').should == 'x86'
535
+ end
536
+ end
537
+
538
+ context "should return 'ppc'" do
539
+ it "when the string contains 'PowerPC'" do
540
+ host.send(:get_arch_from_string, 'blahPowerPCblah').should == 'ppc'
541
+ end
542
+
543
+ it "when the string contains 'PPC'" do
544
+ host.send(:get_arch_from_string, 'blahPPCblah').should == 'ppc'
545
+ end
546
+
547
+ it "when the string contains 'POWER'" do
548
+ host.send(:get_arch_from_string, 'blahPOWERblah').should == 'ppc'
549
+ end
550
+
551
+ it "when the string contains 'ppc'" do
552
+ host.send(:get_arch_from_string, 'blahppcblah').should == 'ppc'
553
+ end
554
+ end
555
+
556
+ context 'should return nil' do
557
+ it 'when PowerPC is cased incorrectly' do
558
+ host.send(:get_arch_from_string, 'powerPC').should == nil
559
+ host.send(:get_arch_from_string, 'Powerpc').should == nil
560
+ end
561
+
562
+ it 'when no recognized arch string is present' do
563
+ host.send(:get_arch_from_string, 'blahblah').should == nil
564
+ end
565
+ end
566
+
567
+ it "should return 'sparc' if the string contains SPARC, regardless of case" do
568
+ host.send(:get_arch_from_string, 'blahSPARCblah').should == 'sparc'
569
+ host.send(:get_arch_from_string, 'blahSPaRCblah').should == 'sparc'
570
+ host.send(:get_arch_from_string, 'blahsparcblah').should == 'sparc'
571
+ end
572
+
573
+ it "should return 'arm' if the string contains 'ARM', regardless of case" do
574
+ host.send(:get_arch_from_string, 'blahARMblah').should == 'arm'
575
+ host.send(:get_arch_from_string, 'blahArMblah').should == 'arm'
576
+ host.send(:get_arch_from_string, 'blaharmblah').should == 'arm'
577
+ end
578
+
579
+ it "should return 'mips' if the string contains 'MIPS', regardless of case" do
580
+ host.send(:get_arch_from_string, 'blahMIPSblah').should == 'mips'
581
+ host.send(:get_arch_from_string, 'blahMiPslah').should == 'mips'
582
+ host.send(:get_arch_from_string, 'blahmipsblah').should == 'mips'
583
+ end
584
+ end
585
+
586
+ context '#parse_windows_os_str' do
587
+ it 'should always return the os_name as Microsoft Windows' do
588
+ result = host.send(:parse_windows_os_str, '')
589
+ result[:os_name].should == 'Microsoft Windows'
590
+ end
591
+
592
+ context 'arch' do
593
+ it 'should return a value for arch if there is one' do
594
+ result = host.send(:parse_windows_os_str, 'Windows x64')
595
+ result[:arch].should == 'x64'
596
+ end
597
+
598
+ it "should not have an arch key if we don't know the arch" do
599
+ result = host.send(:parse_windows_os_str, 'Windows')
600
+ result.has_key?(:arch).should == false
601
+ end
602
+ end
603
+
604
+ context 'Service Pack' do
605
+ it 'should be returned if we see Service Pack X' do
606
+ result = host.send(:parse_windows_os_str, 'Windows XP Service Pack 1')
607
+ result[:os_sp].should == 'SP1'
608
+ end
609
+
610
+ it 'should be returned if we see SPX' do
611
+ result = host.send(:parse_windows_os_str, 'Windows XP SP3')
612
+ result[:os_sp].should == 'SP3'
613
+ end
614
+ end
615
+
616
+ context 'os flavor' do
617
+ it "should appear as 2003 for '.NET Server'" do
618
+ result = host.send(:parse_windows_os_str, 'Windows .NET Server')
619
+ result[:os_flavor].should == '2003'
620
+ end
621
+
622
+ it 'should be recognized for XP' do
623
+ result = host.send(:parse_windows_os_str, 'Windows XP')
624
+ result[:os_flavor].should == 'XP'
625
+ end
626
+
627
+ it 'should be recognized for 2000' do
628
+ result = host.send(:parse_windows_os_str, 'Windows 2000')
629
+ result[:os_flavor].should == '2000'
630
+ end
631
+
632
+ it 'should be recognized for 2003' do
633
+ result = host.send(:parse_windows_os_str, 'Windows 2003')
634
+ result[:os_flavor].should == '2003'
635
+ end
636
+
637
+ it 'should be recognized for 2008' do
638
+ result = host.send(:parse_windows_os_str, 'Windows 2008')
639
+ result[:os_flavor].should == '2008'
640
+ end
641
+
642
+ it 'should be recognized for Vista' do
643
+ result = host.send(:parse_windows_os_str, 'Windows Vista')
644
+ result[:os_flavor].should == 'Vista'
645
+ end
646
+
647
+ it 'should be recognized for SBS' do
648
+ result = host.send(:parse_windows_os_str, 'Windows SBS')
649
+ result[:os_flavor].should == 'SBS'
650
+ end
651
+
652
+ it 'should be recognized for 2000 Advanced Server' do
653
+ result = host.send(:parse_windows_os_str, 'Windows 2000 Advanced Server')
654
+ result[:os_flavor].should == '2000 Advanced Server'
655
+ end
656
+
657
+ it 'should be recognized for 7' do
658
+ result = host.send(:parse_windows_os_str, 'Windows 7')
659
+ result[:os_flavor].should == '7'
660
+ end
661
+
662
+ it 'should be recognized for 7 X Edition' do
663
+ result = host.send(:parse_windows_os_str, 'Windows 7 Ultimate Edition')
664
+ result[:os_flavor].should == '7 Ultimate Edition'
665
+ end
666
+
667
+ it 'should be recognized for 8' do
668
+ result = host.send(:parse_windows_os_str, 'Windows 8')
669
+ result[:os_flavor].should == '8'
670
+ end
671
+
672
+ it 'should be guessed at if all else fails' do
673
+ result = host.send(:parse_windows_os_str, 'Windows Foobar Service Pack 3')
674
+ result[:os_flavor].should == 'Foobar'
675
+ end
676
+ end
677
+
678
+ context 'os type' do
679
+ it 'should be server for Windows NT' do
680
+ result = host.send(:parse_windows_os_str, 'Windows NT 4')
681
+ result[:type].should == 'server'
682
+ end
683
+
684
+ it 'should be server for Windows 2003' do
685
+ result = host.send(:parse_windows_os_str, 'Windows 2003')
686
+ result[:type].should == 'server'
687
+ end
688
+
689
+ it 'should be server for Windows 2008' do
690
+ result = host.send(:parse_windows_os_str, 'Windows 2008')
691
+ result[:type].should == 'server'
692
+ end
693
+
694
+ it 'should be server for Windows SBS' do
695
+ result = host.send(:parse_windows_os_str, 'Windows SBS')
696
+ result[:type].should == 'server'
697
+ end
698
+
699
+ it 'should be server for anything with Server in the string' do
700
+ result = host.send(:parse_windows_os_str, 'Windows Foobar Server')
701
+ result[:type].should == 'server'
702
+ end
703
+
704
+ it 'should be client for anything else' do
705
+ result = host.send(:parse_windows_os_str, 'Windows XP')
706
+ result[:type].should == 'client'
707
+ end
708
+ end
709
+ end
710
+
711
+ context '#validate_fingerprint_data' do
712
+ before(:each) do
713
+ host.stub(:dlog)
714
+ end
715
+
716
+ it 'should return false for an empty hash' do
717
+ fingerprint= FactoryGirl.build(:mdm_note, :data => {})
718
+ host.validate_fingerprint_data(fingerprint).should == false
719
+ end
720
+
721
+ it 'should return false for postgressql fingerprints' do
722
+ fingerprint= FactoryGirl.build(:mdm_note, :ntype => 'postgresql.fingerprint', :data => {})
723
+ host.validate_fingerprint_data(fingerprint).should == false
724
+ end
725
+
726
+ it 'should return false if the fingerprint does not contain a hash' do
727
+ fingerprint= FactoryGirl.build(:mdm_note, :data => 'this is not a fingerprint')
728
+ host.validate_fingerprint_data(fingerprint).should == false
729
+ end
730
+ end
731
+
732
+ context '#normalize_scanner_fp' do
733
+ context 'for session_fingerprint' do
734
+ it 'should return all the correct data for Windows XP SP3 x86' do
735
+ fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host)
736
+ result = host.send(:normalize_scanner_fp, fingerprint)
737
+ result[:os_name].should == 'Microsoft Windows'
738
+ result[:os_flavor].should == 'XP'
739
+ result[:os_sp].should == 'SP3'
740
+ result[:arch].should == 'x86'
741
+ result[:type].should == 'client'
742
+ result[:name].should == nil
743
+ result[:certainty].should == 0.8
744
+ end
745
+
746
+ it 'should return all the correct data for Windows 2008 SP1 x64' do
747
+ fp_data = { :os => 'Microsoft Windows 2008 SP1', :arch => 'x64'}
748
+ fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host, :data => fp_data)
749
+ result = host.send(:normalize_scanner_fp, fingerprint)
750
+ result[:os_name].should == 'Microsoft Windows'
751
+ result[:os_flavor].should == '2008'
752
+ result[:os_sp].should == 'SP1'
753
+ result[:arch].should == 'x64'
754
+ result[:type].should == 'server'
755
+ result[:name].should == nil
756
+ result[:certainty].should == 0.8
757
+ end
758
+
759
+ it 'should fingerprint Metasploitable correctly' do
760
+ # Taken from an actual session_fingerprint of Metasploitable 2
761
+ fp_data = { :os => 'Linux 2.6.24-16-server (i386)', :name => 'metasploitable'}
762
+ fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host, :data => fp_data)
763
+ result = host.send(:normalize_scanner_fp, fingerprint)
764
+ result[:os_name].should == 'Linux'
765
+ result[:name].should == 'metasploitable'
766
+ result[:os_sp].should == '2.6.24-16-server'
767
+ result[:arch].should == 'x86'
768
+ result[:certainty].should == 0.8
769
+ end
770
+
771
+ it 'should just populate os_name if it is unsure' do
772
+ fp_data = { :os => 'Darwin 12.3.0 x86_64 i386'}
773
+ fingerprint = FactoryGirl.build(:mdm_session_fingerprint, :host => host, :data => fp_data)
774
+ result = host.send(:normalize_scanner_fp, fingerprint)
775
+ result[:os_name].should == 'Darwin 12.3.0 x86_64 i386'
776
+ result[:os_sp].should == nil
777
+ result[:arch].should == nil
778
+ result[:certainty].should == 0.8
779
+ end
780
+ end
781
+
782
+ context 'for nmap_fingerprint' do
783
+ it 'should return OS name and flavor for a Windows XP fingerprint' do
784
+ fingerprint = FactoryGirl.build(:mdm_nmap_fingerprint, :host => host)
785
+ result = host.send(:normalize_scanner_fp, fingerprint)
786
+ result[:os_name].should == 'Microsoft Windows'
787
+ result[:os_flavor].should == 'XP'
788
+ result[:certainty].should == 1
789
+ end
790
+
791
+ it 'should return OS name and flavor for a Metasploitable fingerprint' do
792
+ fp_data = {:os_vendor=>"Linux", :os_family=>"Linux", :os_version=>"2.6.X", :os_accuracy=>100}
793
+ fingerprint = FactoryGirl.build(:mdm_nmap_fingerprint, :host => host, :data => fp_data)
794
+ result = host.send(:normalize_scanner_fp, fingerprint)
795
+ result[:os_name].should == 'Linux'
796
+ result[:os_flavor].should == '2.6.X'
797
+ result[:certainty].should == 1
798
+ end
799
+
800
+ it 'should return OS name and flavor fo an OSX fingerprint' do
801
+ fp_data = {:os_vendor=>"Apple", :os_family=>"Mac OS X", :os_version=>"10.8.X", :os_accuracy=>100}
802
+ fingerprint = FactoryGirl.build(:mdm_nmap_fingerprint, :host => host, :data => fp_data)
803
+ result = host.send(:normalize_scanner_fp, fingerprint)
804
+ result[:os_name].should == 'Apple Mac OS X'
805
+ result[:os_flavor].should == '10.8.X'
806
+ result[:certainty].should == 1
807
+ end
808
+ end
809
+
810
+ context 'for nexpose_fingerprint' do
811
+ context 'of a Windows system' do
812
+ it 'should return a generic Windows fingerprint with no product info' do
813
+ fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host)
814
+ result = host.send(:normalize_scanner_fp, fingerprint)
815
+ result[:os_name].should == 'Microsoft Windows'
816
+ result[:arch].should == 'x86'
817
+ result[:certainty].should == 0.67
818
+ end
819
+
820
+ it 'should recognize a Windows 7 fingerprint' do
821
+ fp_data = {:family=>"Windows", :certainty=>"0.67", :vendor=>"Microsoft", :arch=>"x86", :product => 'Windows 7', :version => 'SP1'}
822
+ fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
823
+ result = host.send(:normalize_scanner_fp, fingerprint)
824
+ result[:os_name].should == 'Microsoft Windows'
825
+ result[:os_flavor].should == '7'
826
+ result[:os_sp].should == 'SP1'
827
+ result[:arch].should == 'x86'
828
+ result[:certainty].should == 0.67
829
+ end
830
+ end
831
+
832
+ it 'should recognize an OSX fingerprint' do
833
+ fp_data = {:family=>"Mac OS X", :certainty=>"0.80", :vendor=>"Apple"}
834
+ fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
835
+ result = host.send(:normalize_scanner_fp, fingerprint)
836
+ result[:os_name].should == 'Apple Mac OS X'
837
+ end
838
+
839
+ it 'should recognize a Cisco fingerprint' do
840
+ fp_data = {:family=>"IOS", :certainty=>"1.00", :vendor=>"Cisco", :version=>"11.2(8)SA2"}
841
+ fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
842
+ result = host.send(:normalize_scanner_fp, fingerprint)
843
+ result[:os_name].should == 'Cisco IOS'
844
+ end
845
+
846
+ it 'should recognize an embeeded fingerprint' do
847
+ fp_data = {:family=>"embedded", :certainty=>"1.00", :vendor=>"Footek"}
848
+ fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
849
+ result = host.send(:normalize_scanner_fp, fingerprint)
850
+ result[:os_name].should == 'Footek'
851
+ end
852
+
853
+ it 'should handle an unknown fingerprint' do
854
+ fp_data = {:certainty=>"1.00", :vendor=>"Footek"}
855
+ fingerprint = FactoryGirl.build(:mdm_nexpose_fingerprint, :host => host, :data => fp_data)
856
+ result = host.send(:normalize_scanner_fp, fingerprint)
857
+ result[:os_name].should == 'Footek'
858
+ end
859
+
860
+
861
+ end
862
+
863
+ context 'for retina_fingerprint' do
864
+ it 'should recognize a Windows fingerprint' do
865
+ fingerprint = FactoryGirl.build(:mdm_retina_fingerprint, :host => host)
866
+ result = host.send(:normalize_scanner_fp, fingerprint)
867
+ result[:os_name].should == 'Microsoft Windows'
868
+ result[:os_flavor].should == '2003'
869
+ result[:arch].should == 'x64'
870
+ result[:os_sp].should == 'SP2'
871
+ result[:type].should == 'server'
872
+ result[:certainty].should == 0.8
873
+ end
874
+
875
+ it 'should otherwise jsut copy the fingerprint to os_name' do
876
+ fp_data = { :os => 'Linux 2.6.X (i386)'}
877
+ fingerprint = FactoryGirl.build(:mdm_retina_fingerprint, :host => host, :data => fp_data)
878
+ result = host.send(:normalize_scanner_fp, fingerprint)
879
+ result[:os_name].should == 'Linux 2.6.X (i386)'
880
+ result[:certainty].should == 0.8
881
+ end
882
+ end
883
+ end
884
+
885
+ end
418
886
  end