cms_scanner 0.0.12 → 0.0.13

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79429533403d4c37ac3c20f553e3b78de200666f
4
- data.tar.gz: a295401b0ecf50612bd9c9c23f626009c03a8b76
3
+ metadata.gz: 86ad29d942ae76af1543da17f8f8e9ffa73f0373
4
+ data.tar.gz: bebf3711223c587954b4b4c2f852af89afc1192e
5
5
  SHA512:
6
- metadata.gz: 6fa364fe4c2c68a3ba41b833a0677f3e509b38000917ef782963d043051d5c90dc395028d284064a6be26ade3b309375cd4911edf80e0666d7f815ccf457038a
7
- data.tar.gz: 9a01ac121b97750afaf2ff77e1e18ee588e037c5b4de279af36d3cd7c17bbb58ed1acc3d45d48b89b0910ff0cd7afaa831b0c36af7b3182160ace3aab486ca79
6
+ metadata.gz: a476cb2079b4633e3a672415952fb420cc55359a5cc4438bc7cd0e8dd4556d7a03ec4769c40a3a1f536ae7b2696e5213470c84136e78db249ae638b3e4a13bd2
7
+ data.tar.gz: db601c31e7d60b95f1b56b7b0a903ac83cef5966b81c4737e74f4d7e1019ad508245ccb82b11cbb4b9ab9bd662789002b3f4f26f2209d58f8145b8da0cd477eb
@@ -2,8 +2,21 @@ module CMSScanner
2
2
  module Controller
3
3
  # InterestingFiles Controller
4
4
  class InterestingFiles < Base
5
+ def cli_options
6
+ [
7
+ OptChoice.new(
8
+ ['--interesting-files-detection MODE',
9
+ 'Use the supplied mode for the interesting files detection. ' \
10
+ 'Modes: mixed, passive, aggressive'
11
+ ],
12
+ choices: %w(mixed passive aggressive),
13
+ normalize: :to_sym)
14
+ ]
15
+ end
16
+
5
17
  def run
6
- findings = target.interesting_files(mode: parsed_options[:detection_mode])
18
+ mode = parsed_options[:interesting_files_detection] || parsed_options[:detection_mode]
19
+ findings = target.interesting_files(mode: mode)
7
20
 
8
21
  output('findings', findings: findings) unless findings.empty?
9
22
  end
@@ -2,6 +2,10 @@ module CMSScanner
2
2
  module Formatter
3
3
  # CLI Formatter
4
4
  class Cli < Base
5
+ def bold(text)
6
+ colorize(text, 1)
7
+ end
8
+
5
9
  def red(text)
6
10
  colorize(text, 31)
7
11
  end
@@ -10,6 +14,14 @@ module CMSScanner
10
14
  colorize(text, 32)
11
15
  end
12
16
 
17
+ def amber(text)
18
+ colorize(text, 33)
19
+ end
20
+
21
+ def blue(text)
22
+ colorize(text, 34)
23
+ end
24
+
13
25
  def colorize(text, color_code)
14
26
  "\e[#{color_code}m#{text}\e[0m"
15
27
  end
@@ -24,9 +24,10 @@ module CMSScanner
24
24
  def known_headers
25
25
  %w(
26
26
  age accept-ranges cache-control content-type content-length connection date etag expires
27
- location last-modified link pragma set-cookie strict-transport-security transfer-encoding
28
- vary x-cache x-content-security-policy x-content-type-options x-frame-options x-language
29
- x-permitted-cross-domain-policies x-pingback x-varnish x-webkit-csp x-xss-protection
27
+ keep-alive location last-modified link pragma set-cookie strict-transport-security
28
+ transfer-encoding vary x-cache x-content-security-policy x-content-type-options
29
+ x-frame-options x-language x-permitted-cross-domain-policies x-pingback x-varnish
30
+ x-webkit-csp x-xss-protection
30
31
  )
31
32
  end
32
33
 
@@ -6,7 +6,7 @@ module CMSScanner
6
6
  attr_reader :number
