dawnscanner 2.0.0.rc3 → 2.0.0.rc4

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
  SHA256:
3
- metadata.gz: 72552d751163f1b0a97daa602bf4251d879e66155cb213aaecb0e7b4e9654af1
4
- data.tar.gz: 2f50331bf792286959cd79efb3fc36f106548e11f7c338318b84779b5cb3aa4a
3
+ metadata.gz: b9ae4a53a59b132a6ce6c85407f0d4fddd88eda75958474a1aee0ce2369b4cf4
4
+ data.tar.gz: '01479eaa5129162d83ddcce897f74f250b5fe4b0cbe5e7c5e3bb2444b9cffce8'
5
5
  SHA512:
6
- metadata.gz: 4e1d78d9d5e1b8c407b560a5199d0a3536382e13ce09bda3de2e98a9bffde2e8a0b472acb90a18b16e252355bbfbdde35180072c034500388389613dabd8497a
7
- data.tar.gz: 600b924b3801499ef17e75fbfd5b9e01f9973394f7a76d34828f2702ae76ad4b0364b75403fc0c12820089f9b56a55ec1d2c42a8b7c8c57d5e434f96dac621f1
6
+ metadata.gz: b2ddc397e425922f848612c1244b8e0ace964a766673b9a6f70317e441c00dd35c2687de1040fcfa0ef5203c5f7304d274e4a9091637670a8b5c3ccefec33804
7
+ data.tar.gz: '0345397057005fcd021910298c1befb282eddfcad7e13f876e5d36a8715579d71990dd18bcb9cd3ca3f8387fe99e962ad8e97224d5060dad1f711f49a82e62d2'
data/.gitignore CHANGED
@@ -19,3 +19,4 @@ test/tmp
19
19
  test/version_tmp
20
20
  tmp
