Skip to content

Commit

Permalink
Fixing issue #45
Browse files Browse the repository at this point in the history
Merge branch 'issue_45_add_priority_and_severity_to_checks' into development
  • Loading branch information
thesp0nge committed Mar 26, 2014
2 parents 010359a + 4d9551f commit abe5456
Show file tree
Hide file tree
Showing 17 changed files with 481 additions and 152 deletions.
25 changes: 22 additions & 3 deletions Changelog.md
Expand Up @@ -50,16 +50,35 @@ _latest update: Sun Mar 23 23:06:38 CET 2014_
* Issue #34. I added a deprecation check. However I haven't found an official
link saying which are MVC gem version to be considered officially deprecated
or just old. I enabled only check against ruby

=======
* Added a --seach-knowledge-base removing the optional parameter to
--list-knowledge-base that is just for listing.
* Renamed '--list-knowledgebase' to '--list-knowledge-base' and '-k' short option was removed
* Added a --list-known-families option printing out Codesake::Dawn supported check family name
* Removed '-f' short option for list-known-framework
* Added family and severity to Owasp RoR Cheatsheet files
* Add a method to return severity level. If it's provided by check constructor
then that value is used, otherwise is calculated using CVSS. If no value and
no CVSS are available the return value is "unknown".
* Removed old ruby version check from BasicCheck. It's outdated and no longer
needed
* Added --disable-cve-bulletinsi flag to disable all CVE security checks
* Added --disable-code-quality flag to disable all code quality checks
* Added --disable-code-style flag to disable all code style checks
* Added --disable-owasp-ror-cheatsheet flag to disable all Owasp Ruby on Rails
cheatsheet checks
* Added --disable-owasp-top-10 flag to disable all Owasp Top 10 checks
* Revamped help output
* Added YAML Codesake::Dawn configuration support. Now you can specify your
preferences in a .codesake-dawn.yaml file in your home directory (or you can
use the --config-file option to specify the file you want to use). It returns
an embedded default configuration if the supplied filename doesn't exist.

## Version 1.0.6 - codename: Lightning McQueen (2014-03-23)

* Added a check for CVE-2014-2538

## Version 1.0.5 - codename: Lightning McQueen (2014-03-18)

>>>>>>> issue_46_add_cve_2014_2538
* Added a check for CVE-2014-2322
* Added a check for CVE-2014-0036

Expand Down
91 changes: 71 additions & 20 deletions bin/dawn
Expand Up @@ -15,35 +15,84 @@ VALID_OUTPUT_FORMAT = %w(console json csv html)

$logger = Codesake::Commons::Logging.instance
opts = GetoptLong.new(
# report formatting options
[ '--ascii-tabular-report', '-a', GetoptLong::NO_ARGUMENT],
[ '--json', '-j', GetoptLong::NO_ARGUMENT],
[ '--html', '-H', GetoptLong::NO_ARGUMENT],

# MVC forcing
[ '--rails', '-r', GetoptLong::NO_ARGUMENT],
[ '--sinatra', '-s', GetoptLong::NO_ARGUMENT],
[ '--padrino', '-p', GetoptLong::NO_ARGUMENT],
[ '--gem-lock', '-G', GetoptLong::REQUIRED_ARGUMENT],
[ '--list-known-framework', '-f', GetoptLong::NO_ARGUMENT],
[ '--list-knowledgebase', '-k', GetoptLong::OPTIONAL_ARGUMENT],
[ '--verbose', '-V', GetoptLong::NO_ARGUMENT],
[ '--debug', '-D', GetoptLong::NO_ARGUMENT],

[ '--gem-lock', '-G', GetoptLong::REQUIRED_ARGUMENT],
[ '--count-only', '-C', GetoptLong::NO_ARGUMENT],
[ '--exit-on-warn', '-z', GetoptLong::NO_ARGUMENT],

# Disable checks by family type
[ '--disable-cve-bulletins', GetoptLong::NO_ARGUMENT],
[ '--disable-code-quality', GetoptLong::NO_ARGUMENT],
[ '--disable-code-style', GetoptLong::NO_ARGUMENT],
[ '--disable-owasp-ror-cheatsheet', GetoptLong::NO_ARGUMENT],
[ '--disable-owasp-top-10', GetoptLong::NO_ARGUMENT],

# Search knowledge base
[ '--search-knowledge-base', '-S', GetoptLong::REQUIRED_ARGUMENT],
# List stuff
[ '--list-knowledge-base', GetoptLong::NO_ARGUMENT],
[ '--list-known-framework', GetoptLong::NO_ARGUMENT],
[ '--list-known-families', GetoptLong::NO_ARGUMENT],
# please save output to file
[ '--file', '-F', GetoptLong::REQUIRED_ARGUMENT],
# specify an alternate config file
[ '--config-file', '-c', GetoptLong::REQUIRED_ARGUMENT],

# service options
[ '--verbose', '-V', GetoptLong::NO_ARGUMENT],
[ '--debug', '-D', GetoptLong::NO_ARGUMENT],
[ '--version', '-v', GetoptLong::NO_ARGUMENT],
[ '--help', '-h', GetoptLong::NO_ARGUMENT]
)
opts.quiet=true

engine = nil
options = {:verbose=>false, :output=>"console", :dump_kb=>false, :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false}


options = Codesake::Dawn::Core.read_conf(Codesake::Dawn::Core.find_conf(true))
check = ""
guess = {:name=>"", :version=>"", :connected_gems=>[]}