7
7
 
8
8
  def initialize(number, opts = {})
9
- @number = number
9
+ @number = number.to_s
10
10
  parse_finding_options(opts)
11
11
  end
12
12
 
@@ -0,0 +1 @@
1
+ <% # Empty file, the banner should be implemented in each scanner %>
@@ -1,3 +1,4 @@
1
+ <%= render('banner') -%>
1
2
  <%= green('[+]') %> URL: <%= @url %>
2
3
  <%= green('[+]') %> Started: <%= @start_time.asctime %>
3
4
 
@@ -1,7 +1,7 @@
1
1
  Interesting Findings: <%= @findings.size %>
2
2
  <% @findings.each do |finding| -%>
3
3
 
4
- [+] <%= finding.url %>
4
+ <%= green('[+]') %> <%= finding.url %>
5
5
  <% if finding.confidence > 0 -%>
6
6
  | Confidence: <%= finding.confidence %>%
7
7
  <% end -%>
data/cms_scanner.gemspec CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  s.add_development_dependency 'rspec', '~> 3.2'
33
33
  s.add_development_dependency 'rspec-its', '~> 1.1'
34
34
  s.add_development_dependency 'bundler', '~> 1.6'
35
- s.add_development_dependency 'rubocop', '~> 0.28'
35
+ s.add_development_dependency 'rubocop', '~> 0.29'
36
36
  s.add_development_dependency 'webmock', '~> 1.20'
37
37
  s.add_development_dependency 'simplecov', '~> 0.9'
38
38
  end
data/lib/cms_scanner.rb CHANGED
@@ -9,12 +9,11 @@ require 'public_suffix'
9
9
  require 'erb'
10
10
  require 'fileutils'
11
11
  require 'pathname'
12
- # Helpers
13
- require 'helper'
14
12
  # Monkey Patches
15
13
  require 'cms_scanner/typhoeus/response'
16
14
  require 'cms_scanner/public_suffix/domain'
17
15
  # Custom Libs
16
+ require 'cms_scanner/helper'
18
17
  require 'cms_scanner/errors/auth_errors'
19
18
  require 'cms_scanner/cache/typhoeus'
20
19
  require 'cms_scanner/target'
@@ -24,6 +23,7 @@ require 'cms_scanner/controller'
24
23
  require 'cms_scanner/controllers'
25
24
  require 'cms_scanner/formatter'
26
25
  require 'cms_scanner/finders'
26
+ require 'cms_scanner/vulnerability'
27
27
 
28
28
  # Module
29
29
  module CMSScanner
@@ -3,7 +3,7 @@ module CMSScanner
3
3
  class Controllers < Array
4
4
  attr_reader :option_parser
5
5
 
6
- def initialize(option_parser = OptParseValidator::OptParser.new)
6
+ def initialize(option_parser = OptParseValidator::OptParser.new(nil, 40))
7
7
  @option_parser = option_parser
8
8
  end
9
9
 
@@ -17,7 +17,7 @@ module CMSScanner
17
17
  def run(opts = {})
18
18
  each do |finder|
19
19
  symbols_from_mode(opts[:mode]).each do |symbol|
20
- [*finder.send(symbol, opts)].each do |found|
20
+ [*finder.send(symbol, opts)].compact.each do |found|
21
21
  findings << found
22
22
  end
23
23
  end
@@ -7,32 +7,40 @@ module CMSScanner
7
7
  # returned the best finding
8
8
  class UniqueFinders < IndependentFinders
9
9
  # @param [ Hash ] opts
10
- # @option opts [ Symbol ] mode :mixed, :passive or :aggressive
10
+ # @option opts [ Symbol ] :mode :mixed, :passive or :aggressive
11
11
  # @option opts [ Int ] :confidence_threshold If a finding's confidence reaches this value,
12
12
  # it will be returned as the best finding.
13
13
  # Default is 100.
14
14
  # If <= 0, all finders will be ran.
15
15
  #
