lib/codesake/dawn/core.rb in codesake-dawn-1.0.6 vs lib/codesake/dawn/core.rb in codesake-dawn-1.1.0.rc1
- old
+ new
@@ -1,60 +1,52 @@
+require "yaml"
+
module Codesake
module Dawn
class Core
+ # TODO.20140326
+ # All those methods must moved from here to Util class and a
+ # Codesake::Dawn::Core namespace must be created.
def self.help
puts "Usage: dawn [options] target_directory"
- printf "\n\nExamples:"
- puts "$ dawn a_sinatra_webapp_directory"
- puts "$ dawn -C the_rails_blog_engine"
- puts "$ dawn -C --output json a_sinatra_webapp_directory"
- printf "\n -r, --rails\t\t\t\t\tforce dawn to consider the target a rails application"
- printf "\n -s, --sinatra\t\t\t\tforce dawn to consider the target a sinatra application"
- printf "\n -p, --padrino\t\t\t\tforce dawn to consider the target a padrino application"
+ printf "\nExamples:\n"
+ puts "\t$ dawn a_sinatra_webapp_directory"
+ puts "\t$ dawn -C the_rails_blog_engine"
+ puts "\t$ dawn -C --json a_sinatra_webapp_directory"
+ puts "\t$ dawn --ascii-tabular-report my_rails_blog_ecommerce"
+ puts "\t$ dawn --html -F my_report.html my_rails_blog_ecommerce"
+ printf "\n -r, --rails\t\t\t\t\tforce dawn to consider the target a rails application"
+ printf "\n -s, --sinatra\t\t\t\tforce dawn to consider the target a sinatra application"
+ printf "\n -p, --padrino\t\t\t\tforce dawn to consider the target a padrino application"
printf "\n -G, --gem-lock\t\t\t\tforce dawn to scan only for vulnerabilities affecting dependencies in Gemfile.lock"
- printf "\n -D, --debug\t\t\t\t\tenters dawn debug mode"
- printf "\n -f, --list-known-framework\t\t\tlist ruby MVC frameworks supported by dawn"
- printf "\n -k, --list-knowledgebase [check_name]\tlist dawn known security checks. If check_name is specified dawn says if check is present or not"
- printf "\n -o, --output [console, json. csv, html]\tthe output will be in the specified format"
- printf "\n -V, --verbose\t\t\t\tthe output will be more verbose"
+ printf "\n -a, --ascii-tabular-report\t\t\tcause dawn to format findings using table in ascii art"
+ printf "\n -j, --json\t\t\t\t\tcause dawn to format findings using json"
printf "\n -C, --count-only\t\t\t\tdawn will only count vulnerabilities (useful for scripts)"
printf "\n -z, --exit-on-warn\t\t\t\tdawn will return number of found vulnerabilities as exit code"
+ printf "\n -F, --file filename\t\t\t\ttells dawn to write output to filename"
+ printf "\n -c, --config-file filename\t\t\ttells dawn to load configuration from filename"
+ printf "\n\nDisable security check family\n"
+ printf "\n --disable-cve-bulletins\t\t\tdisable all CVE security checks"
+ printf "\n --disable-code-quality\t\t\tdisable all code quality checks"
+ printf "\n --disable-code-style\t\t\tdisable all code style checks"
+ printf "\n --disable-owasp-ror-cheatsheet\t\tdisable all Owasp Ruby on Rails cheatsheet checks"
+ printf "\n --disable-owasp-top-10\t\t\tdisable all Owasp Top 10 checks"
+ printf "\n\nFlags useful to query Codesake::Dawn\n"
+ printf "\n -S, --search-knowledge-base [check_name]\tsearch check_name in the knowledge base"
+ printf "\n --list-knowledge-base\t\t\tlist knowledge-base content"
+ printf "\n --list-known-families\t\t\tlist security check families contained in dawn's knowledge base"
+ printf "\n --list-known-framework\t\t\tlist ruby MVC frameworks supported by dawn"
+ printf "\n\nService flags\n"
+ printf "\n -D, --debug\t\t\t\t\tenters dawn debug mode"
+ printf "\n -V, --verbose\t\t\t\tthe output will be more verbose"
printf "\n -v, --version\t\t\t\tshow version information"
printf "\n -h, --help\t\t\t\t\tshow this help\n"
- 0
+ true
end
-
- def self.output_json_run(target = "", engine = nil)
- result = {}
- return {:status=>"KO", :message=>"BUG at #{__FILE__}@#{__LINE__}: target is empty or engine is nil."}.to_json if target.empty? or engine.nil?
- return {:status=>"KO", :message=>"#{target} doesn't exist"}.to_json if ! Dir.exist?(target)
- check_applied = Codesake::Dawn::Core.dry_run(target, engine)
- return {:status=>"KO", :message=>"no security checks applied"}.to_json unless check_applied
-
- result[:status]="OK"
- result[:target]=target
- result[:mvc]=engine.name
- result[:mvc_version]=engine.get_mvc_version
- result[:vulnerabilities_count]=engine.count_vulnerabilities
- result[:vulnerabilities]=[]
- engine.vulnerabilities.each do |v|
- result[:vulnerabilities] << v[:name]
- end
- result[:mitigated_vuln_count]=engine.mitigated_issues.count
- result[:mitigated_vuln] = engine.mitigated_issues
- result[:reflected_xss] = []
- engine.reflected_xss.each do |r|
- result[:reflected_xss] << "request parameter \"#{r[:sink_source]}\""
- end
-
- result.to_json
- end
-
-
def self.dump_knowledge_base(verbose = false)
kb = Codesake::Dawn::KnowledgeBase.new
lines = []
lines << "Security checks currently supported:\n"
@@ -71,27 +63,20 @@
lines.empty? ? 0 : lines.compact.join("\n")
end
-
- def self.dry_run(target, engine)
- engine.set_target(target)
- engine.load_knowledge_base
- engine.apply_all
- end
-
# guess_mvc is very close to detect_mvc despite it accepts a
# filename as input and it tries to guess the mvc framework used from the
# gems it founds in Gemfile.lock without creating an engine.
def self.guess_mvc(gemfile_lock)
ret = {:name=>"", :version=>"", :connected_gems=>[]}
a = []
my_dir = Dir.pwd
- Dir.chdir(File.dirname(gemfile_lock))
+ Dir.chdir(File.dirname(gemfile_lock))
raise ArgumentError.new("can't read #{gemfile_lock}") unless File.readable?(File.basename(gemfile_lock))
lockfile = Bundler::LockfileParser.new(Bundler.read_file(File.basename(gemfile_lock)))
Dir.chdir(my_dir)
lockfile.specs.each do |s|
@@ -107,24 +92,72 @@
def self.detect_mvc(target)
raise ArgumentError.new("you must set target directory") if target.nil?
my_dir = Dir.pwd
- Dir.chdir(target)
+ Dir.chdir(target)
raise ArgumentError.new("no Gemfile.lock in #{target}") unless File.exist?("Gemfile.lock")
lockfile = Bundler::LockfileParser.new(Bundler.read_file("Gemfile.lock"))
Dir.chdir(my_dir)
lockfile.specs.each do |s|
return Codesake::Dawn::Rails.new(target) if s.name == "rails"
return Codesake::Dawn::Padrino.new(target) if s.name == "padrino"
end
- return Codesake::Dawn::Sinatra.new(target)
+ return Codesake::Dawn::Sinatra.new(target)
end
def self.is_good_target?(target)
(File.exist?(target) and File.directory?(target))
+ end
+
+ def self.find_conf(create_if_none = false)
+ conf_name = 'codesake-dawn.yaml'
+ path_order = [
+ './',
+ '~/',
+ '/usr/local/etc/',
+ ]
+ path_order.each do |p|
+ fn = p + conf_name if p.start_with?('/')
+ # if outside $HOME the config file must be hidden
+ fn = File.expand_path(p) + '/.'+conf_name if ! p.start_with?('/')
+ return fn if File.exist?(fn)
+ end
+
+ # Codesake::Dawn didn't find a config file.
+ # If create_if_none flag is set to false, than I'll return nil so the
+ # read_conf method will return the default configuration
+ return nil unless create_if_none
+
+ # If create_if_none flag is set to true, than I'll create a config file
+ # on the current directory with the default configuration.
+ conf = {"config"=>{:verbose=>false, :output=>"console", :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false, :enabled_checks=> Codesake::Dawn::Kb::BasicCheck::ALLOWED_FAMILIES}}
+
+ File.open(File.expand_path('~') +'/.'+conf_name, 'w') do |f|
+ f.write(YAML.dump(conf))
+ end
+ end
+
+ def self.read_conf(file=nil)
+
+ conf = {:verbose=>false, :output=>"console", :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false, :enabled_checks=> Codesake::Dawn::Kb::BasicCheck::ALLOWED_FAMILIES}
+ return conf if file.nil?
+ return conf if ! File.exist?(file)
+
+ c = YAML.load_file(file)
+
+ cf = c["config"]
+ cc = cf["enabled_checks"]
+ # TODO
+ # I must add some sanity check here
+ conf[:verbose] = cf["verbose"] unless cf["verbose"].nil?
+ conf[:debug] = cf["debug"] unless cf["debug"].nil?
+ conf[:output] = cf["output"] unless cf["output"].nil?
+ conf[:enabled_checks] = cc unless cc.nil?
+
+ return conf
end
end
end
end