Module: Dawn::Engine
- Included in:
- GemfileLock, Padrino, Rails, Sinatra
- Defined in:
- lib/dawn/engine.rb
Instance Attribute Summary collapse
-
#applied_checks ⇒ Object
readonly
Returns the value of attribute applied_checks.
-
#checks ⇒ Object
readonly
Returns the value of attribute checks.
-
#connected_gems ⇒ Object
readonly
Returns the value of attribute connected_gems.
-
#controllers ⇒ Object
readonly
Each controller will be a little bit more complex.
-
#debug ⇒ Object
Returns the value of attribute debug.
-
#engine_error ⇒ Object
readonly
Returns the value of attribute engine_error.
-
#force ⇒ Object
readonly
This attribute is used when @name == “Gemfile.lock” to force the loading of specific MVC checks.
-
#gemfile_lock ⇒ Object
readonly
Returns the value of attribute gemfile_lock.
-
#mitigated_issues ⇒ Object
readonly
Returns the value of attribute mitigated_issues.
-
#models ⇒ Object
readonly
Models I don’t know right now.
-
#mvc_version ⇒ Object
readonly
Returns the value of attribute mvc_version.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#output_dir_name ⇒ Object
readonly
Returns the value of attribute output_dir_name.
-
#reflected_xss ⇒ Object
readonly
Returns the value of attribute reflected_xss.
-
#ruby_version ⇒ Object
readonly
Returns the value of attribute ruby_version.
-
#scan_start ⇒ Object
readonly
Returns the value of attribute scan_start.
-
#scan_stop ⇒ Object
readonly
Returns the value of attribute scan_stop.
-
#skipped_checks ⇒ Object
readonly
Returns the value of attribute skipped_checks.
-
#stats ⇒ Object
readonly
Returns the value of attribute stats.
-
#target ⇒ Object
readonly
Returns the value of attribute target.
-
#views ⇒ Object
readonly
Each view will be something like :language=>:haml.
-
#vulnerabilities ⇒ Object
readonly
Returns the value of attribute vulnerabilities.
Instance Method Summary collapse
-
#apply(name) ⇒ Object
Security stuff applies here.
- #apply_all(checks_to_be_skipped = []) ⇒ Object
- #build_view_array(dir) ⇒ Object
- #can_apply? ⇒ Boolean
- #count_vulnerabilities ⇒ Object
-
#create_output_dir ⇒ Object
Creates the directory.
- #detect_controllers ⇒ Object
- #detect_models ⇒ Object
- #detect_views ⇒ Object
- #error! ⇒ Object
- #error? ⇒ Boolean
- #find_vulnerability_by_name(name) ⇒ Object
- #get_mvc_version ⇒ Object
- #get_ruby_version ⇒ Object
- #has_gemfile_lock? ⇒ Boolean
- #has_reflected_xss? ⇒ Boolean
- #initialize(dir = nil, name = "", options = {}) ⇒ Object
- #is_applied?(name) ⇒ Boolean
- #is_good_mvc? ⇒ Boolean
- #is_vulnerable_to?(name) ⇒ Boolean
- #load_knowledge_base(enabled_checks = []) ⇒ Object
-
#output_dir ⇒ Object
Creates the directory name where dawnscanner results will be saved.
- #scan_time ⇒ Object
- #set_mvc_version ⇒ Object
- #set_target(dir) ⇒ Object
- #target_is_dir? ⇒ Boolean
Instance Attribute Details
#applied_checks ⇒ Object (readonly)
Returns the value of attribute applied_checks.
48 49 50 |
# File 'lib/dawn/engine.rb', line 48 def applied_checks @applied_checks end |
#checks ⇒ Object (readonly)
Returns the value of attribute checks.
21 22 23 |
# File 'lib/dawn/engine.rb', line 21 def checks @checks end |
#connected_gems ⇒ Object (readonly)
Returns the value of attribute connected_gems.
20 21 22 |
# File 'lib/dawn/engine.rb', line 20 def connected_gems @connected_gems end |
#controllers ⇒ Object (readonly)
Each controller will be a little bit more complex. Of course for Sinatra, the controller filename will be the sole web application ruby file. :actions=>[{:name=>“index”, :method=>:get, :map=>“/”]
40 41 42 |
# File 'lib/dawn/engine.rb', line 40 def controllers @controllers end |
#debug ⇒ Object
Returns the value of attribute debug.
46 47 48 |
# File 'lib/dawn/engine.rb', line 46 def debug @debug end |
#engine_error ⇒ Object (readonly)
Returns the value of attribute engine_error.
26 27 28 |
# File 'lib/dawn/engine.rb', line 26 def engine_error @engine_error end |
#force ⇒ Object (readonly)
This attribute is used when @name == “Gemfile.lock” to force the loading of specific MVC checks
17 18 19 |
# File 'lib/dawn/engine.rb', line 17 def force @force end |
#gemfile_lock ⇒ Object (readonly)
Returns the value of attribute gemfile_lock.
18 19 20 |
# File 'lib/dawn/engine.rb', line 18 def gemfile_lock @gemfile_lock end |
#mitigated_issues ⇒ Object (readonly)
Returns the value of attribute mitigated_issues.
23 24 25 |
# File 'lib/dawn/engine.rb', line 23 def mitigated_issues @mitigated_issues end |
#models ⇒ Object (readonly)
Models I don’t know right now. Let them initialized as Array… we will see later
44 45 46 |
# File 'lib/dawn/engine.rb', line 44 def models @models end |
#mvc_version ⇒ Object (readonly)
Returns the value of attribute mvc_version.
19 20 21 |
# File 'lib/dawn/engine.rb', line 19 def mvc_version @mvc_version end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
12 13 14 |
# File 'lib/dawn/engine.rb', line 12 def name @name end |
#output_dir_name ⇒ Object (readonly)
Returns the value of attribute output_dir_name.
51 52 53 |
# File 'lib/dawn/engine.rb', line 51 def output_dir_name @output_dir_name end |
#reflected_xss ⇒ Object (readonly)
Returns the value of attribute reflected_xss.
29 30 31 |
# File 'lib/dawn/engine.rb', line 29 def reflected_xss @reflected_xss end |
#ruby_version ⇒ Object (readonly)
Returns the value of attribute ruby_version.
24 25 26 |
# File 'lib/dawn/engine.rb', line 24 def ruby_version @ruby_version end |
#scan_start ⇒ Object (readonly)
Returns the value of attribute scan_start.
13 14 15 |
# File 'lib/dawn/engine.rb', line 13 def scan_start @scan_start end |
#scan_stop ⇒ Object (readonly)
Returns the value of attribute scan_stop.
14 15 16 |
# File 'lib/dawn/engine.rb', line 14 def scan_stop @scan_stop end |
#skipped_checks ⇒ Object (readonly)
Returns the value of attribute skipped_checks.
49 50 51 |
# File 'lib/dawn/engine.rb', line 49 def skipped_checks @skipped_checks end |
#stats ⇒ Object (readonly)
Returns the value of attribute stats.
27 28 29 |
# File 'lib/dawn/engine.rb', line 27 def stats @stats end |
#target ⇒ Object (readonly)
Returns the value of attribute target.
11 12 13 |
# File 'lib/dawn/engine.rb', line 11 def target @target end |
#views ⇒ Object (readonly)
Each view will be something like :language=>:haml
34 35 36 |
# File 'lib/dawn/engine.rb', line 34 def views @views end |
#vulnerabilities ⇒ Object (readonly)
Returns the value of attribute vulnerabilities.
22 23 24 |
# File 'lib/dawn/engine.rb', line 22 def vulnerabilities @vulnerabilities end |
Instance Method Details
#apply(name) ⇒ Object
Security stuff applies here
Public it applies a single security check given by its name
name - the security check to be applied
Examples
engine.apply("CVE-2013-1800")
# => boolean
Returns a true value if the security check was successfully applied or false otherwise
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/dawn/engine.rb', line 271 def apply(name) # FIXME.20140325 # Now if no checks are loaded because knowledge base was not previously called, apply and apply_all proudly refuse to run. # Reason is simple, load_knowledge_base now needs enabled check array # and I don't want to pollute engine API to propagate this value. It's # a param to load_knowledge_base and then bin/dawn calls it # accordingly. # load_knowledge_base if @checks.nil? if @checks.nil? $logger.err "you must load knowledge base before trying to apply security checks" return false end return false if @checks.empty? @checks.each do |check| _do_apply(check) if check.name == name end false end |
#apply_all(checks_to_be_skipped = []) ⇒ Object
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/dawn/engine.rb', line 296 def apply_all(checks_to_be_skipped=[]) @scan_start = Time.now debug_me("I'm asked to skip those checks #{checks_to_be_skipped}") debug_me("SCAN STARTED: #{@scan_start}") if @checks.nil? $logger.error "you must load knowledge base before trying to apply security checks" @scan_stop = Time.now debug_me("SCAN STOPPED: #{@scan_stop}") return false end if @checks.empty? $logger.warn "no security checks found. This is strange" @scan_stop = Time.now debug_me("SCAN STOPPED: #{@scan_stop}") return false end @checks.each do |check| if checks_to_be_skipped.include?(check.name) $logger.info("skipping security check #{check.name}") else _do_apply(check) end end @scan_stop = Time.now debug_me("SCAN STOPPED: #{@scan_stop}") true end |
#build_view_array(dir) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/dawn/engine.rb', line 127 def build_view_array(dir) return [] unless File.exist?(dir) and File.directory?(dir) ret = [] Dir.glob(File.join("#{dir}", "*")).each do |filename| ret << {:filename=>filename, :language=>:haml} if File.extname(filename) == ".haml" end ret end |
#can_apply? ⇒ Boolean
215 216 217 |
# File 'lib/dawn/engine.rb', line 215 def can_apply? target_is_dir? && is_good_mvc? end |
#count_vulnerabilities ⇒ Object
363 364 365 366 367 368 369 |
# File 'lib/dawn/engine.rb', line 363 def count_vulnerabilities ret = 0 ret = @vulnerabilities.count unless @vulnerabilities.nil? ret += @reflected_xss.count unless @reflected_xss.nil? ret end |
#create_output_dir ⇒ Object
Creates the directory
247 248 249 250 |
# File 'lib/dawn/engine.rb', line 247 def create_output_dir FileUtils.mkdir_p(@output_dir_name) @output_dir_name end |
#detect_controllers ⇒ Object
139 140 141 |
# File 'lib/dawn/engine.rb', line 139 def detect_controllers [] end |
#detect_models ⇒ Object
143 144 145 |
# File 'lib/dawn/engine.rb', line 143 def detect_models [] end |
#detect_views ⇒ Object
117 118 119 |
# File 'lib/dawn/engine.rb', line 117 def detect_views [] end |
#error! ⇒ Object
120 121 122 |
# File 'lib/dawn/engine.rb', line 120 def error! @error = true end |
#error? ⇒ Boolean
123 124 125 |
# File 'lib/dawn/engine.rb', line 123 def error? @error end |
#find_vulnerability_by_name(name) ⇒ Object
345 346 347 348 349 350 351 352 |
# File 'lib/dawn/engine.rb', line 345 def find_vulnerability_by_name(name) apply(name) unless is_applied?(name) @vulnerabilities.each do |v| return v if v[:name] == name end nil end |
#get_mvc_version ⇒ Object
219 220 221 |
# File 'lib/dawn/engine.rb', line 219 def get_mvc_version "#{@mvc_version}" if is_good_mvc? end |
#get_ruby_version ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/dawn/engine.rb', line 147 def get_ruby_version unless @target.nil? # does target use rbenv? ver = get_rbenv_ruby_ver # does the target use rvm? ver = get_rvm_ruby_ver if ver[:version].empty? && ver[:patchlevel].empty? # take the running ruby otherwise ver = {:engine=>RUBY_ENGINE, :version=>RUBY_VERSION, :patchlevel=>"p#{RUBY_PATCHLEVEL}"} if ver[:version].empty? && ver[:patchlevel].empty? else ver = {:engine=>RUBY_ENGINE, :version=>RUBY_VERSION, :patchlevel=>"p#{RUBY_PATCHLEVEL}"} end ver end |
#has_gemfile_lock? ⇒ Boolean
207 208 209 |
# File 'lib/dawn/engine.rb', line 207 def has_gemfile_lock? File.exist?(@gemfile_lock) end |
#has_reflected_xss? ⇒ Boolean
359 360 361 |
# File 'lib/dawn/engine.rb', line 359 def has_reflected_xss? (@reflected_xss.count != 0) unless @reflected_xss.nil? end |
#initialize(dir = nil, name = "", options = {}) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/dawn/engine.rb', line 53 def initialize(dir=nil, name="", ={}) @name = name @scan_start = Time.now @scan_stop = @scan_start @mvc_version = "" @gemfile_lock = "" @force = "" @connected_gems = [] @checks = [] @vulnerabilities = [] @mitigated_issues = [] @applied = [] @reflected_xss = [] @engine_error = false @applied_checks = 0 @skipped_checks = 0 @gemfile_lock_sudo = false set_target(dir) unless dir.nil? @ruby_version = get_ruby_version if dir.nil? @gemfile_lock = [:gemfile_name] unless [:gemfile_name].nil? # @stats = gather_statistics @views = detect_views @controllers = detect_controllers @models = detect_models @output_dir_name = output_dir if $logger.nil? require 'logger' $logger = Logger.new(STDOUT) $logger.helo "dawn-engine", Dawn::VERSION end $logger.warn "pattern matching security checks are disabled for Gemfile.lock scan" if @name == "Gemfile.lock" $logger.warn "combo security checks are disabled for Gemfile.lock scan" if @name == "Gemfile.lock" debug_me "engine is in debug mode" if @name == "Gemfile.lock" && ! [:guessed_mvc].nil? # since all checks relies on @name a Gemfile.lock engine must # impersonificate the engine for the mvc it was detected debug_me "now I'm switching my name from #{@name} to #{[:guessed_mvc][:name]}" $logger.err "there are no connected gems... it seems Gemfile.lock parsing failed" if [:guessed_mvc][:connected_gems].empty? @name = [:guessed_mvc][:name] @mvc_version = [:guessed_mvc][:version] @connected_gems = [:guessed_mvc][:connected_gems] @gemfile_lock_sudo = true end # FIXME.20140325 # # I comment out this call. knowledge base must be called explicitly # since it's now possible to pass an array saying check families to be # loaded. # # load_knowledge_base end |
#is_applied?(name) ⇒ Boolean
333 334 335 336 337 338 |
# File 'lib/dawn/engine.rb', line 333 def is_applied?(name) @applied.each do |a| return true if a[:name] == name end return false end |
#is_good_mvc? ⇒ Boolean
211 212 213 |
# File 'lib/dawn/engine.rb', line 211 def is_good_mvc? (@mvc_version != "") end |
#is_vulnerable_to?(name) ⇒ Boolean
354 355 356 |
# File 'lib/dawn/engine.rb', line 354 def is_vulnerable_to?(name) return (find_vulnerability_by_name(name) != nil) end |
#load_knowledge_base(enabled_checks = []) ⇒ Object
175 176 177 178 179 180 181 182 183 184 |
# File 'lib/dawn/engine.rb', line 175 def load_knowledge_base(enabled_checks=[]) debug_me("load_knowledge_base called. Enabled checks are: #{enabled_checks}") Dawn::KnowledgeBase.enabled_checks=[:bulletin, :generic_check] kb = Dawn::KnowledgeBase.instance @checks=kb.load debug_me("#{@checks.count} checks loaded") @checks end |
#output_dir ⇒ Object
Creates the directory name where dawnscanner results will be saved
Examples
engine.create_output_dir
# => /Users/thesp0nge/dawnscanner/results/railsgoat/20151123
# => /Users/thesp0nge/dawnscanner/results/railsgoat/20151123_1 (if
previous directory name exists)
234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/dawn/engine.rb', line 234 def output_dir @output_dir_name = File.join(Dir.home, 'dawnscanner', 'results', File.basename(@target), Time.now.strftime('%Y%m%d')) if Dir.exist?(@output_dir_name) i=1 while (Dir.exist?(@output_dir_name)) do @output_dir_name = File.join(Dir.home, 'dawnscanner', 'results', File.basename(@target), "#{Time.now.strftime('%Y%m%d')}_#{i}") i+=1 end end @output_dir_name end |
#scan_time ⇒ Object
329 330 331 |
# File 'lib/dawn/engine.rb', line 329 def scan_time @scan_stop - @scan_start end |
#set_mvc_version ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/dawn/engine.rb', line 188 def set_mvc_version ver = "" return ver unless target_is_dir? return ver unless has_gemfile_lock? my_dir = Dir.pwd Dir.chdir(@target) lockfile = Bundler::LockfileParser.new(Bundler.read_file("Gemfile.lock")) lockfile.specs.each do |s| # detecting MVC version using @name in case of sinatra, padrino or rails engine ver= s.version.to_s if s.name == @name && @name != "Gemfile.lock" # detecting MVC version using @force in case of Gemfile.lock engine ver= s.version.to_s if s.name == @force.to_s && @name == "Gemfile.lock" @connected_gems << {:name=>s.name, :version=>s.version.to_s} end Dir.chdir(my_dir) return ver end |
#set_target(dir) ⇒ Object
164 165 166 167 168 169 |
# File 'lib/dawn/engine.rb', line 164 def set_target(dir) @target = dir @gemfile_lock = File.join(@target, "Gemfile.lock") @mvc_version = set_mvc_version @ruby_version = get_ruby_version end |
#target_is_dir? ⇒ Boolean
171 172 173 |
# File 'lib/dawn/engine.rb', line 171 def target_is_dir? File.directory?(@target) end |