16
- # @return [ Object ]
16
+ # @return [ Object ] The best finding
17
17
  def run(opts = {})
18
18
  opts[:confidence_threshold] ||= 100
19
19
 
20
20
  symbols_from_mode(opts[:mode]).each do |symbol|
21
21
  each do |finder|
22
- [*finder.send(symbol, opts)].each do |found|
23
- findings << found
24
- end
22
+ [*finder.send(symbol, opts)].compact.each { |found| findings << found }
25
23
 
26
24
  next if opts[:confidence_threshold] <= 0
27
25
 
28
- findings.each do |f|
29
- return f if f.confidence >= opts[:confidence_threshold]
30
- end
26
+ findings.each { |f| return f if f.confidence >= opts[:confidence_threshold] }
31
27
  end
32
28
  end
33
29
 
30
+ best_finding(findings)
31
+ end
32
+
33
+ # @param [ Array<Object> ] findings
34
+ #
35
+ # @return [ Object ] The best finding
36
+ def best_finding(findings)
34
37
  # results are sorted by confidence ASC
35
- findings.sort_by(&:confidence).last
38
+ findings.sort_by!(&:confidence)
39
+
40
+ # If all findings have the same confidence, nil is returned
41
+ return if findings.size > 1 && findings.first.confidence == findings.last.confidence
42
+
43
+ findings.last
36
44
  end
37
45
  end
38
46
  end
File without changes
@@ -6,21 +6,11 @@ module CMSScanner
6
6
  @scope ||= Scope.new
7
7
  end
8
8
 
9
- # // are handled by Addressable::URI, but worngly :/
10
- # e.g: Addressable::URI.parse('//file').host => file
11
- #
12
- # Idea: parse the // with PublicSuffix to see if a valid
13
- # domain is used
14
- #
15
- # @param [ String ] url
9
+ # @param [ String ] url An absolute URL
16
10
  #
17
11
  # @return [ Boolean ] true if the url given is in scope
18
12
  def in_scope?(url)
19
- url.strip!
20
-
21
- return true if url[0, 1] == '/' && url[1, 1] != '/'
22
-
23
- scope.include?(Addressable::URI.parse(url).host)
13
+ scope.include?(Addressable::URI.parse(url.strip).host)
24
14
  rescue
25
15
  false
26
16
  end
@@ -35,15 +25,16 @@ module CMSScanner
35
25
 
36
26
  res.html.xpath(xpath).each do |tag|
37
27
  attributes.each do |attribute|
38
- next unless in_scope?(tag[attribute])
28
+ attr_value = tag[attribute]
29
+
30
+ next unless attr_value && !attr_value.empty?
39
31
 
40
- attr_value = tag[attribute].strip
32
+ url = uri.join(attr_value.strip).to_s
41
33
 
42
- # Relative URL case (The // case is currently ignored by in_scope?)
43
- attr_value = uri.join(attr_value).to_s unless attr_value =~ /\Ahttps?/i
34
+ next unless in_scope?(url)
44
35
 
45
- yield attr_value if block_given? && !found.include?(attr_value)
46
- found << attr_value
36
+ yield url if block_given? && !found.include?(url)
37
+ found << url
47
38
  end
48
39
  end
49
40
 
@@ -1,4 +1,4 @@
1
1
  # Version
2
2
  module CMSScanner
3
- VERSION = '0.0.12'
3
+ VERSION = '0.0.13'
4
4
  end
