Permalink
Browse files

Improved documentation and added bootstrap 2.x stuff to produce HTML

reports
  • Loading branch information...
thesp0nge committed Feb 5, 2014
1 parent f1e6460 commit 96341855ffd65b78c069fa20e3c8dec74e21cad0
Showing with 2,252 additions and 30 deletions.
  1. +36 −21 README.md
  2. +1 −0 Roadmap.md
  3. +9 −4 bin/dawn
  4. +2 −0 lib/codesake/dawn/core.rb
  5. +2 −3 lib/codesake/dawn/gemfile_lock.rb
  6. +103 −2 lib/codesake/dawn/reporter.rb
  7. +2,027 −0 support/bootstrap.js
  8. +9 −0 support/bootstrap.min.css
  9. +63 −0 support/codesake.css
View
@@ -115,28 +115,32 @@ $ dawn [options] target
In case of need, there is a quick command line option reference running ```dawn -h``` at your OS prompt.
```
-$ bundle exec dawn -h
-08:05:21 [*] dawn v1.0.0 is starting up
-Usage: dawn [options] target_directory
+$ dawn -h
+Usage: dawn [options] target_directory
-Examples:$ dawn a_sinatra_webapp_directory
-$ dawn -C the_rails_blog_engine
-$ dawn -C --output json a_sinatra_webapp_directory
-
- -r, --rails force dawn to consider the target a rails application
- -s, --sinatra force dawn to consider the target a sinatra application
- -p, --padrino force dawn to consider the target a padrino application
- -G, --gem-lock force dawn to scan only for vulnerabilities affecting dependencies in Gemfile.lock
- -D, --debug enters dawn debug mode
- -f, --list-known-framework list ruby MVC frameworks supported by dawn
- -k, --list-knowledgebase [check_name] list dawn known security checks. If check_name is specified dawn says if check is present or not
- -o, --output [console, json. csv, html] the output will be in the specified format
- -V, --verbose the output will be more verbose
- -C, --count-only dawn will only count vulnerabilities (useful for scripts)
- -z, --exit-on-warn dawn will return number of found vulnerabilities as exit code
- -v, --version show version information
- -h, --help show this help
+Examples:
+ $ dawn a_sinatra_webapp_directory
+ $ dawn -C the_rails_blog_engine
+ $ dawn -C --json a_sinatra_webapp_directory
+ $ dawn --ascii-tabular-report my_rails_blog_ecommerce
+ $ dawn --html -F my_report.html my_rails_blog_ecommerce
+
+ -r, --rails force dawn to consider the target a rails application
+ -s, --sinatra force dawn to consider the target a sinatra application
+ -p, --padrino force dawn to consider the target a padrino application
+ -G, --gem-lock force dawn to scan only for vulnerabilities affecting dependencies in Gemfile.lock
+ -D, --debug enters dawn debug mode
+ -f, --list-known-framework list ruby MVC frameworks supported by dawn
+ -k, --list-knowledgebase [check_name] list dawn known security checks. If check_name is specified dawn says if check is present or not
+ -a, --ascii-tabular-report cause dawn to format findings using table in ascii art
+ -j, --json cause dawn to format findings using json
+ -V, --verbose the output will be more verbose
+ -C, --count-only dawn will only count vulnerabilities (useful for scripts)
+ -z, --exit-on-warn dawn will return number of found vulnerabilities as exit code
+ -F, --file tells dawn to write output to filename
+ -v, --version show version information
+ -h, --help show this help
```
### Codesake::Dawn security scan in action
@@ -227,6 +231,17 @@ This check will analyze the source code looking for the following patterns: XXX,
08:28:18 [*] dawn is leaving
```
+If you need a fancy HTML report about your scan, just ask to Codesake::Dawn
+
+```
+$ dawn /Users/thesp0nge/src/hacking/rt_first_app --html --file report.html (ruby-2.0.0-p353@codesake)
+
+09:00:54 [*] dawn v1.1.0 is starting up
+09:00:54 [!] dawn: this is a development Codesake::Dawn version
+09:00:54 [*] dawn: report.html created (2952 bytes)
+09:00:54 [*] dawn is leaving
+```
+
---
## Useful links
@@ -263,7 +278,7 @@ Thank you.
[saten](https://github.com/saten): first issue posted about a typo in the README
-[presidentbeef](https://github.com/presidentbeef): for his outstanding work that inspired me creating dawn and for double check comparison matrix. Issue #2 is your :)
+[presidentbeef](https://github.com/presidentbeef): for his outstanding work that inspired me creating dawn and for double check comparison matrix. Issue #2 is yours :)
[marinerJB](https://github.com/marinerJB): for misc bug reports and further ideas
View
@@ -54,6 +54,7 @@ _latest update: Thu Jan 30 08:39:13 CET 2014_
* Create a digital signature as described [here](http://rubygems.rubyforge.org/rubygems-update/Gem/Security.html)
* Add preliminary Cross Site Scripting detection for Ruby on Rails.
* bin/dawn refactoring using the new Reporting class to produce json, csv, html output
+* add config file with setting (css directory, report options, ...)
## Version 1.2.0
View
@@ -17,6 +17,7 @@ $logger = Codesake::Commons::Logging.instance
opts = GetoptLong.new(
[ '--ascii-tabular-report', '-a', GetoptLong::NO_ARGUMENT],
[ '--json', '-j', GetoptLong::NO_ARGUMENT],
+ [ '--html', '-H', GetoptLong::NO_ARGUMENT],
[ '--rails', '-r', GetoptLong::NO_ARGUMENT],
[ '--sinatra', '-s', GetoptLong::NO_ARGUMENT],
[ '--padrino', '-p', GetoptLong::NO_ARGUMENT],
@@ -27,11 +28,12 @@ opts = GetoptLong.new(
[ '--debug', '-D', GetoptLong::NO_ARGUMENT],
[ '--count-only', '-C', GetoptLong::NO_ARGUMENT],
[ '--exit-on-warn', '-z', GetoptLong::NO_ARGUMENT],
+ [ '--file', '-F', GetoptLong::REQUIRED_ARGUMENT],
[ '--version', '-v', GetoptLong::NO_ARGUMENT],
[ '--help', '-h', GetoptLong::NO_ARGUMENT]
)
engine = nil
-options = {:verbose=>false, :output=>"console", :dump_kb=>false, :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :debug=>false, :exit_on_warn => false}
+options = {:verbose=>false, :output=>"console", :dump_kb=>false, :mvc=>"", :gemfile_scan=>false, :gemfile_name=>"", :filename=>nil, :debug=>false, :exit_on_warn => false}
check = ""
guess = {:name=>"", :version=>"", :connected_gems=>[]}
@@ -46,18 +48,21 @@ opts.each do |opt, val|
options[:output] = "json"
when '--ascii-tabular-report'
options[:output] = "tabular"
+ when '--html'
+ options[:output] = "html"
when '--rails'
options[:mvc]=:rails
when '--sinatra'
options[:mvc]=:sinatra
when '--padrino'
options[:mvc]=:padrino
+ when '--file'
+ options[:filename] = val
when '--gem-lock'
options[:gemfile_scan] = true
unless val.empty?
options[:gemfile_name] = val
guess = Codesake::Dawn::Core.guess_mvc(val)
- puts "Guessed MVC: #{guess[:name]} v#{guess[:version]}"
end
when '--verbose'
@@ -114,7 +119,7 @@ unless options[:gemfile_scan]
$logger.die(e.message)
end
else
- engine = Codesake::Dawn::GemfileLock.new(target, options[:gemfile_name], options[:debug], guess) # if options[:gemfile_scan]
+ engine = Codesake::Dawn::GemfileLock.new(target, options[:gemfile_name], guess) # if options[:gemfile_scan]
end
engine = Codesake::Dawn::Rails.new(target) if options[:mvc] == :rails && options[:gemfile_scan].nil?
@@ -149,5 +154,5 @@ if options[:output] == "count"
Kernel.exit(0)
end
-Codesake::Dawn::Reporter.new({:engine=>engine, :apply_all_code=>ret, :format=>options[:output].to_sym}).report
+Codesake::Dawn::Reporter.new({:engine=>engine, :apply_all_code=>ret, :format=>options[:output].to_sym, :filename=>options[:filename]}).report
$logger.bye
@@ -9,6 +9,7 @@ def self.help
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"
@@ -21,6 +22,7 @@ def self.help
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 -v, --version\t\t\t\tshow version information"
printf "\n -h, --help\t\t\t\t\tshow this help\n"
@@ -3,9 +3,8 @@ module Dawn
class GemfileLock
include Codesake::Dawn::Engine
- def initialize(dir = "./", filename = "", debug, guessed_mvc)
- debug_me "GUESSED MVS IS #{guessed_mvc}"
- super(dir, "Gemfile.lock", {:gemfile_name=>filename, :debug=>debug, :guessed_mvc=>guessed_mvc})
+ def initialize(dir = "./", filename = "", guessed_mvc)
+ super(dir, "Gemfile.lock", {:gemfile_name=>filename, :guessed_mvc=>guessed_mvc})
end
end
@@ -6,6 +6,7 @@ def initialize(options={})
@engine = nil
@ret = false
+ @filename = options[:filename]
@ret = options[:apply_all_code] unless options[:apply_all_code].nil?
@format = options[:format] unless options[:format].nil?
@engine = options[:engine] unless options[:engine].nil?
@@ -17,15 +18,110 @@ def report
ascii_tabular_report if @format == :tabular
json_report if @format == :json
ascii_plain_report if @format == :console
+ html_report if @format == :html
end
private
+ def write(output)
+
+ puts output if @filename.nil?
+
+ unless @filename.nil?
+ $logger.warn "I will use codesake.css, bootstrap.min.css and bootstrap.js stored in ./support/ directory" if @format == :html
+ File.open(@filename, "w") do |f|
+ f.puts output
+ end
+ $logger.ok "#{@filename} created (#{output.length} bytes)"
+ end
+ end
def is_valid_format?(format)
return false if format.nil?
return true if (format == :console) || (format == :tabular) || (format == :json) || (format == :html) || (format == :csv)
return false # otherwise
end
+ def html_report
+ html_head = "<!doctype html><html><head><title>Codesake::Dawn report for #{File.basename(@engine.target)}</title>"
+ html_head += "<script src=\"./support/bootstrap.js\"></script>"
+ html_head += "<link href=\"./support/codesake.css\" media=\"all\" rel=\"stylesheet\" />"
+ html_head += "<link href=\"./support/bootstrap.min.css\" media=\"all\" rel=\"stylesheet\" />"
+ html_head += "</head>"
+ html_body = "<body>"
+ html_body += ""
+ html_body += "<div id=\"wrap\">"
+ html_body += "<div class=\"container-narrow\">"
+ html_body += "<div class=\"masthead\">"
+ html_body += "<ul class=\"nav nav-pills pull-right\">"
+ html_body += "<li class=\"\"><a href=\"https://dawn.codesake.com\">Home</a></li>"
+ html_body += "<li class=\"active\"><a href=\"https://github.com/codesake/codesake-dawn\">Github repo</a></li>"
+ html_body += "</ul>"
+ html_body += "<h3 class=\"muted\">Codesake::Dawn</h3>"
+ html_body += "</div>"
+ html_body += "<h1>Security code review results for \"#{File.basename(@engine.target)}\"</h1>"
+ html_body += "<hr />"
+ html_body += "<h2>Scan detail</h2>"
+ html_body += "<div class=\"row\">"
+ html_body += "<p>The scan was last executed #{@engine.scan_start.strftime("%d %b %Y - %T")} and Codesake::Dawn founds #{@engine.count_vulnerabilities} vulnerabilities</p>"
+ html_body += "</div>"
+
+
+ html_body += "<hr />"
+ html_body += "<h2>Scan details</h2>"
+ html_body += "<table class=\"table-striped table-bordered table\">"
+ html_body += "<thead><tr><td>Key</td><td>Value</td></tr></thead>"
+ html_body += "<tbody>"
+ html_body += "<tr><td>Dawn version</td><td>#{Codesake::Dawn::VERSION}</td></tr>" unless Codesake::Dawn::RELEASE == "(development)"
+ html_body += "<tr><td>Dawn development version</td><td>#{Codesake::Dawn::VERSION}</td></tr>" if Codesake::Dawn::RELEASE == "(development)"
+ html_body += "<tr><td>Scan duration</td><td>#{@engine.scan_time.round(3)} sec</td></tr>"
+ html_body += "<tr><td>Target</td><td>#{@engine.target}</td></tr>"
+ html_body += "<tr><td>MVC detected framework</td><td>#{@engine.name} v#{@engine.get_mvc_version}</td></tr>" unless @engine.name == "Gemfile.lock"
+ html_body += "<tr><td>MVC detected framework</td><td>#{@engine.force} v#{@engine.get_mvc_version}</td></tr>" if @engine.name == "Gemfile.lock"
+ if @ret
+ html_body += "<tr><td>Applied checks</td><td>#{@engine.applied_checks} security checks</td></tr>"
+ html_body += "<tr><td>Skipped checks</td><td>#{@engine.skipped_checks} security checks</td></tr>"
+ else
+ html_body += "<tr><td>Applied checks</td><td>No security checks in the knowledge base</td></tr>"
+ end
+
+ html_body+="<tr><td>Vulnerabilities found</td><td>#{@engine.count_vulnerabilities}</td></tr>"
+ html_body+="<tr><td>Mitigated issues found</td><td>#{@engine.mitigated_issues.count}</td></tr>"
+ html_body+="<tr><td>Reflected XSS</td><td>#{@engine.reflected_xss.count}</td></tr>"
+ html_body += "</tbody>"
+ html_body += "</table>"
+
+
+
+ if @engine.count_vulnerabilities > 0
+ html_body += "<hr />"
+ html_body += "<h2>Vulnerabilities found</h2> "
+ html_body += "<table class=\"table-striped table-bordered table\">"
+ html_body += "<thead><tr><td>Name</td><td>CVSS score</td><td>Description</td><td>Remediation</td></tr></thead>"
+
+ @engine.vulnerabilities.each do |vuln|
+ html_body += "<tr><td><a href=\"#{vuln[:cve_link]}\">#{vuln[:name]}</a></td><td>#{vuln[:cvss_score]}</td><td>#{vuln[:message]}</td><td>#{vuln[:remediation]}</td></tr>"
+ end
+ html_body += "</tbody>"
+ html_body += "</table>"
+ end
+ html_body += "<div id=\"push\"></div>"
+ html_body += "<div id=\"footer\">"
+ html_body += "<div class=\"container\">"
+ html_body += "<p class=\"muted credit\">&copy; <a href=\"http://dawn.codesake.com\">Codesake::Dawn</a> &mdash; #{Time.now.strftime("%Y")} &mdash; engine v#{Codesake::Dawn::VERSION} (#{Codesake::Dawn::RELEASE})</p>"
+ html_body += "</div>"
+ html_body +="</div>"
+ html_body += "</div>"
+ html_body += "</div>"
+
+ html_body += "</body>"
+ html_body += "</html>"
+
+
+ html = html_head + html_body
+
+ write(html)
+ true
+ end
+
def ascii_tabular_report
# 0_First table: executive summary
@@ -84,6 +180,8 @@ def ascii_tabular_report
table = Terminal::Table.new :title=>"Mitigated issues", :headings=>['Issue', 'Description', 'Evidences'], :rows=>rows
puts table
end
+
+ true
end
@@ -119,8 +217,9 @@ def json_report
result[:reflected_xss] << "request parameter \"#{r[:sink_source]}\""
end
- puts result.to_json
- end
+ write(result.to_json)
+ true
+ end
def ascii_plain_report
@@ -166,6 +265,8 @@ def ascii_plain_report
end
end
end
+
+ true
end
end
end
Oops, something went wrong.

0 comments on commit 9634185

Please sign in to comment.