21
21
  db/*
22
+ tags
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 3
data/Changelog.md CHANGED
@@ -16,9 +16,12 @@ _latest update: mer 28 nov 2018, 11.03.53, CET_
16
16
  * Removed rake osvdb[name] and rake cve[name] tasks
17
17
  * Adding telemetry
18
18
  * Dawn::Utils include refactory. Now it's available application wide
19
- * debug information refactory.
19
+ * debug information refactory.
20
20
  * engine class, apply_all method now accepts an optional parameter containing a
21
21
  list of security checks to be excluded (issue #230).
22
+ * Fix issue #244. Now the KB path is no more hardcoded but it is relative to
23
+ $HOME and 'dawnscanner' folder where results are stored.
24
+ * Fix issue #245. Pattern matching check is skipped on empty files.
22
25
 
23
26
  ## Version 1.6.9 - codename: Tow Mater (2018-11-28)
24
27
 
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2019 Paolo Perego
1
+ Copyright (c) 2013-2021 Paolo Perego
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  # Dawnscanner - The raising security scanner for ruby web applications
2
2
 
3
- dawnscanner is a source code scanner designed to review your ruby code for
3
+ dawnscanner is a source code scanner designed to review your web applications for
4
4
  security issues.
5
5
 
6
- dawnscanner is able to scan plain ruby scripts (e.g. command line applications) but
7
- all its features are unleashed when dealing with web applications source code.
8
- dawnscanner is able to scan major MVC (Model View Controller) frameworks, out of the
9
- box:
6
+ dawnscanner is able to scan web applications written in Ruby and it supports all
7
+ major MVC (Model View Controller) frameworks, out of the box:
10
8
 
11
9
  * [Ruby on Rails](http://rubyonrails.org)
12
10
  * [Sinatra](http://www.sinatrarb.com)
data/Rakefile CHANGED
@@ -44,7 +44,7 @@ namespace :version do
44
44
  f.puts("module Dawn")
45
45
 
46
46
  puts "#{branch_name}|"
47
- if branch_name != "master"
47
+ if branch_name != "main"
48
48
  av = version.split('.')
49
49
  f.puts " VERSION = \"#{av[0]}.#{av[1]}.#{commit_hash.chop}\""
50
50
  f.puts " CODENAME = \"#{codename.lstrip!.chop}\""
@@ -74,7 +74,8 @@ namespace :kb do
74
74
  desc 'Pack the library for shipping'
75
75
 
76
76
  task :pack do
77
- YAML_KB = File.join(Dir.pwd, 'db')
77
+ YAML_KB = File.join(Dir.home, "dawnscanner", 'db')
78
+ FileUtils.mkdir_p(YAML_KB)
78
79
  __kb_pack
79
80
  end
80
81
 
@@ -199,7 +200,7 @@ def __kb_pack
199
200
 
200
201
 
201
202
  open(File.join(YAML_KB, "kb.yaml"), 'w') do |f|
202
- f.puts(Dawn::KnowledgeBaseExperimental.kb_descriptor)
203
+ f.puts(Dawn::KnowledgeBase.kb_descriptor)
203
204
  end
204
205
  puts "kb.yaml created"
205
206
  system "shasum -a 256 #{YAML_KB}/kb.yaml > #{YAML_KB}/kb.yaml.sig"
data/Roadmap.md CHANGED
@@ -11,12 +11,24 @@ The document is _dynamic_ and feature schedule may vary. If you do need a
11
11
  feature to be included sooner, please open an [issue on
12
12
  github](https://github.com/thesp0nge/dawnscanner/issues/new)
13
13
 
14
- _latest update: Thu Dec 3 18:29:11 CET 2015_
14
+ _latest update: mar 7 mag 2019, 17:48:53, CEST_
15
15
 
16
16
 
17
- ## Version 1.5.5 (est. Jan 2016)
17
+ * Add Hanami support
18
+ * Add node.js support
19
+
20
+ * Add Maven support (this will lead of creating the skeleton of a
21
+ dawnscanner-java gem. I will decide later if it will stay with the core or if
22
+ it will be a separted gem plugging into dawnscanner as plugin).
23
+ * Add support for pure Rack applications
24
+ * Add basic support for Javascript. At the beginning, it will be a signature
25
+ based support. dawnscanner will try to detect the js library version by using
26
+ SHA hashing functions, comparing it with fingerprint of vulnerable libraies.
27
+ Of course, this will lead to false negatives if a user tamper the original
28
+ JS. We must consider also minified versions and we're not able to deal with
29
+ obfuscated code.
30
+
18
31
 
19
- * close all issues on github markedsfor milestone 1.5.5
20
32
  * Issue #131 - Adding a check for OSVDB 119927 : http Gem for Ruby SSL Certificate Validation MitM Spoofing
21
33
  * Issue #119 - Adding a check for OSVDB 114641 : Ruby lib/rexml/entity.rb NULL String Handling Recursive XML External Entity (XXE) Expansion Resource Consumption Remote DoS
22
34
  * Issue #118 - Adding a check for OSVDB 113965 : Sprockets Gem for Ruby Unspecified Request Handling File Enumeration
@@ -39,24 +51,6 @@ _latest update: Thu Dec 3 18:29:11 CET 2015_
39
51
  * adding test for CVE-2011-4969 XSS in jquery < 1.6.2
40
52
 
41
53
 
42
- ## Version 2.0.0 (est. June 2016)
43
-
44
- ### New supported frameworks
45
-
46
- * Add Lotus support
47
- * Add Maven support (this will lead of creating the skeleton of a
48
- dawnscanner-java gem. I will decide later if it will stay with the core or if
49
- it will be a separted gem plugging into dawnscanner as plugin).
50
- * Add support for pure Rack applications
51
- * Add basic support for Javascript. At the beginning, it will be a signature
52
- based support. dawnscanner will try to detect the js library version by using
53
- SHA hashing functions, comparing it with fingerprint of vulnerable libraies.
54
- Of course, this will lead to false negatives if a user tamper the original
55
- JS. We must consider also minified versions and we're not able to deal with
56
- obfuscated code.
57
-
58
- ### New checks
59
-
60
54
  * Add a language check. It will handle a ruby script as input and a
61
55
  ruby\_parser line as unsafe pattern. It will compile the ruby and look for
62
56
  the unsafe pattern
@@ -67,7 +61,6 @@ _latest update: Thu Dec 3 18:29:11 CET 2015_
67
61
  dawnscanner the proper way. This is a dynamic tests that it must be run in a
68
62
  static way, looking for the public directory for old and backup files
69
63
  pattern.
70
- * Security checks for vulnerabilities out until 31 May 2016.
71
64
 
72
65
  ### New features
73
66
 
@@ -115,7 +108,6 @@ _latest update: Thu Dec 3 18:29:11 CET 2015_
115
108
  ## Version 2.5.0 (est. December 2016)
116
109
 
117
110
  * Add automatic mitigation patch generation for Ruby
118
- * Add node.js support
119
111
  * Add Opal support
120
112
 
121
113
  ## Long term Roadmap
data/VERSION CHANGED
@@ -12,4 +12,4 @@
12
12
  # | "Guido" | x.x.0 |
13
13
  # | "Luigi" | x.x.0 |
14
14
  # | "Doc Hudson" | x.x.0 |
15
- 2.0.0.rc3 - Finn McMissile
15
+ 2.0.0.rc4 - Finn McMissile
data/bin/dawn CHANGED
@@ -8,6 +8,7 @@ require 'justify'
8
8
  require 'dawnscanner'
9
9
 
10
10
  APPNAME = File.basename($0)
11
+
11
12
  LIST_KNOWN_FRAMEWORK = %w(rails sinatra padrino)
12
13
  VALID_OUTPUT_FORMAT = %w(console json csv html)
13
14
 
@@ -23,7 +24,7 @@ $logger.formatter = proc do |severity, datetime, progname, msg|
23
24
  date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
24
25
  if severity == "INFO" or severity == "WARN"
25
26
  "[#{date_format}] #{severity} (dawn): #{msg}\n"
26
- else
27
+ else
27
28
  "[#{date_format}] #{severity} (dawn): #{msg}\n"
28
29
  end
29
30
  end
@@ -0,0 +1 @@
1
+ 55641656f0a1979b283c10ac526f00f5fc449d89
Binary file
data/docs/.placeholder ADDED
File without changes
data/docs/CNAME ADDED
@@ -0,0 +1 @@
1
+ www.dawnscanner.org
data/docs/_config.yml ADDED
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-cayman
@@ -3,31 +3,43 @@ require 'dawn/utils'
3
3
 
4
4
  module Dawn
5
5
  module Cli
6
-
7
6
  # This class is responsible for the "dawn kb" command and related
8
7
  # subcommands.
9
8
  class Kb < Thor
10
9
  package_name "dawnscanner"
11
- desc "search", "Searches the knowledge base for a given security test"
12
- def search(string)
10
+ desc "find", "Searches the knowledge base for a given security test"
11
+ def find(string)
13
12
  kb = Dawn::KnowledgeBase.instance
14
13
  kb.find(string)
15
14
  end
16
15
 
16
+ desc "lint", "Checks knowledge base content for correcteness"
17
+ def lint
18
+ kb = Dawn::KnowledgeBase.instance
19
+ kb.load(true)
20
+ end
21
+
22
+ desc "unpack", "Unpacks security checks in KB library path"
23
+ def unpack
24
+ $logger.helo APPNAME, Dawn::VERSION
25
+ kb = Dawn::KnowledgeBase.instance
26
+ kb.unpack
27
+ $logger.bye
28
+ Kernel.exit(0)
29
+ end
30
+
17
31
  desc "status", "Checks the status of the knowledge base"
18
32
  def status
19
33
  $logger.helo APPNAME, Dawn::VERSION
20
- Dawn::KnowledgeBase.path="/home/thesp0nge/src/hacking/dawnscanner/db"
21
34
  Dawn::KnowledgeBase.enabled_checks=[:bulletin, :generic_check]
22
35
  kb = Dawn::KnowledgeBase.instance
23
36
  kb.load
24
37
  if kb.security_checks.empty?
25
38
  $logger.error(kb.error)
26
39
  end
27
-
28
40
  $logger.info("" + kb.security_checks.count.to_s + " security checks loaded")
29
41
  if kb.is_packed?
30
- $logger.error "The knowledge base is packed. It must be unpacked with the 'unpack' command before it can be used"
42
+ $logger.error "The knowledge base is packed. It must be unpacked with the 'unpack' command before it can be used"
31
43
  end
32
44
  $logger.bye
33
45
  Kernel.exit(0)
@@ -50,14 +62,15 @@ module Dawn
50
62
  desc "kb SUBCOMMAND ... ARGS", "Interacts with the knowledge base"
51
63
  subcommand "kb", Dawn::Cli::Kb
52
64
 
53
- desc "scan", "scans a ruby written application for security issues"
54
- option :config_file
55
- method_option :gemfile, :type=>:boolean, :default=>true, :aliases => "-G", :desc => "uses Gemfile.lock to detect MVC"
56
- method_option :skip, :type=>:array, :aliases => "-S", :desc => "specify a list of security checks to be skipped"
57
- option :exit_on_warn, :type=>:boolean
58
- option :count, :type=>:boolean
59
- option :s
60
- option :output
65
+ desc "scan", "scans a ruby written web application for security issues"
66
+ method_option :config_file, :type=>:string, :default=>"", :aliases => "-c", :desc=>"tells dawn to load configuration from filename"
67
+ method_option :gemfile, :type=>:boolean, :default=>true, :aliases => "-G", :desc => "uses Gemfile.lock to detect MVC"
68
+ method_option :skip, :type=>:array, :aliases => "-S", :desc => "specify a list of security checks to be skipped"
69
+ method_option :report_format, :type=>:string, :aliases => "-F", :desc=>"specify the report format (text, html, json). Default is plain text files."
70
+ method_option :exit_on_warn, :type=>:boolean, :default=>false, :aliases => "-z", :desc =>"return number of found vulnerabilities as exit code"
71
+ method_option :count, :type=>:boolean, :default=>false, :aliases => "-C", :desc=>"count vulnerabilities (useful for scripts)"
72
+ method_option :output, :type=>:string, :aliases => "-O", :desc=>"write output to a file with the name specified by the parameter"
73
+ method_option :dependencies, :type=>:boolean, :default=>false, :aliases => "-d", :desc=>"scan only for vulnerabilities affecting dependencies in Gemfile.lock"
61
74
 
62
75
  def scan(target)
63
76
  $logger.helo APPNAME, Dawn::VERSION
@@ -70,21 +83,21 @@ module Dawn
70
83
  checks_to_be_skipped = []
71
84
  checks_to_be_skipped = options[:skip] unless options[:skip].nil?
72
85
 
73
- $logger.error("#{options[:skip]}")
74
-
75
86
  debug_me("scanning #{target}")
76
87
 
77
88
  $config_file= Dawn::Core.find_conf(true) if options[:config_file].nil?
78
89
  $config = Dawn::Core.read_conf($config_file)
79
90
 
91
+ debug_me($config)
92
+
80
93
  $telemetry_url = $config[:telemetry][:endpoint] if $config[:telemetry][:enabled]
81
94
  debug_me("telemetry url is " + $telemetry_url) unless @telemetry_url.nil?
82
-
95
+
83
96
  $telemetry_id = $config[:telemetry][:id] if $config[:telemetry][:enabled]
84
97
  debug_me("telemetry id is " + $telemetry_id) unless @telemetry_id.nil?
85
98
 
86
- $logger.info("telemetry is disabled in config file") unless $config[:telemetry][:enabled]
87
-
99
+ debug_me("telemetry is disabled in config file") unless $config[:telemetry][:enabled]
100
+
88
101
  engine = Dawn::Core.detect_mvc(target) unless options[:gemfile]
89
102
  engine = Dawn::GemfileLock.new(target) if options[:gemfile]
90
103
 
@@ -101,17 +114,20 @@ module Dawn
101
114
  end
102
115
  end
103
116
 
104
-
117
+
105
118
  engine.load_knowledge_base
106
-
119
+
107
120
  ret = engine.apply_all(checks_to_be_skipped)
108
- if options[:output]
109
- STDERR.puts (ret)? engine.vulnerabilities.count : "-1" unless options[:output] == "json"
110
- STDERR.puts (ret)? {:status=>"OK", :vulnerabilities_count=>engine.count_vulnerabilities}.to_json : {:status=>"KO", :vulnerabilities_count=>-1}.to_json if options[:output] == "json"
121
+
122
+
123
+ if options[:report_format] and options[:report_format].eql? "json"
124
+ STDERR.puts (ret)? {:status=>"OK", :vulnerabilities_count=>engine.count_vulnerabilities}.to_json : {:status=>"KO", :vulnerabilities_count=>-1}.to_json
111
125
  $logger.bye
112
126
  Kernel.exit(0)
113
127
  end
114
128
 
129
+ $logger.info("#{engine.count_vulnerabilities} issues found")
130
+
115
131
  Dawn::Reporter.new({:engine=>engine, :apply_all_code=>ret}).report
116
132
  $logger.bye
117
133
 
data/lib/dawn/core.rb CHANGED
@@ -123,7 +123,7 @@ module Dawn
123
123
 
124
124
  # If create_if_none flag is set to true, than I'll create a config file
125
125
  # on the current directory with the default configuration.
126
- conf = {:verbose=>false, :output=>"tabular", :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false, :enabled_checks=> Dawn::Kb::BasicCheck::ALLOWED_FAMILIES}
126
+ conf = {:verbose=>false, :output=>"tabular", :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false, :enabled_checks=> Dawn::Kb::BasicCheck::ALLOWED_FAMILIES, :telemetry=>{:enabled=>false, :endpoint=>"", :id=>""}}
127
127
 
128
128
  # Calculate the conf file path
129
129
  conf_path = File.expand_path('~') +'/.'+conf_name
@@ -138,7 +138,7 @@ module Dawn
138
138
  end
139
139
 
140
140
  def self.read_conf(file=nil)
141
- conf = {:verbose=>false, :output=>"tabular", :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false, :enabled_checks=> Dawn::Kb::BasicCheck::ALLOWED_FAMILIES}
141
+ conf = {:verbose=>false, :output=>"tabular", :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false, :enabled_checks=> Dawn::Kb::BasicCheck::ALLOWED_FAMILIES, :telemetry=>{:enabled=>false, :endpoint=>"", :id=>""}}
142
142
  begin
143
143
  debug_me("returning a default config") if file.nil? or ! File.exist?(file)
144
144
  return conf if file.nil?
data/lib/dawn/engine.rb CHANGED
@@ -39,7 +39,7 @@ module Dawn
39
39
  attr_reader :controllers
40
40
 
41
41
  # Models I don't know right now. Let them initialized as Array... we
42
- # will see later
42
+ # will see later
43
43
  attr_reader :models
44
44
 
45
45
  attr_accessor :debug
@@ -69,10 +69,10 @@ module Dawn
69
69
 
70
70
  set_target(dir) unless dir.nil?
71
71
 
72
-
72
+
73
73
 
74
74
  @ruby_version = get_ruby_version if dir.nil?
75
- @gemfile_lock = options[:gemfile_name] unless options[:gemfile_name].nil?
75
+ @gemfile_lock = options[:gemfile_name] unless options[:gemfile_name].nil?
76
76
 
77
77
  # @stats = gather_statistics
78
78
 
@@ -89,12 +89,12 @@ module Dawn
89
89
  end
90
90
  $logger.warn "pattern matching security checks are disabled for Gemfile.lock scan" if @name == "Gemfile.lock"
91
91
  $logger.warn "combo security checks are disabled for Gemfile.lock scan" if @name == "Gemfile.lock"
92
- debug_me "engine is in debug mode"
92
+ debug_me "engine is in debug mode"
93
93
 
94
94
  if @name == "Gemfile.lock" && ! options[:guessed_mvc].nil?
95
95
  # since all checks relies on @name a Gemfile.lock engine must
96
96
  # impersonificate the engine for the mvc it was detected
97
- debug_me "now I'm switching my name from #{@name} to #{options[:guessed_mvc][:name]}"
97
+ debug_me "now I'm switching my name from #{@name} to #{options[:guessed_mvc][:name]}"
98
98
  $logger.err "there are no connected gems... it seems Gemfile.lock parsing failed" if options[:guessed_mvc][:connected_gems].empty?
99
99
  @name = options[:guessed_mvc][:name]
100
100
  @mvc_version = options[:guessed_mvc][:version]
@@ -111,7 +111,7 @@ module Dawn
111
111
  # load_knowledge_base
112
112
  end
113
113
 
114
-
114
+
115
115
 
116
116
  def detect_views
117
117
  []
@@ -125,10 +125,10 @@ module Dawn
125
125
 
126
126
  def build_view_array(dir)
127
127
 
128
- return [] unless File.exist?(dir) and File.directory?(dir)
128
+ return [] unless File.exist?(dir) and File.directory?(dir)
129
129
 
130
130
  ret = []
131
- Dir.glob(File.join("#{dir}", "*")).each do |filename|
131
+ Dir.glob(File.join("#{dir}", "*")).each do |filename|
132
132
  ret << {:filename=>filename, :language=>:haml} if File.extname(filename) == ".haml"
133
133
  end
134
134
 
@@ -151,9 +151,9 @@ module Dawn
151
151
  # does the target use rvm?
152
152
  ver = get_rvm_ruby_ver if ver[:version].empty? && ver[:patchlevel].empty?
153
153
  # take the running ruby otherwise
154
- ver = {:engine=>RUBY_ENGINE, :version=>RUBY_VERSION, :patchlevel=>"p#{RUBY_PATCHLEVEL}"} if ver[:version].empty? && ver[:patchlevel].empty?
154
+ ver = {:engine=>RUBY_ENGINE, :version=>RUBY_VERSION, :patchlevel=>"p#{RUBY_PATCHLEVEL}"} if ver[:version].empty? && ver[:patchlevel].empty?
155
155
  else
156
- ver = {:engine=>RUBY_ENGINE, :version=>RUBY_VERSION, :patchlevel=>"p#{RUBY_PATCHLEVEL}"}
156
+ ver = {:engine=>RUBY_ENGINE, :version=>RUBY_VERSION, :patchlevel=>"p#{RUBY_PATCHLEVEL}"}
157
157
 
158
158
  end
159
159
 
@@ -174,10 +174,8 @@ module Dawn
174
174
  def load_knowledge_base(enabled_checks=[])
175
175
  debug_me("load_knowledge_base called. Enabled checks are: #{enabled_checks}")
176
176
 
177
- Dawn::KnowledgeBase.path="/home/thesp0nge/src/hacking/dawnscanner/db"
178
177
  Dawn::KnowledgeBase.enabled_checks=[:bulletin, :generic_check]
179
178
  kb = Dawn::KnowledgeBase.instance
180
- $logger.warn "KB path is forced @ /home/thesp0nge/src/hacking/dawnscanner/db"
181
179
 
182
180
  @checks=kb.load
183
181
  debug_me("#{@checks.count} checks loaded")
@@ -192,13 +190,13 @@ module Dawn
192
190
  return ver unless has_gemfile_lock?
193
191
 
194
192
  my_dir = Dir.pwd
195
- Dir.chdir(@target)
193
+ Dir.chdir(@target)
196
194
  lockfile = Bundler::LockfileParser.new(Bundler.read_file("Gemfile.lock"))
197
195
  lockfile.specs.each do |s|
198
196
  # detecting MVC version using @name in case of sinatra, padrino or rails engine
199
- ver= s.version.to_s if s.name == @name && @name != "Gemfile.lock"
197
+ ver= s.version.to_s if s.name == @name && @name != "Gemfile.lock"
200
198
  # detecting MVC version using @force in case of Gemfile.lock engine
201
- ver= s.version.to_s if s.name == @force.to_s && @name == "Gemfile.lock"
199
+ ver= s.version.to_s if s.name == @force.to_s && @name == "Gemfile.lock"
202
200
  @connected_gems << {:name=>s.name, :version=>s.version.to_s}
203
201
  end
204
202
  Dir.chdir(my_dir)
@@ -297,7 +295,7 @@ module Dawn
297
295
  def have_a_telemetry_id?
298
296
  debug_me ($telemetry_id != "" and ! $telemetry_id.nil?)
299
297
  return ($telemetry_id != "" and ! $telemetry_id.nil?)
300
-
298
+
301
299
  end
302
300
 
303
301
  def get_a_telemetry_id
@@ -312,6 +310,11 @@ module Dawn
312
310
  end
313
311
 
314
312
  def telemetry
313
+ unless $config[:telemetry][:enabled]
314
+ debug_me("telemetry is disabled")
315
+ return false
316
+ end
317
+
315
318
  unless have_a_telemetry_id?
316
319
  $telemetry_id = get_a_telemetry_id
317
320
  $config[:telemetry][:id] = $telemetry_id
@@ -321,11 +324,11 @@ module Dawn
321
324
  end
322
325
 
323
326
  debug_me("Telemetry ID is: " + $telemetry_id)
324
-
327
+
325
328
  uri=URI.parse($telemetry_url+"/"+$telemetry_id)
326
329
  header = {'Content-Type': 'text/json'}
327
- tele = { "kb_version" => Dawn::KnowledgeBase::VERSION ,
328
- "ip" => Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address,
330
+ tele = { "kb_version" => Dawn::KnowledgeBase::VERSION ,
331
+ "ip" => Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address,
329
332
  "message"=> Dawn::KnowledgeBase
330
333
  }
331
334
  http = Net::HTTP.new(uri.host, uri.port)
@@ -363,7 +366,7 @@ module Dawn
363
366
  end
364
367
 
365
368
  @checks.each do |check|
366
- if checks_to_be_skipped.include?(check.name)
369
+ if checks_to_be_skipped.include?(check.name)
367
370
  $logger.info("skipping security check #{check.name}")
368
371
  else
369
372
  _do_apply(check)
@@ -439,7 +442,8 @@ module Dawn
439
442
 
440
443
  check.ruby_version = @ruby_version[:version]
441
444
  check.detected_ruby = @ruby_version if check.kind == Dawn::KnowledgeBase::RUBY_VERSION_CHECK
442
- check.dependencies = self.connected_gems if check.kind == Dawn::KnowledgeBase::DEPENDENCY_CHECK
445
+ check.dependencies = self.connected_gems if check.kind == Dawn::KnowledgeBase::DEPENDENCY_CHECK or
446
+ check.kind == Dawn::KnowledgeBase::UNSAFE_DEPENDENCY_CHECK
443
447
  check.root_dir = self.target if check.kind == Dawn::KnowledgeBase::PATTERN_MATCH_CHECK
444
448
  check.options = {:detected_ruby => self.ruby_version,
445
449
  :dependencies => self.connected_gems,
@@ -1,6 +1,6 @@
1
1
  module Dawn
2
2
  module Kb
3
- module OperatingSystemCheck
3
+ class OperatingSystemCheck
4
4
  include BasicCheck
5
5
 
6
6
  # safe_os is an Hash with this form {:family=>"", :vendor=>"", :version=>""}
@@ -25,7 +25,7 @@ module Dawn
25
25
 
26
26
  EXCLUSION_LIST = [
27
27
  "tags",
28
- "vendor/bundle",
28
+ "vendor/bundle",
29
29
  "features",
30
30
  "specs",
31
31
  "test"
@@ -38,10 +38,10 @@ module Dawn
38
38
  @attack_pattern_is_regex = false
39
39
  @glob = "**"
40
40
  @attack_pattern = options[:attack_pattern] unless options[:attack_pattern].nil?
41
- @negative_search = options[:negative_search] unless options[:negative_search].nil?
42
- @avoid_comments = options[:avoid_comments] unless options[:avoid_comments].nil?
43
- @evidences = options[:evidences] unless options[:evidences].nil?
44
- @attack_pattern_is_regex = options[:attack_pattern_is_regex] unless options[:attack_pattern_is_regex].nil?
41
+ @negative_search = options[:negative_search] unless options[:negative_search].nil?
42
+ @avoid_comments = options[:avoid_comments] unless options[:avoid_comments].nil?
43
+ @evidences = options[:evidences] unless options[:evidences].nil?
44
+ @attack_pattern_is_regex = options[:attack_pattern_is_regex] unless options[:attack_pattern_is_regex].nil?
45
45
  @glob = File.join(@glob, options[:glob]) unless options[:glob].nil?
46
46
  debug_me("EVIDENCES ARE #{@evidences.inspect}")
47
47
  end
@@ -60,6 +60,7 @@ module Dawn
60
60
  Dir.glob(File.join("#{root_dir}", @glob)).each do |filename|
61
61
  debug_me("#{File.basename(__FILE__)}@#{__LINE__}: analyzing #{filename}: search is #{@negative_search}")
62
62
  matches = []
63
+ raise ArgumentError.new("skipping empty file") if File.zero?(filename)
63
64
  begin
64
65
  matches = run(load_file(filename)) if File.exists?(filename) && File.file?(filename) && ! File.binary?(filename) && ! must_exclude?(filename)
65
66
  found = ! matches.empty?
@@ -84,17 +85,17 @@ module Dawn
84
85
  return ret_value
85
86
  end
86
87
 
87
- private
88
+ private
88
89
  def string_to_array(par)
89
90
  return par if par.class == Array
90
- %w(par)
91
+ %w(par)
91
92
  end
92
93
 
93
94
  def load_file(filename)
94
95
 
95
96
  f = File.open(filename)
96
97
  lines = f.readlines
97
- f.close
98
+ f.close
98
99
 
99
100
  lines
100
101
  end
@@ -0,0 +1,44 @@
1
+ module Dawn
2
+ module Kb
3
+ # While working on the KB rebase, fetching data from NVD API, I suddenly
4
+ # realize I must change the way a vulnerable dependency must be handled.
5
+ # Instead of changing what is working right now, I'll add a new dependency
6
+ # check ruby class
7
+ # NVD bulletins lists versions that are vulnerable and it would break
8
+ # automatism adding a post data fetching step to realize which is the first
9
+ # safe version.
10
+ #
11
+ # This class will handle a dependency name, the version found in
12
+ # Gemfile.lock and an array of vulnerable versions. If the version found is
13
+ # in the array, than the vuln? method returns true.
14
+ # This is an approach far more easy rathern than the one chosen in the past.
15
+ class UnsafeDependencyCheck
16
+ include BasicCheck
17
+
18
+ attr_accessor :dependencies
19
+ attr_accessor :vulnerable_version_array
20
+
21
+ def initialize(options)
22
+ super(options)
23
+ end
24
+
25
+ def vuln?
26
+ ret = false
27
+
28
+ # 20210325: I know... a single check handles a single dependency so,
29
+ # this should not be an array. This involves too many underlying
30
+ # changes one day I'll make.
31
+ @dependencies.each do |dep|
32
+ unless @vulnerable_version_array.nil? or @vulnerable_version_array.empty?
33
+ if dep[:name] == @vulnerable_version_array[0][:name]
34
+ return false if @vulnerable_version_array[0][:version].nil? or @vulnerable_version_array[0][:version].empty?
35
+ return true if @vulnerable_version_array[0][:version].include? dep[:version]
36
+ end
37
+ end
38
+ end
39
+
40
+ return false
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,7 @@
1
1
  require 'singleton'
2
2
 
3
+ require 'rubygems/package'
4
+
3
5
  # For HTTPS communication to check for KB updates and to fetch them
4
6
  require 'net/http'
5
7
  require 'uri'
@@ -19,12 +21,10 @@ require "dawn/kb/combo_check"
19
21
  require "dawn/kb/version_check"
20
22
  require "dawn/kb/deprecation_check"
21
23
  require "dawn/kb/rubygem_check"
24
+ require "dawn/kb/unsafe_depedency_check"
22
25
 
23
26
  module Dawn
24
- # This is the YAML powered experimental knowledge base
25
- #
26
- # When the old KB format, using Ruby classes will be marked as deprecated,
27
- # than this one will be the official.
27
+ # This is the YAML powered knowledge base
28
28
  #
29
29
  # Dawnscanner KB will be a bunch of YAML file, stored in a hierachy of
30
30
  # directories resembling security checks family. A digital signature will be
@@ -46,7 +46,7 @@ module Dawn
46
46
  #
47
47
  # Example
48
48
  #
49
- # require "dawn/knowledge_base_experimental"
49
+ # require "dawn/knowledge_base"
50
50
  #
51
51
  # ...
52
52
  #
@@ -54,22 +54,22 @@ module Dawn
54
54
  # d.update if d.update?
55
55
  # d.load
56
56
  #
57
- # Last update: gio 29 nov 2018, 17.34.57, CET
57
+ # Last update: Mon Mar 22 05:08:55 PM CET 2021
58
58
  class KnowledgeBase
59
59
  include Singleton
60
60
 
61
- @@path = ""
62
61
  @error = ""
63
62
  @@enabled_checks = [:generic_check, :code_quality, :bulletin, :code_style, :owasp_top_10]
64
63
 
65
64
 
66
- GEM_CHECK = :rubygem_check
67
- DEPENDENCY_CHECK = :dependency_check
68
- PATTERN_MATCH_CHECK = :pattern_match_check
69
- RUBY_VERSION_CHECK = :ruby_version_check
70
- OS_CHECK = :os_check
71
- COMBO_CHECK = :combo_check
72
- CUSTOM_CHECK = :custom_check
65
+ GEM_CHECK = :rubygem_check
66
+ DEPENDENCY_CHECK = :dependency_check
67
+ UNSAFE_DEPENDENCY_CHECK = :unsafe_dependency_check
68
+ PATTERN_MATCH_CHECK = :pattern_match_check
69
+ RUBY_VERSION_CHECK = :ruby_version_check
70
+ OS_CHECK = :os_check
71
+ COMBO_CHECK = :combo_check
72
+ CUSTOM_CHECK = :custom_check
73
73
 
74
74
  REMOTE_KB_URL_PREFIX = "https://dawnscanner.org/data/"
75
75
  FILES = %w(kb.yaml bulletin.tar.gz generic_check.tar.gz owasp_ror_cheatsheet.tar.gz code_style.tar.gz code_quality.tar.gz owasp_top_10.tar.gz signatures.tar.gz)
@@ -87,7 +87,10 @@ module Dawn
87
87
  $logger = Logger.new(STDOUT)
88
88
  $logger.helo "knowledge-base-experimental", Dawn::VERSION
89
89
  end
90
- @path=@@path
90
+ @path = default_path
91
+ @path = options[:path] if options[:path]
92
+ FileUtils.mkdir_p(@path)
93
+
91
94
  @enabled_checks = @@enabled_checks
92
95
 
93
96
  debug_me "KB root path is #{@path}"
@@ -97,9 +100,13 @@ module Dawn
97
100
  @@enabled_checks=checks
98
101
  end
99
102
 
103
+ def default_path
104
+ @path = File.join(Dir.home, 'dawnscanner', 'kb')
105
+ return @path
106
+ end
100
107
 
101
108
  def self.path= path_name
102
- @@path=path_name
109
+ @path=path_name
103
110
  end
104
111
 
105
112
  def is_packed?
@@ -116,8 +123,29 @@ module Dawn
116
123
  end
117
124
 
118
125
  def unpack
119
- $logger.warn "unpack is not yet implemented"
120
-
126
+ # https://weblog.jamisbuck.org/2015/7/23/tar-gz-in-ruby.html
127
+ FILES.each do |f|
128
+ full_name = File.join(path,f)
129
+ if File.file?(full_name) and File.extname(full_name).eql?('.gz')
130
+ File.open(full_name, "rb") do |file|
131
+ Zlib::GzipReader.wrap(file) do |gz|
132
+ Gem::Package::TarReader.new(gz) do |tar|
133
+ tar.each do |entry|
134
+ if entry.file?
135
+ FileUtils.mkdir_p(File.dirname(File.join(path, entry.full_name)))
136
+ File.open(File.join(path, entry.full_name), "wb") do |f|
137
+ f.write(entry.read)
138
+ end
139
+ File.chmod(entry.header.mode, File.join(path,entry.full_name))
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ else
146
+ $logger.warn("can't open " + f)
147
+ end
148
+ end
121
149
  end
122
150
 
123
151
  def self.kb_descriptor
@@ -153,7 +181,10 @@ module Dawn
153
181
  #
154
182
  # Returns an array of security checks, matching the mvc to be reviewed and
155
183
  # the enabled check list or an empty array if an error occured.
156
- def load
184
+ def load(lint=false)
185
+ good =0
186
+ invalid =0
187
+
157
188
  @security_checks = []
158
189
  # $path = File.join(Dir.pwd, "db")
159
190
 
@@ -178,10 +209,20 @@ module Dawn
178
209
  $logger.warn "Missing check directory #{dir}"
179
210
  else
180
211
  Dir.glob(dir+"/**/*.yml").each do |f|