@@ -0,0 +1,35 @@
1
+ require 'cms_scanner/vulnerability/references'
2
+
3
+ module CMSScanner
4
+ # Generic Vulnerability
5
+ class Vulnerability
6
+ attr_reader :title, :references, :type, :fixed_in
7
+
8
+ # @param [ String ] title
9
+ # @param [ Hash ] references
10
+ # @option references [ Array<String>, String ] cve
11
+ # @option references [ Array<String>, String ] secunia
12
+ # @option references [ Array<String>, String ] osvdb
13
+ # @option references [ Array<String>, String ] exploitdb
14
+ # @option references [ Array<String> ] url URL(s) to related advisories etc
15
+ # @option references [ Array<String>, String ] metasploit The related metasploit module(s)
16
+ # @param [ String ] type
17
+ # @param [ String ] fixed_in
18
+ def initialize(title, references = {}, type = nil, fixed_in = nil)
19
+ @title = title
20
+ @references = references
21
+ @type = type
22
+ @fixed_in = fixed_in
23
+ end
24
+
25
+ # param [ Vulnerability ] other
26
+ #
27
+ # @return [ Boolean ]
28
+ def ==(other)
29
+ title == other.title &&
30
+ type == other.type &&
31
+ references == other.references &&
32
+ fixed_in == other.fixed_in
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,104 @@
1
+ module CMSScanner
2
+ # References related to the vulnerability
3
+ class Vulnerability
4
+ # @return [ Array<String> ] All the references URLs
5
+ def references_urls
6
+ cve_urls + secunia_urls + osvdb_urls + exploitdb_urls + msf_urls + packetstorm_urls
7
+ end
8
+
9
+ # @return [ Array<String> ] The CVEs
10
+ def cves
11
+ @cve ||= [*references[:cve]].map(&:to_s)
12
+ end
13
+
14
+ # @return [ Array<String> ]
15
+ def cve_urls
16
+ cves.reduce([]) { |a, e| a << cve_url(e) }
17
+ end
18
+
19
+ # @return [ String ] The URL to the CVE
20
+ def cve_url(cve)
21
+ "http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-#{cve}"
22
+ end
23
+
24
+ # @return [ Array<String> ] The Secunia IDs
25
+ def secunia_ids
26
+ @secunia_ids ||= [*references[:secunia]].map(&:to_s)
27
+ end
28
+
29
+ # @return [ Array<String> ]
30
+ def secunia_urls
31
+ secunia_ids.reduce([]) { |a, e| a << secunia_url(e) }
32
+ end
33
+
34
+ # @return [ String ] The URL to the Secunia advisory
35
+ def secunia_url(id)
36
+ "https://secunia.com/advisories/#{id}"
37
+ end
38
+
39
+ # @return [ Array<String> ] The OSVDB IDs
40
+ def osvdb_ids
41
+ @osvdb_ids ||= [*references[:osvdb]].map(&:to_s)
42
+ end
43
+
44
+ # @return [ Array<String> ]
45
+ def osvdb_urls
46
+ osvdb_ids.reduce([]) { |a, e| a << osvdb_url(e) }
47
+ end
48
+
49
+ # @return [ String ] The URL to the ExploitDB advisory
50
+ def osvdb_url(id)
51
+ "http://osvdb.org/#{id}"
52
+ end
53
+
54
+ # @return [ Array<String> ] The ExploitDB ID
55
+ def exploitdb_ids
56
+ @exploitdb_ids ||= [*references[:exploitdb]].map(&:to_s)
57
+ end
58
+
59
+ # @return [ Array<String> ]
60
+ def exploitdb_urls
61
+ exploitdb_ids.reduce([]) { |a, e| a << exploitdb_url(e) }
62
+ end
63
+
64
+ # @return [ String ]
65
+ def exploitdb_url(id)
66
+ "http://www.exploit-db.com/exploits/#{id}/"
67
+ end
68
+
69
+ # @return [ String<Array> ]
70
+ def urls
71
+ @urls ||= [*references[:url]].map(&:to_s)
72
+ end
73
+
74
+ # @return [ Array<String> ] The metasploit modules
75
+ def msf_modules
76
+ @msf_modules ||= [*references[:metasploit]].map(&:to_s)
77
+ end
78
+
79
+ # @return [ Array<String> ]
80
+ def msf_urls
81
+ msf_modules.reduce([]) { |a, e| a << msf_url(e) }
82
+ end
83
+
84
+ # @return [ String ] The URL to the metasploit module page
85
+ def msf_url(mod)
86
+ "http://www.rapid7.com/db/modules/#{mod.sub(/^\//, '')}"
87
+ end
88
+
89
+ # @return [ Array<String> ] The Packetstormsecurity ID
90
+ def packetstorm_ids
91
+ @packetstorm_ids ||= [*references[:packetstorm]].map(&:to_s)
92
+ end
93
+
94
+ # @return [ Array<String> ]
95
+ def packetstorm_urls
96
+ packetstorm_ids.reduce([]) { |a, e| a << packetstorm_url(e) }
97
+ end
98
+
99
+ # @return [ String ]
100
+ def packetstorm_url(id)
101
+ "http://packetstormsecurity.com/files/#{id}/"
102
+ end
103
+ end
104
+ end
@@ -10,30 +10,52 @@ describe CMSScanner::Controller::InterestingFiles do
10
10
  described_class.parsed_options = parsed_options
