cms_scanner 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
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