181
- data = YAML.load_file(f)
182
- @security_checks << data
212
+ begin
213
+ data = YAML.load_file(f)
214
+ @security_checks << data
215
+ good+=1
216
+ $logger.info("#{File.basename(f)} loaded") if lint
217
+ rescue Exception => e
218
+ $logger.error(e.message)
219
+ invalid+=1
220
+ end
183
221
  end
222
+ end
184
223
 
224
+ if lint
225
+ $logger.info("#{invalid} invalid checks out of #{good+invalid}")
185
226
  end
186
227
 
187
228
 
data/lib/dawn/reporter.rb CHANGED
@@ -199,7 +199,8 @@ module Dawn
199
199
  # 1_a) Third party gem vulnerabilities
200
200
  rows = []
201
201
  @engine.vulnerabilities.each do |vuln|
202
- rows << [vuln[:name].justify(10), vuln[:severity], vuln[:message].justify(30), vuln[:remediation].justify(15), vuln[:evidences].join.justify(15)]
202
+ $logger.error(vuln)
203
+ rows << [vuln[:name]&.justify(10), vuln[:severity], vuln[:message]&.justify(30), vuln[:remediation]&.justify(15), vuln[:evidences].join&.justify(15)]
203
204
  rows << :separator
204
205
  end
205
206
  table = Terminal::Table.new :title=>"Vulnerabilities", :headings=>['Issue', 'Severity', 'Description', 'Solution', 'Evidences'], :rows=>rows