11
11
  end
12
12
 
13
- its(:cli_options) { should be_nil }
14
13
  its(:before_scan) { should be_nil }
15
14
  its(:after_scan) { should be_nil }
16
15
 
16
+ describe '#cli_options' do
17
+ its(:cli_options) { should_not be_empty }
18
+ its(:cli_options) { should be_a Array }
19
+
20
+ it 'contains to correct options' do
21
+ expect(controller.cli_options.map(&:to_sym)).to eq [:interesting_files_detection]
22
+ end
23
+ end
24
+
17
25
  describe '#run' do
18
26
  before do
19
27
  expect(controller.target).to receive(:interesting_files)
20
- .with(mode: parsed_options[:detection_mode]).and_return(stubbed)
28
+ .with(
29
+ mode: parsed_options[:interesting_files_detection] || parsed_options[:detection_mode]
30
+ ).and_return(stubbed)
21
31
  end
32
+
22
33
  after { controller.run }
23
34
 
24
35
  [:mixed, :passive, :aggressive].each do |mode|
25
- context "when #{mode} mode" do
36
+ context "when --detection-mode #{mode}" do
26
37
  let(:parsed_options) { super().merge(detection_mode: mode) }
27
38
 
28
39
  context 'when no findings' do
29
40
  let(:stubbed) { [] }
30
41
 
42
+ before { expect(controller.formatter).to_not receive(:output) }
43
+
31
44
  it 'does not call the formatter' do
32
- expect(controller.formatter).to_not receive(:output)
45
+ # Handled by the before statements above
46
+ end
47
+
48
+ context 'when --interesting-files-detection mode supplied' do
49
+ let(:parsed_options) do
50
+ super().merge(interesting_files_detection: :passive)
51
+ end
52
+
53
+ it 'gives the correct detection paramter' do
54
+ # Handled by before/after statements
55
+ end
33
56
  end
34
57
  end
35
58
 
36
- # TODO: Test the output with a dummy finding ?
37
59
  context 'when findings' do
38
60
  let(:stubbed) { ['yolo'] }
39
61
 
@@ -7,7 +7,11 @@ describe CMSScanner::Formatter::Cli do
7
7
  its(:format) { should eq 'cli' }
8
8
  end
9
9
 
10
- describe '#green, #red, #colorize' do
10
+ describe '#bold, #red, #green, #amber, #blue, #colorize' do
11
+ it 'returns the correct bold string' do
12
+ expect(formatter.bold('Text')).to eq "\e[1mText\e[0m"
13
+ end
14
+
11
15
  it 'returns the correct red string' do
12
16
  expect(formatter.red('Text')).to eq "\e[31mText\e[0m"
13
17
  end
@@ -15,5 +19,13 @@ describe CMSScanner::Formatter::Cli do
15
19
  it 'returns the correct green string' do
16
20
  expect(formatter.green('Another Text')).to eq "\e[32mAnother Text\e[0m"
17
21
  end
