Module: Dawn::Engine
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.
-
#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.
-
#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 ⇒ Object
- #build_view_array(dir) ⇒ Object
- #can_apply? ⇒ Boolean
- #count_vulnerabilities ⇒ Object
- #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
- #scan_time ⇒ Object
- #set_mvc_version ⇒ Object
- #set_target(dir) ⇒ Object
- #target_is_dir? ⇒ Boolean
Methods included from Utils
#__debug_me_and_return, #debug_me, #debug_me_and_return_false, #debug_me_and_return_true
Instance Attribute Details
#applied_checks ⇒ Object (readonly)
Returns the value of attribute applied_checks.
43 44 45 |
# File 'lib/dawn/engine.rb', line 43 def applied_checks @applied_checks end |
#checks ⇒ Object (readonly)
Returns the value of attribute checks.
17 18 19 |
# File 'lib/dawn/engine.rb', line 17 def checks @checks end |
#connected_gems ⇒ Object (readonly)
Returns the value of attribute connected_gems.
16 17 18 |
# File 'lib/dawn/engine.rb', line 16 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=>“/”]
35 36 37 |
# File 'lib/dawn/engine.rb', line 35 def controllers @controllers end |
#debug ⇒ Object
Returns the value of attribute debug.
41 42 43 |
# File 'lib/dawn/engine.rb', line 41 def debug @debug end |
#engine_error ⇒ Object (readonly)
Returns the value of attribute engine_error.
22 23 24 |
# File 'lib/dawn/engine.rb', line 22 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
13 14 15 |
# File 'lib/dawn/engine.rb', line 13 def force @force end |
#gemfile_lock ⇒ Object (readonly)
Returns the value of attribute gemfile_lock.
14 15 16 |
# File 'lib/dawn/engine.rb', line 14 def gemfile_lock @gemfile_lock end |
#mitigated_issues ⇒ Object (readonly)
Returns the value of attribute mitigated_issues.
19 20 21 |
# File 'lib/dawn/engine.rb', line 19 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
39 40 41 |
# File 'lib/dawn/engine.rb', line 39 def models @models end |
#mvc_version ⇒ Object (readonly)
Returns the value of attribute mvc_version.
15 16 17 |
# File 'lib/dawn/engine.rb', line 15 def mvc_version @mvc_version end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
8 9 10 |
# File 'lib/dawn/engine.rb', line 8 def name @name end |
#reflected_xss ⇒ Object (readonly)
Returns the value of attribute reflected_xss.
24 25 26 |
# File 'lib/dawn/engine.rb', line 24 def reflected_xss @reflected_xss end |
#ruby_version ⇒ Object (readonly)
Returns the value of attribute ruby_version.
20 21 22 |
# File 'lib/dawn/engine.rb', line 20 def ruby_version @ruby_version end |
#scan_start ⇒ Object (readonly)
Returns the value of attribute scan_start.
9 10 11 |
# File 'lib/dawn/engine.rb', line 9 def scan_start @scan_start end |
#scan_stop ⇒ Object (readonly)
Returns the value of attribute scan_stop.
10 11 12 |
# File 'lib/dawn/engine.rb', line 10 def scan_stop @scan_stop end |
#skipped_checks ⇒ Object (readonly)
Returns the value of attribute skipped_checks.
44 45 46 |
# File 'lib/dawn/engine.rb', line 44 def skipped_checks @skipped_checks end |
#target ⇒ Object (readonly)
Returns the value of attribute target.
7 8 9 |
# File 'lib/dawn/engine.rb', line 7 def target @target end |
#views ⇒ Object (readonly)
Each view will be something like :language=>:haml
29 30 31 |
# File 'lib/dawn/engine.rb', line 29 def views @views end |
#vulnerabilities ⇒ Object (readonly)
Returns the value of attribute vulnerabilities.
18 19 20 |
# File 'lib/dawn/engine.rb', line 18 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
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/dawn/engine.rb', line 224 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| if check.name == name unless ((check.kind == Dawn::KnowledgeBase::PATTERN_MATCH_CHECK || check.kind == Dawn::KnowledgeBase::COMBO_CHECK ) && @name == "Gemfile.lock") debug_me "applying check #{check.name}" @applied_checks += 1 @applied << { :name=>name } check.ruby_version = @ruby_version[:version] check.detected_ruby = @ruby_version if check.kind == Dawn::KnowledgeBase::RUBY_VERSION_CHECK check.dependencies = self.connected_gems if check.kind == Dawn::KnowledgeBase::DEPENDENCY_CHECK check.root_dir = self.target if check.kind == Dawn::KnowledgeBase::PATTERN_MATCH_CHECK check. = {:detected_ruby => self.ruby_version, :dependencies => self.connected_gems, :root_dir => self.target } if check.kind == Dawn::KnowledgeBase::COMBO_CHECK check_vuln = check.vuln? @vulnerabilities << {:name=> check.name, :severity=>check.severity, :priority=>check.priority, :kind=>check.check_family, :message=>check., :remediation=>check.remediation, :evidences=>check.evidences, :vulnerable_checks=>nil} if check_vuln && check.kind != Dawn::KnowledgeBase::COMBO_CHECK @vulnerabilities << {:name=> check.name, :severity=>check.severity, :priority=>check.priority, :kind=>check.check_family, :message=>check., :remediation=>check.remediation, :evidences=>check.evidences, :vulnerable_checks=>check.vulnerable_checks} if check_vuln && check.kind == Dawn::KnowledgeBase::COMBO_CHECK @mitigated_issues << {:name=> check.name, :severity=>check.severity, :priority=>check.priority, :kind=>check.check_family, :message=>check., :remediation=>check.remediation, :evidences=>check.evidences, :vulnerable_checks=>nil} if check.mitigated? return true else debug_me "skipping check #{check.name}" @skipped_checks += 1 end end end false end |
#apply_all ⇒ Object
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 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 |
# File 'lib/dawn/engine.rb', line 270 def apply_all @scan_start = Time.now debug_me("SCAN STARTED: #{@scan_start}") # 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" @scan_stop = Time.now debug_me("SCAN STOPPED: #{@scan_stop}") return false end if @checks.empty? @scan_stop = Time.now debug_me("SCAN STOPPED: #{@scan_stop}") return false end @checks.each do |check| unless ((check.kind == Dawn::KnowledgeBase::PATTERN_MATCH_CHECK || check.kind == Dawn::KnowledgeBase::COMBO_CHECK ) && @gemfile_lock_sudo) @applied << { :name => name } debug_me "applying check #{check.name}" @applied_checks += 1 check.ruby_version = @ruby_version[:version] check.detected_ruby = @ruby_version if check.kind == Dawn::KnowledgeBase::RUBY_VERSION_CHECK check.dependencies = self.connected_gems if check.kind == Dawn::KnowledgeBase::DEPENDENCY_CHECK check.root_dir = self.target if check.kind == Dawn::KnowledgeBase::PATTERN_MATCH_CHECK check. = {:detected_ruby => self.ruby_version, :dependencies => self.connected_gems, :root_dir => self.target } if check.kind == Dawn::KnowledgeBase::COMBO_CHECK check_vuln = check.vuln? @vulnerabilities << {:name=> check.name, :severity=>check.severity, :priority=>check.priority, :kind=>check.check_family, :message=>check., :remediation=>check.remediation, :evidences=>check.evidences, :vulnerable_checks=>nil} if check_vuln && check.kind != Dawn::KnowledgeBase::COMBO_CHECK @vulnerabilities << {:name=> check.name, :severity=>check.severity, :priority=>check.priority, :kind=>check.check_family, :message=>check., :remediation=>check.remediation, :evidences=>check.evidences, :vulnerable_checks=>check.vulnerable_checks} if check_vuln && check.kind == Dawn::KnowledgeBase::COMBO_CHECK @mitigated_issues << {:name=> check.name, :severity=>check.severity, :priority=>check.priority, :kind=>check.check_family, :message=>check., :remediation=>check.remediation, :evidences=>check.evidences, :vulnerable_checks=>nil} if check.mitigated? else debug_me "skipping check #{check.name}" @skipped_checks += 1 end end @scan_stop = Time.now debug_me("SCAN STOPPED: #{@scan_stop}") true end |
#build_view_array(dir) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/dawn/engine.rb', line 113 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
203 204 205 |
# File 'lib/dawn/engine.rb', line 203 def can_apply? target_is_dir? && is_good_mvc? end |
#count_vulnerabilities ⇒ Object
357 358 359 360 361 362 363 |
# File 'lib/dawn/engine.rb', line 357 def count_vulnerabilities ret = 0 ret = @vulnerabilities.count unless @vulnerabilities.nil? ret += @reflected_xss.count unless @reflected_xss.nil? ret end |
#detect_controllers ⇒ Object
125 126 127 |
# File 'lib/dawn/engine.rb', line 125 def detect_controllers [] end |
#detect_models ⇒ Object
129 130 131 |
# File 'lib/dawn/engine.rb', line 129 def detect_models [] end |
#detect_views ⇒ Object
103 104 105 |
# File 'lib/dawn/engine.rb', line 103 def detect_views [] end |
#error! ⇒ Object
106 107 108 |
# File 'lib/dawn/engine.rb', line 106 def error! @error = true end |
#error? ⇒ Boolean
109 110 111 |
# File 'lib/dawn/engine.rb', line 109 def error? @error end |
#find_vulnerability_by_name(name) ⇒ Object
339 340 341 342 343 344 345 346 |
# File 'lib/dawn/engine.rb', line 339 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
207 208 209 |
# File 'lib/dawn/engine.rb', line 207 def get_mvc_version "#{@mvc_version}" if is_good_mvc? end |
#get_ruby_version ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/dawn/engine.rb', line 133 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
195 196 197 |
# File 'lib/dawn/engine.rb', line 195 def has_gemfile_lock? File.exist?(@gemfile_lock) end |
#has_reflected_xss? ⇒ Boolean
353 354 355 |
# File 'lib/dawn/engine.rb', line 353 def has_reflected_xss? (@reflected_xss.count != 0) unless @reflected_xss.nil? end |
#initialize(dir = nil, name = "", options = {}) ⇒ Object
46 47 48 49 50 51 52 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 |
# File 'lib/dawn/engine.rb', line 46 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 @debug = false @debug = [:debug] unless [:debug].nil? @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? @views = detect_views @controllers = detect_controllers @models = detect_models if $logger.nil? $logger = Codesake::Commons::Logging.instance $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
327 328 329 330 331 332 |
# File 'lib/dawn/engine.rb', line 327 def is_applied?(name) @applied.each do |a| return true if a[:name] == name end return false end |
#is_good_mvc? ⇒ Boolean
199 200 201 |
# File 'lib/dawn/engine.rb', line 199 def is_good_mvc? (@mvc_version != "") end |
#is_vulnerable_to?(name) ⇒ Boolean
348 349 350 |
# File 'lib/dawn/engine.rb', line 348 def is_vulnerable_to?(name) return (find_vulnerability_by_name(name) != nil) end |
#load_knowledge_base(enabled_checks = []) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/dawn/engine.rb', line 161 def load_knowledge_base(enabled_checks=[]) debug_me("load_knowledge_base called. Enabled checks are: #{enabled_checks}") if @name == "Gemfile.lock" @checks = Dawn::KnowledgeBase.new({:enabled_checks=>enabled_checks}).all if @force.empty? @checks = Dawn::KnowledgeBase.new({:enabled_checks=>enabled_checks}).all_by_mvc(@force) unless @force.empty? else @checks = Dawn::KnowledgeBase.new({:enabled_checks=>enabled_checks}).all_by_mvc(@name) end debug_me("#{@checks.count} checks loaded") @checks end |
#scan_time ⇒ Object
323 324 325 |
# File 'lib/dawn/engine.rb', line 323 def scan_time @scan_stop - @scan_start end |
#set_mvc_version ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/dawn/engine.rb', line 176 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
150 151 152 153 154 155 |
# File 'lib/dawn/engine.rb', line 150 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
157 158 159 |
# File 'lib/dawn/engine.rb', line 157 def target_is_dir? File.directory?(@target) end |