data/lib/dawn/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Dawn
2
- VERSION = "2.0.0.rc3"
3
- CODENAME = "Finn McMissile"
4
- RELEASE = "(development)"
5
- BUILD = "2"
6
- COMMIT = "g8c963e9"
2
+ VERSION = "2.0.0.rc4"
3
+ CODENAME = "Finn McMissile"
4
+ RELEASE = "20210406"
5
+ BUILD = "26"
6
+ COMMIT = "g9f7c8c3"
7
7
  end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe "The security check for gem unsafe dependency should" do
5
+ before(:all) do
6
+ @check = YAML.load_file("./spec/lib/kb/dependency_check.yml")
7
+ @check.debug=true
8
+ puts @check.vulnerable_version_array
9
+ end
10
+
11
+ it "fires if vulnerable 0.5.0 version is detected" do
12
+ @check.dependencies = [{:name=>"acme-gem", :version=>'0.5.0'}]
13
+ expect(@check.vuln?).to eq(true)
14
+ end
15
+ it "fires if vulnerable 1.3.2 version is found" do
16
+ @check.dependencies = [{:name=>"acme-gem", :version=>'1.3.2'}]
17
+ expect(@check.vuln?).to eq(true)
18
+ end
19
+
20
+ it "fires if vulnerable 3.4.0 version is found" do
21
+ @check.dependencies = [{:name=>"acme-gem", :version=>'3.4.0'}]
22
+ expect(@check.vuln?).to eq(true)
23
+ end
24
+
25
+ it "doesn't fire if not vulnerable 3.0.0 version is found" do
26
+ @check.dependencies = [{:name=>"acme-gem", :version=>'3.0.0'}]
27
+ expect(@check.vuln?).to eq(false)
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ --- !ruby/object:Dawn::Kb::UnsafeDependencyCheck
2
+ applies:
3
+ - rails
4
+ - sinatra
5
+ - padrino
6
+ title: A test here
7
+ cvss: '(AV:L/AC:L/Au:S/C:N/I:C/A:C)'
8
+ cve: 'CVE-2021-99999'
9
+ owasp: A9
10
+ release_date: '25/03/2021'
11
+ kind: :unsafe_dependency_check
12
+ message: |-
13
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur nisi turpis, tincidunt rhoncus leo sed, euismod sollicitudin nisl. In a arcu accumsan, fermentum quam vel, auctor risus. Nulla non sollicitudin libero. Cras hendrerit consectetur pulvinar. Vivamus ligula quam, vulputate eget justo in, varius rhoncus lorem. Nulla vel volutpat enim. Nulla hendrerit posuere tempor. Nulla in metus eget lacus tempor sollicitudin sed et dolor. Ut interdum volutpat felis, ac bibendum mauris volutpat ut. Etiam posuere justo ex, nec faucibus orci suscipit sit amet. Vivamus rutrum massa fermentum mi pellentesque vehicula. Nullam elementum urna mauris, nec cursus risus convallis vel. Nulla consectetur enim ut magna rutrum, et mollis ante auctor. Etiam accumsan in lacus et ultricies. Morbi ullamcorper velit a ipsum egestas, quis laoreet lectus placerat. Maecenas nunc augue, pulvinar non ligula ac, maximus venenatis mi.
14
+
15
+ remediation: |-
16
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse et metus blandit, viverra ante a, auctor urna. Integer eget est ac nisl bibendum pharetra. Vivamus rhoncus neque vitae felis congue luctus. Praesent vitae lobortis mi. Nulla malesuada elit dictum tincidunt volutpat. Quisque tincidunt lorem nec eros ullamcorper lobortis. Nunc in felis sit amet purus sollicitudin tincidunt. Sed semper sapien nisi, non rutrum orci ultricies eget. Integer neque mauris, gravida ac varius nec, tincidunt consequat turpis. Fusce nisi metus, iaculis a eros eget, interdum sodales lectus. Pellentesque purus nisi, venenatis ut quam vitae, lacinia tristique turpis. Morbi sed maximus odio, et interdum risus. Duis nec congue lacus. Nunc sed elit a leo fermentum feugiat a aliquam arcu.
17
+
18
+ severity: :critical
19
+ priority: :high
20
+ check_family: :bulletin
21
+ vulnerable_version_array:
22
+ - :name: 'acme-gem'
23
+ :version:
24
+ - '0.5.0'
25
+ - '0.9.0'
26
+ - '0.9.2'
27
+ - '1.3.2'
28
+ - '2.9.0'
29
+ - '3.4.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dawnscanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc3
4
+ version: 2.0.0.rc4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paolo Perego
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-07 00:00:00.000000000 Z
11
+ date: 2021-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cvss
@@ -289,6 +289,7 @@ files:
289
289
  - checksum/dawnscanner-1.6.8.gem.sha1