22
+
23
+ it 'returns the correct amber string' do
24
+ expect(formatter.amber('Text')).to eq "\e[33mText\e[0m"
25
+ end
26
+
27
+ it 'returns the correct blue string' do
28
+ expect(formatter.blue('Text')).to eq "\e[34mText\e[0m"
29
+ end
18
30
  end
19
31
  end
@@ -7,6 +7,16 @@ describe CMSScanner::Version do
7
7
  let(:opts) { {} }
8
8
  let(:number) { '1.0' }
9
9
 
10
+ describe '#number' do
11
+ its(:number) { should eql '1.0' }
12
+
13
+ context 'when float number supplied' do
14
+ let(:number) { 2.0 }
15
+
16
+ its(:number) { should eq '2.0' }
17
+ end
18
+ end
19
+
10
20
  describe '#==' do
11
21
  context 'when same @number' do
12
22
  it 'returns true' do
@@ -6,7 +6,8 @@ module CMSScanner
6
6
  # Dummy Test Finder
7
7
  class DummyFinder < Finder
8
8
  def passive(_opts = {})
9
- DummyFinding.new('test', found_by: found_by)
9
+ # the nil is there to ensure such value is ignored
10
+ [DummyFinding.new('test', found_by: found_by), nil]
10
11
  end
11
12
 
12
13
  def aggressive(_opts = {})
@@ -6,7 +6,8 @@ module CMSScanner
6
6
  # Dummy Test Finder
7
7
  class Dummy < Finder
8
8
  def passive(_opts = {})
9
- DummyFinding.new('v1', found_by: found_by)
9
+ # the nil is there to ensure such value is ignored
10
+ [DummyFinding.new('v1', found_by: found_by), nil]
10
11
  end
11
12
 
12
13
  def aggressive(_opts = {})
@@ -1,6 +1,9 @@
1
1
  <a href="http://e.org/f.txt">Link</a>
2
2
  <a href="http://e.org/f.txt">Link</a> <!-- Duplicates should be ignored -->
3
3
 
4
+ <a href="mailto:mail@g.com">eMail me!</a>
5
+ <a href="jaVaScript:alert(2)">Click me Fool !</a>
6
+
4
7
  <script src=" https://cdn.e.org/f2.js "></script> <!-- head & tail spaces should be removed -->
5
8
 
6
9
  <script src="/script/s.js"></script>
@@ -2,13 +2,57 @@ require 'spec_helper'
2
2
  require 'dummy_unique_finders'
3
3
 
4
4
  describe CMSScanner::Finders::UniqueFinders do
5
- subject(:finders) { described_class.new }
5
+ subject(:finders) { described_class.new }
6
+ let(:unique_finders) { CMSScanner::Finders::Unique }
7
+
8
+ describe '#best_finding' do
9
+ let(:findings) { [] }
10
+
11
+ after { expect(finders.best_finding(findings)).to eql @expected }
12
+
13
+ context 'when no findings' do
14
+ it 'returns nil' do
15
+ @expected = nil
16
+ end
17
+ end
18
+
19
+ context 'when one finding' do
20
+ let(:findings) { [CMSScanner::DummyFinding.new('one', confidence: 40)] }
21
+
22
+ it 'returns it' do
23
+ @expected = findings[0]
24
+ end
25
+ end
26
+
27
+ context 'when multiple findings' do
28
+ let(:findings) do
29
+ (1..5).reduce([]) { |a, e| a << CMSScanner::DummyFinding.new(e, confidence: 20) }
30
+ end
31
+
32
+ context 'when they have the same confidence' do
33
+ it 'returns nil' do
34
+ @expected = nil
35
+ end
36
+ end
37
+
38
+ context 'when there is a best confidence' do
39
+ (0..4).each do |position|
40
+ context "when at [#{position}]" do
41
+ it 'returns it' do
42
+ findings[position].confidence = 100
43
+
44
+ @expected = findings[position]
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
6
51
 
7
52
  describe '#run' do