begin
opts.each do |opt, val|
case opt
when '--version'
puts "#{Codesake::Dawn::VERSION} [#{Codesake::Dawn::CODENAME}]"
Kernel.exit(0)
when '--config-file'
options = Codesake::Dawn::Core.read_conf(val)
when '--disable-cve-bulletins'
options[:enabled_checks].delete(:cve_bulletin)
when '--disable-code-quality'
options[:enabled_checks].delete(:code_quality)
when '--disable-code-style'
options[:enabled_checks].delete(:code_style)
when '--disable-owasp-ror-cheatsheet'
options[:enabled_checks].delete(:owasp_ror_cheatsheet)
when '--disable-owasp-top-10'
options[:enabled_checks].delete(:owasp_top_10_1)
options[:enabled_checks].delete(:owasp_top_10_2)
options[:enabled_checks].delete(:owasp_top_10_3)
options[:enabled_checks].delete(:owasp_top_10_4)
options[:enabled_checks].delete(:owasp_top_10_5)
options[:enabled_checks].delete(:owasp_top_10_6)
options[:enabled_checks].delete(:owasp_top_10_7)
options[:enabled_checks].delete(:owasp_top_10_8)
options[:enabled_checks].delete(:owasp_top_10_9)
options[:enabled_checks].delete(:owasp_top_10_10)
when '--list-known-families'
printf "Codesake::Dawn supports following check families:\n\n"
puts Codesake::Dawn::Kb::BasicCheck.families
Kernel.exit(0)
when '--json'
options[:output] = "json"
when '--ascii-tabular-report'
Expand Down Expand Up @@ -73,9 +122,15 @@ opts.each do |opt, val|
when '--exit-on-warn'
options[:exit_on_warn] = true

when '--list-knowledgebase'
options[:dump_kb]=true
check = val unless val.nil?
when '--search-knowledge-base'
found = Codesake::Dawn::KnowledgeBase.find(nil, val)
puts "#{val} found in knowledgebase." if found
puts "#{val} not found in knowledgebase" if ! found
Kernel.exit(0)

when '--list-knowledge-base'
puts Codesake::Dawn::Core.dump_knowledge_base(options[:verbose])
Kernel.exit(0)
when '--list-known-framework'
puts "Ruby MVC framework supported by #{APPNAME}:"
LIST_KNOWN_FRAMEWORK.each do |mvc|
Expand All @@ -86,16 +141,11 @@ opts.each do |opt, val|
Kernel.exit(Codesake::Dawn::Core.help)
end
end
rescue GetoptLong::InvalidOption => e

if options[:dump_kb]
puts Codesake::Dawn::Core.dump_knowledge_base(options[:verbose]) if check.empty?
if ! check.empty?
found = Codesake::Dawn::KnowledgeBase.find(nil, check)
puts "#{check} found in knowledgebase." if found
puts "#{check} not found in knowledgebase" if ! found
end

Kernel.exit(0)
$logger.helo APPNAME, Codesake::Dawn::VERSION
$logger.err e.message
Kernel.exit(Codesake::Dawn::Core.help)
end

target=ARGV.shift
Expand All @@ -105,6 +155,7 @@ trap("INT") { $logger.die('[INTERRUPTED]') }
$logger.die("missing target") if target.nil? && options[:gemfile_name].nil?
$logger.die("invalid directory (#{target})") if options[:gemfile_name].nil? &&! Codesake::Dawn::Core.is_good_target?(target)
$logger.die("if scanning Gemfile.lock file you must not force target MVC using one from -r, -s or -p flag") if ! options[:mvc].empty? && options[:gemfile_scan]
$logger.log("security check enabled: #{options[:enabled_checks]}")


## MVC auto detect.
Expand Down Expand Up @@ -143,7 +194,7 @@ $logger.die "missing target framework option" if engine.nil?
$logger.warn "this is a development Codesake::Dawn version" if Codesake::Dawn::RELEASE == "(development)"
$logger.die "nothing to do on #{target}" if ! options[:gemfile_scan] && ! engine.can_apply?

engine.load_knowledge_base
engine.load_knowledge_base(options[:enabled_checks])
ret = engine.apply_all

if options[:output] == "count"
Expand Down
26 changes: 26 additions & 0 deletions doc/codesake-dawn.yaml.sample
@@ -0,0 +1,26 @@
---
config:
:verbose: false
:output: console
:mvc: ''
:gemfile_scan: false
:gemfile_name: ''
:filename:
:debug: false
:exit_on_warn: false
:enabled_checks:
- :generic_check
- :code_quality
- :cve_bulletin
- :code_style
- :owasp_ror_cheatsheet
- :owasp_top_10_1
- :owasp_top_10_2
- :owasp_top_10_3
- :owasp_top_10_4
- :owasp_top_10_5
- :owasp_top_10_6
- :owasp_top_10_7
- :owasp_top_10_8
- :owasp_top_10_9
- :owasp_top_10_10
88 changes: 75 additions & 13 deletions lib/codesake/dawn/core.rb
@@ -1,7 +1,12 @@
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 "\nExamples:\n"
Expand All @@ -10,23 +15,33 @@ def self.help
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 -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 -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 -V, --verbose\t\t\t\tthe output will be more verbose"
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\t\t\t\t\ttells dawn to write output to filename"
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 --list-knowledge-base [check_name]\tlist dawn known security checks. If check_name is specified dawn says if check is present or not"
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"

true
true
end

def self.dump_knowledge_base(verbose = false)
Expand All @@ -49,7 +64,6 @@ def self.dump_knowledge_base(verbose = false)

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.
Expand All @@ -59,7 +73,7 @@ def self.guess_mvc(gemfile_lock)

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)))
Expand All @@ -79,7 +93,7 @@ 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"))
Expand All @@ -89,12 +103,60 @@ def self.detect_mvc(target)
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

0 comments on commit abe5456

Please sign in to comment.