290
290
  - checksum/dawnscanner-2.0.0.rc1.gem.sha1
291
291
  - checksum/dawnscanner-2.0.0.rc2.gem.sha1
292
+ - checksum/dawnscanner-2.0.0.rc3.gem.sha1
292
293
  - code_of_conduct.md
293
294
  - dawnscanner.gemspec
294
295
  - doc/change.sh
@@ -297,8 +298,12 @@ files:
297
298
  - doc/dawn_1_2_announcement.md
298
299
  - doc/dawn_1_5_announcement.md
299
300
  - doc/dawnscanner.yml.sample
301
+ - doc/kickstart_kb.tar.gz
300
302
  - doc/knowledge_base.rb
301
303
  - doc/new_knowledge_base_v1.0.md
304
+ - docs/.placeholder
305
+ - docs/CNAME
306
+ - docs/_config.yml
302
307
  - features/dawn_complains_about_an_incorrect_command_line.feature.disabled
303
308
  - features/dawn_scan_a_secure_sinatra_app.feature.disabled
304
309
  - features/dawn_scan_a_vulnerable_sinatra_app.feature.disabled
@@ -316,6 +321,7 @@ files:
316
321
  - lib/dawn/kb/pattern_match_check.rb
317
322
  - lib/dawn/kb/ruby_version_check.rb