8
- let(:target) { 'target' }
9
- let(:finding) { CMSScanner::DummyFinding }
10
- let(:unique_finders) { CMSScanner::Finders::Unique }
11
- let(:opts) { {} }
53
+ let(:target) { 'target' }
54
+ let(:finding) { CMSScanner::DummyFinding }
55
+ let(:opts) { {} }
12
56
 
13
57
  before do
14
58
  finders <<
@@ -20,7 +64,7 @@ describe CMSScanner::Finders::UniqueFinders do
20
64
  after do
21
65
  result = finders.run(opts)
22
66
 
23
- expect(result).to be_a finding
67
+ expect(result).to be_a finding if @expected
24
68
  expect(result).to eql @expected
25
69
  end
26
70
 
@@ -31,13 +31,15 @@ describe CMSScanner::Target do
31
31
 
32
32
  describe '#in_scope?' do
33
33
  context 'when default scope (target domain)' do
34
- [nil, '', 'http://out-of-scope.com', '//jquery.com/j.js'].each do |url|
34
+ [nil, '', 'http://out-of-scope.com', '//jquery.com/j.js',
35
+ 'javascript:alert(3)', 'mailto:p@g.com'
36
+ ].each do |url|
35
37
  it "returns false for #{url}" do
36
38
  expect(target.in_scope?(url)).to eql false
37
39
  end
38
40
  end
39
41
 