318
323
  - lib/dawn/kb/rubygem_check.rb
324
+ - lib/dawn/kb/unsafe_depedency_check.rb
319
325
  - lib/dawn/kb/version_check.rb
320
326
  - lib/dawn/knowledge_base.rb
321
327
  - lib/dawn/logger.rb
@@ -340,7 +346,9 @@ files:
340
346
  - spec/lib/kb/codesake_dependency_version_check_spec.rb
341
347
  - spec/lib/kb/codesake_deprecation_check_spec.rb
342
348
  - spec/lib/kb/codesake_ruby_version_check_spec.rb
349
+ - spec/lib/kb/codesake_unsafe_dependency_check_spec.rb
343
350
  - spec/lib/kb/codesake_version_check_spec.rb
351
+ - spec/lib/kb/dependency_check.yml
344
352
  - spec/lib/kb/owasp_ror_cheatsheet_disabled.rb
345
353
  - spec/lib/kb/yamilize_kb_spec.rb
346
354
  - spec/spec_helper.rb
@@ -351,7 +359,7 @@ homepage: https://dawnscanner.org
351
359
  licenses:
352
360
  - MIT
353
361
  metadata: {}
354
- post_install_message:
362
+ post_install_message:
355
363
  rdoc_options: []
356
364
  require_paths:
357
365
  - lib
@@ -366,9 +374,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
366
374
  - !ruby/object:Gem::Version
367
375
  version: 1.3.1
368
376
  requirements: []
369
- rubyforge_project:
370
- rubygems_version: 2.7.7
371
- signing_key:
377
+ rubygems_version: 3.2.3
378
+ signing_key:
372
379
  specification_version: 4
373
380
  summary: Dawnscanner is a security source code scanner for ruby powered code. It is
374
381
  crafted with love to make your sinatra, padrino and ruby on rails web applications
@@ -389,7 +396,9 @@ test_files:
389
396
  - spec/lib/kb/codesake_dependency_version_check_spec.rb
390
397
  - spec/lib/kb/codesake_deprecation_check_spec.rb
391
398
  - spec/lib/kb/codesake_ruby_version_check_spec.rb
399
+ - spec/lib/kb/codesake_unsafe_dependency_check_spec.rb
392
400
  - spec/lib/kb/codesake_version_check_spec.rb
401
+ - spec/lib/kb/dependency_check.yml
393
402
  - spec/lib/kb/owasp_ror_cheatsheet_disabled.rb
394
403
  - spec/lib/kb/yamilize_kb_spec.rb
395
404
  - spec/spec_helper.rb