40
- %w(https://e.org/file.txt http://e.org/ /relative).each do |url|
42
+ %w(https://e.org/file.txt http://e.org/ //e.org).each do |url|
41
43
  it "returns true for #{url}" do
42
44
  expect(target.in_scope?(url)).to eql true
43
45
  end
@@ -53,7 +55,7 @@ describe CMSScanner::Target do
53
55
  end
54
56
  end
55
57
 
56
- %w(https://cdn.e.org/file.txt http://www.e.org/ https://192.168.1.12/home).each do |url|
58
+ %w(http://e.org //cdn.e.org/f.txt http://s.e.org/ https://192.168.1.12/h).each do |url|
57
59
  it "returns true for #{url}" do
58
60
  expect(target.in_scope?(url)).to eql true
59
61
  end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Vulnerability do
4
+ subject(:vuln) { described_class.new(title, references) }
5
+ let(:title) { 'Test Vuln' }
6
+ let(:references) { {} }
7
+
8
+ describe '#new' do
9
+ context 'when no references' do
10
+ [:cves, :secunia_ids, :osvdb_ids, :exploitdb_ids, :urls,
11
+ :msf_modules, :packetstorm_ids
12
+ ].each do |attribute|
13
+ its(attribute) { should eql([]) }
14
+ end
15
+
16
+ [:cve_urls, :secunia_urls, :osvdb_urls, :exploitdb_urls, :msf_urls,
17
+ :packetstorm_urls
18
+ ].each do |attribute|
19
+ its(attribute) { should eql([]) }
20
+ end
21
+
22
+ its(:references_urls) { should eql([]) }
23
+ end
24
+
25
+ context 'when references provided as string' do
26
+ let(:references) do
27
+ {
28
+ cve: 11,
29
+ secunia: 12,
30
+ osvdb: 13,
31
+ exploitdb: 14,
32
+ url: 'single-url',
33
+ metasploit: '/exploit/yolo',
34
+ packetstorm: 15
35
+ }
36
+ end
37
+
38
+ its(:cves) { should eql %w(11) }
39
+ its(:cve_urls) { should eql %w(http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-11) }
40
+
41
+ its(:secunia_ids) { should eql %w(12) }
42
+ its(:secunia_urls) { should eql %w(https://secunia.com/advisories/12) }
43
+
44
+ its(:osvdb_ids) { should eql %w(13) }
45
+ its(:osvdb_urls) { should eql %w(http://osvdb.org/13) }
46
+
47
+ its(:exploitdb_ids) { should eql %w(14) }
48
+ its(:exploitdb_urls) { should eql %w(http://www.exploit-db.com/exploits/14/) }
49
+
50
+ its(:urls) { should eql %w(single-url) }
51
+
52
+ its(:msf_modules) { should eql %w(/exploit/yolo) }
53
+ its(:msf_urls) { should eql %w(http://www.rapid7.com/db/modules/exploit/yolo) }
54
+
55
+ its(:packetstorm_ids) { should eq %w(15) }
56
+ its(:packetstorm_urls) { should eql %w(http://packetstormsecurity.com/files/15/) }
57
+ end
58
+
59
+ context 'when references provided as array' do
60
+ xit
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Vulnerability do
4
+ subject(:vuln) { described_class.new(title) }
5
+ let(:title) { 'Test Vuln' }
6
+
7
+ describe '#new' do
8
+ its(:title) { should eql title }
9
+ its(:references) { should eql({}) }
10
+ its(:type) { should eql nil }
11
+ its(:fixed_in) { should eql nil }
12
+ end
13
+
14
+ describe '#==' do
15
+ context 'when te same vuln' do
16
+ it 'returns true' do
17
+ expect(vuln).to eq vuln.dup
18
+ end
19
+ end
20
+
21
+ context 'when not equal' do
22
+ it 'returns false' do
23
+ expect(vuln).to_not eq described_class.new('not eq')
24
+ end
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cms_scanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - WPScanTeam - Erwan Le Rousseau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-06 00:00:00.000000000 Z
11
+ date: 2015-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opt_parse_validator
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '0.28'
159
+ version: '0.29'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '0.28'
166
+ version: '0.29'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: webmock
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -230,6 +230,7 @@ files:
230
230
  - app/models/robots_txt.rb
231
231
  - app/models/version.rb
232
232
  - app/models/xml_rpc.rb
233
+ - app/views/cli/core/banner.erb
233
234
  - app/views/cli/core/finished.erb
234
235
  - app/views/cli/core/started.erb
235
236
  - app/views/cli/interesting_files/_array.erb
@@ -262,6 +263,7 @@ files:
262
263
  - lib/cms_scanner/finders/unique_finders.rb
263
264
  - lib/cms_scanner/formatter.rb
264
265
  - lib/cms_scanner/formatter/buffer.rb
266
+ - lib/cms_scanner/helper.rb
265
267
  - lib/cms_scanner/public_suffix/domain.rb
266
268
  - lib/cms_scanner/target.rb
267
269
  - lib/cms_scanner/target/hashes.rb
@@ -274,8 +276,9 @@ files:
274
276
  - lib/cms_scanner/target/server/iis.rb
275
277
  - lib/cms_scanner/typhoeus/response.rb
276
278
  - lib/cms_scanner/version.rb
279
+ - lib/cms_scanner/vulnerability.rb
280
+ - lib/cms_scanner/vulnerability/references.rb
277
281
  - lib/cms_scanner/web_site.rb
278
- - lib/helper.rb
279
282
  - spec/app/controllers/core_spec.rb
280
283
  - spec/app/controllers/interesting_files_spec.rb
281
284
  - spec/app/finders/interesting_files/fantastico_fileslist_spec.rb
@@ -344,6 +347,8 @@ files:
344
347
  - spec/lib/target/scope_spec.rb
345
348
  - spec/lib/target/servers_spec.rb
346
349
  - spec/lib/target_spec.rb
350
+ - spec/lib/vulnerability/references_spec.rb
351
+ - spec/lib/vulnerability_spec.rb
347
352
  - spec/lib/web_site_spec.rb
348
353
  - spec/output/core/finished.cli_no_colour
349
354
  - spec/output/core/finished.json
@@ -459,6 +464,8 @@ test_files:
459
464
  - spec/lib/target/scope_spec.rb
460
465
  - spec/lib/target/servers_spec.rb
461
466
  - spec/lib/target_spec.rb
467
+ - spec/lib/vulnerability/references_spec.rb
468
+ - spec/lib/vulnerability_spec.rb
462
469
  - spec/lib/web_site_spec.rb
463
470
  - spec/output/core/finished.cli_no_colour
464
471
  - spec/output/core/finished.json