owasp-glue 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +27 -0
  3. data/FEATURES +19 -0
  4. data/README.md +117 -0
  5. data/bin/glue +67 -0
  6. data/lib/glue.rb +317 -0
  7. data/lib/glue/event.rb +14 -0
  8. data/lib/glue/filters.rb +41 -0
  9. data/lib/glue/filters/base_filter.rb +19 -0
  10. data/lib/glue/filters/jira_one_time_filter.rb +57 -0
  11. data/lib/glue/filters/remove_all_filter.rb +16 -0
  12. data/lib/glue/filters/zap_consdensing_filter.rb +76 -0
  13. data/lib/glue/finding.rb +52 -0
  14. data/lib/glue/mounters.rb +55 -0
  15. data/lib/glue/mounters/base_mounter.rb +31 -0
  16. data/lib/glue/mounters/docker_mounter.rb +44 -0
  17. data/lib/glue/mounters/filesystem_mounter.rb +20 -0
  18. data/lib/glue/mounters/git_mounter.rb +52 -0
  19. data/lib/glue/mounters/iso_mounter.rb +42 -0
  20. data/lib/glue/mounters/url_mounter.rb +28 -0
  21. data/lib/glue/options.rb +269 -0
  22. data/lib/glue/reporters.rb +50 -0
  23. data/lib/glue/reporters/base_reporter.rb +21 -0
  24. data/lib/glue/reporters/csv_reporter.rb +19 -0
  25. data/lib/glue/reporters/jira_reporter.rb +59 -0
  26. data/lib/glue/reporters/json_reporter.rb +20 -0
  27. data/lib/glue/reporters/text_reporter.rb +19 -0
  28. data/lib/glue/scanner.rb +28 -0
  29. data/lib/glue/tasks.rb +124 -0
  30. data/lib/glue/tasks/av.rb +42 -0
  31. data/lib/glue/tasks/base_task.rb +80 -0
  32. data/lib/glue/tasks/brakeman.rb +58 -0
  33. data/lib/glue/tasks/bundle-audit.rb +95 -0
  34. data/lib/glue/tasks/checkmarx.rb +60 -0
  35. data/lib/glue/tasks/dawnscanner.rb +55 -0
  36. data/lib/glue/tasks/eslint.rb +69 -0
  37. data/lib/glue/tasks/fim.rb +60 -0
  38. data/lib/glue/tasks/findsecbugs.rb +90 -0
  39. data/lib/glue/tasks/npm.rb +58 -0
  40. data/lib/glue/tasks/nsp.rb +65 -0
  41. data/lib/glue/tasks/owasp-dep-check.rb +117 -0
  42. data/lib/glue/tasks/patterns.json +394 -0
  43. data/lib/glue/tasks/pmd.rb +63 -0
  44. data/lib/glue/tasks/retirejs.rb +107 -0
  45. data/lib/glue/tasks/scanjs-eslintrc +106 -0
  46. data/lib/glue/tasks/scanjs.rb +31 -0
  47. data/lib/glue/tasks/sfl.rb +67 -0
  48. data/lib/glue/tasks/snyk.rb +81 -0
  49. data/lib/glue/tasks/test.rb +47 -0
  50. data/lib/glue/tasks/zap.rb +99 -0
  51. data/lib/glue/tracker.rb +47 -0
  52. data/lib/glue/util.rb +36 -0
  53. data/lib/glue/version.rb +3 -0
  54. metadata +294 -0
@@ -0,0 +1,60 @@
1
+ require 'glue/tasks/base_task'
2
+ require 'glue/util'
3
+ require 'nokogiri'
4
+
5
+ class Glue::Checkmarx < Glue::BaseTask
6
+
7
+ # Glue::Tasks.add self
8
+ include Glue::Util
9
+
10
+ def initialize(trigger, tracker)
11
+ super(trigger, tracker)
12
+ @name = "Checkmarx"
13
+ @description = "CxSAST"
14
+ @stage = :code
15
+ @labels << "code"
16
+ end
17
+
18
+ def run
19
+ rootpath = @trigger.path
20
+ runsystem(true, "runCxConsole.sh", "scan", "-v",
21
+ "-CxUser", "#{@tracker.options[:checkmarx_user]}",
22
+ "-CxPassword", "#{@tracker.options[:checkmarx_password]}",
23
+ "-CxServer", "#{@tracker.options[:checkmarx_server]}",
24
+ "-LocationType", "folder",
25
+ "-LocationPath", "#{rootpath}",
26
+ "-ProjectName", "#{@tracker.options[:checkmarx_project]}",
27
+ "-ReportXML", "#{rootpath}checkmarx_results.xml",
28
+ "-Log", "#{@tracker.options[:checkmarx_log]}"
29
+ )
30
+ @results = Nokogiri::XML(File.read("#{rootpath}checkmarx_results.xml")).xpath '//Result'
31
+ end
32
+
33
+ def analyze
34
+ begin
35
+ @results.each do |result|
36
+ description = result.parent.attributes['name'].value.gsub('_', ' ')
37
+ detail = result.attributes['DeepLink'].value
38
+ source = { :scanner => @name, :file => result.attributes['FileName'].value, :line => result.attributes['Line'].value.to_i, :code => result.at_xpath('Path/PathNode/Snippet/Line/Code').text }
39
+ sev = severity(result.parent.attributes['Severity'].value)
40
+ fprint = fingerprint("#{description}#{source}#{sev}")
41
+
42
+ report description, detail, source, sev, fprint
43
+ end
44
+ rescue Exception => e
45
+ Glue.warn e.message
46
+ Glue.warn e.backtrace
47
+ end
48
+ end
49
+
50
+ def supported?
51
+ supported=runsystem(true, "runCxConsole.sh", "--help")
52
+ if supported =~ /command not found/
53
+ Glue.notify "Install CxConsolePlugin"
54
+ return false
55
+ else
56
+ return true
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,55 @@
1
+ require 'glue/tasks/base_task'
2
+ require 'glue/util'
3
+ require 'tempfile'
4
+
5
+ class Glue::DawnScanner < Glue::BaseTask
6
+
7
+ Glue::Tasks.add self
8
+ include Glue::Util
9
+
10
+ def initialize(trigger, tracker)
11
+ super(trigger, tracker)
12
+ @name = "DawnScanner"
13
+ @description = "DawnScanner ruby analyzer"
14
+ @stage = :code
15
+ @labels << "code"
16
+ end
17
+
18
+ def run
19
+ Dir.chdir("#{@trigger.path}") do
20
+ @results_file = Tempfile.new(['dawnresults', 'xml'])
21
+ runsystem(true, "dawn", "-F", "#{@results_file.path}", "-j", ".")
22
+ @results = JSON.parse(File.read("#{@results_file.path}"))['vulnerabilities']
23
+ end
24
+ end
25
+
26
+ def analyze
27
+ begin
28
+ @results.each do |result|
29
+ description = result['name'].gsub('\n',' ')
30
+ detail = "#{result['message']}\n#{result['remediation']}\n#{result['cve_link']}"
31
+ source = {:scanner => @name, :file => nil, :line => nil, :code => nil}
32
+ sev = severity(result['severity'])
33
+ fprint = fingerprint("#{description}#{detail}#{source}#{sev}")
34
+
35
+ report description, detail, source, sev, fprint
36
+ end
37
+ rescue Exception => e
38
+ Glue.warn e.message
39
+ Glue.warn e.backtrace
40
+ ensure
41
+ File.unlink @results_file
42
+ end
43
+ end
44
+
45
+ def supported?
46
+ supported=runsystem(true, "dawn", "--version")
47
+ if supported =~ /command not found/
48
+ Glue.notify "Install dawnscanner: 'gem install dawnscanner'"
49
+ return false
50
+ else
51
+ return true
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,69 @@
1
+ require 'glue/tasks/base_task'
2
+ require 'json'
3
+ require 'glue/util'
4
+
5
+ class Glue::ESLint < Glue::BaseTask
6
+
7
+ Glue::Tasks.add self
8
+ include Glue::Util
9
+
10
+ def initialize(trigger, tracker)
11
+ super(trigger,tracker)
12
+ @name = "ESLint/ScanJS"
13
+ @description = "Source analysis for JavaScript"
14
+ @stage = :code
15
+ @labels << "code" << "javascript"
16
+ end
17
+
18
+ def run
19
+ rootpath = @trigger.path
20
+ currentpath = File.expand_path File.dirname(__FILE__)
21
+ Glue.debug "ESLint Config Path: #{currentpath}"
22
+ @result = `eslint -c #{currentpath}/scanjs-eslintrc --no-color --quiet --format json #{rootpath}`
23
+ end
24
+
25
+ def analyze
26
+ # puts @result
27
+ begin
28
+ parsed = JSON.parse(@result)
29
+ parsed.each do |result|
30
+ findings = {}
31
+ prints = []
32
+ messages = []
33
+ result['messages'].each do |msg|
34
+ message = msg['message']
35
+ findings[message] = {} if findings[message].nil?
36
+ findings[message][:detail] = msg['ruleId']
37
+ if messages.include?(message)
38
+ findings[message][:source] = "#{findings[message][:source]},#{msg['line']}" unless findings[message][:source].include?(",#{msg['line']}")
39
+ else
40
+ findings[message][:source] = "#{result['filePath']} Line: #{msg['line']}"
41
+ messages << message
42
+ end
43
+ findings[message][:severity] = severity(msg['severity'].to_s)
44
+ end
45
+ findings.each do |key, value|
46
+ print = fingerprint("#{key}#{value[:detail]}#{value[:source]}#{value[:sev]}")
47
+ unless prints.include?(print)
48
+ prints << print
49
+ report key, value[:detail], value[:source], value[:severity], print
50
+ end
51
+ end
52
+ end
53
+ rescue Exception => e
54
+ Glue.warn e.message
55
+ Glue.warn e.backtrace
56
+ end
57
+ end
58
+
59
+ def supported?
60
+ supported=runsystem(true, "eslint", "-c", "~/.scanjs-eslintrc")
61
+ if supported =~ /command not found/
62
+ Glue.notify "Install eslint and the scanjs .eslintrc"
63
+ return false
64
+ else
65
+ return true
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,60 @@
1
+ # https://github.com/jessek/hashdeep/releases/tag/release-4.4
2
+
3
+ require 'glue/tasks/base_task'
4
+ require 'open3'
5
+
6
+ class Glue::FIM < Glue::BaseTask
7
+
8
+ Glue::Tasks.add self
9
+
10
+ def initialize(trigger, tracker)
11
+ super(trigger,tracker)
12
+ @name = "FIM"
13
+ @description = "File integrity monitor"
14
+ @stage = :file
15
+ @result = ''
16
+ @labels << "filesystem"
17
+ end
18
+
19
+ def run
20
+ rootpath = @trigger.path
21
+ if File.exists?("/area81/tmp/#{rootpath}/filehash")
22
+ Glue.notify "File Hashes found, comparing to file system"
23
+ cmd="hashdeep -j99 -r -a -vv -k /area81/tmp/#{rootpath}/filehash #{rootpath}"
24
+
25
+ # Ugly stdout parsing
26
+ r=/(.*): No match/
27
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
28
+ while line = stdout.gets
29
+ if line.match r
30
+ @result << line
31
+ end
32
+ end
33
+ end
34
+ else
35
+ Glue.notify "No existing baseline - generating initial hashes"
36
+ cmd="mkdir -p /area81/tmp/#{rootpath}; hashdeep -j99 -r #{rootpath} > /area81/tmp/#{rootpath}/filehash"
37
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
38
+ while line = stdout.gets
39
+ puts "."
40
+ end
41
+ end
42
+ @result = ''
43
+ end
44
+ end
45
+
46
+ def analyze
47
+ list = @result.split(/\n/)
48
+ list.each do |v|
49
+ # v.slice! installdir
50
+ Glue.notify v
51
+ report "File changed.", v, @name, :low
52
+ end
53
+ end
54
+
55
+ def supported?
56
+ # In future, verify tool is available.
57
+ return true
58
+ end
59
+
60
+ end
@@ -0,0 +1,90 @@
1
+ require 'glue/tasks/base_task'
2
+ require 'glue/util'
3
+ require 'nokogiri'
4
+ require 'tempfile'
5
+ require 'mkmf'
6
+
7
+ MakeMakefile::Logging.instance_variable_set(:@logfile, File::NULL)
8
+
9
+ class Glue::FindSecurityBugs < Glue::BaseTask
10
+
11
+ Glue::Tasks.add self
12
+ include Glue::Util
13
+
14
+ def initialize(trigger, tracker)
15
+ super(trigger, tracker)
16
+ @name = "FindSecurityBugs"
17
+ @description = "FindSecurityBugs plugin for FindBugs"
18
+ @stage = :code
19
+ @labels << "code"
20
+ end
21
+
22
+ def run
23
+ @results_file = Tempfile.new(['findsecbugs','xml'])
24
+
25
+ unless File.exist?("#{@trigger.path}/.git/config")
26
+ Dir.chdir(@trigger.path) do
27
+ runsystem(true, "git", "init")
28
+ runsystem(true, "git", "add", "*")
29
+ runsystem(true, "git", "commit", "-am", "fake commit for mvn compile")
30
+ end
31
+ end
32
+
33
+ directories_with?('pom.xml').each do |dir|
34
+ Dir.chdir(dir) do
35
+ runsystem(true, "mvn", "compile", "-fn")
36
+ end
37
+ end
38
+
39
+ Dir.chdir(@tracker.options[:findsecbugs_path]) do
40
+ runsystem(true, "/bin/sh", "#{@tracker.options[:findsecbugs_path]}/findsecbugs.sh", "-effort:max", "-quiet", "-xml:withMessages", "-output", "#{@results_file.path}", "#{@trigger.path}")
41
+ @results = Nokogiri::XML(File.read(@results_file)).xpath '//BugInstance'
42
+ end
43
+ end
44
+
45
+ def analyze
46
+ begin
47
+ @results.each do |result|
48
+ description = result.xpath('ShortMessage').text
49
+ bug_type = result.attributes['type'].value
50
+ detail = "Class: #{result.at_xpath('Method').attributes['classname'].value}, Method: #{result.at_xpath('Method').attributes['name'].value}\n#{result.xpath('LongMessage').text}\nhttps://find-sec-bugs.github.io/bugs.htm##{bug_type}"
51
+
52
+ file = result.at_xpath('SourceLine').attributes['sourcepath'].value
53
+ trigger_path = Pathname.new(@trigger.path)
54
+ real_path = nil
55
+ trigger_path.find {|path| real_path = path if path.fnmatch "*/#{file}"}
56
+ file = real_path.relative_path_from(trigger_path).to_s unless real_path.nil?
57
+
58
+ line = result.at_xpath('SourceLine[@primary="true"]').attributes['start'].value
59
+ code = "#{result.at_xpath('String').attributes['value'].value}"
60
+ source = {:scanner => @name, :file => file, :line => line, :code => code}
61
+ sev = result.attributes['priority'].value
62
+ fprint = fingerprint("#{description}#{detail}#{source}")
63
+
64
+ report description, detail, source, sev, fprint
65
+ end
66
+ rescue Exception => e
67
+ Glue.warn e.message
68
+ Glue.warn e.backtrace
69
+ ensure
70
+ File.unlink @results_file
71
+ end
72
+ end
73
+
74
+ def supported?
75
+ unless find_executable0('mvn') and File.exist?("#{@trigger.path}/pom.xml")
76
+ Glue.notify "FindSecurityBugs support requires maven and pom.xml"
77
+ Glue.notify "Please install maven somewhere in your PATH and include a valid pom.xml in the project root"
78
+ return false
79
+ end
80
+
81
+ unless @tracker.options.has_key?(:findsecbugs_path) and File.exist?("#{@tracker.options[:findsecbugs_path]}/findsecbugs.sh")
82
+ Glue.notify "#{@tracker.options[:findsecbugs_path]}"
83
+ Glue.notify "Download and unpack the latest findsecbugs-cli release: https://github.com/find-sec-bugs/find-sec-bugs/releases"
84
+ return false
85
+ else
86
+ return true
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,58 @@
1
+ require 'glue/tasks/base_task'
2
+ require 'glue/util'
3
+ require 'find'
4
+ require 'pry'
5
+
6
+ class Glue::Npm < Glue::BaseTask
7
+
8
+ Glue::Tasks.add self
9
+ include Glue::Util
10
+
11
+ def initialize(trigger, tracker)
12
+ super(trigger, tracker)
13
+ @name = "NPM"
14
+ @description = "Node Package Manager"
15
+ @stage = :file
16
+ @labels << "file" << "javascript"
17
+ @results = []
18
+ end
19
+
20
+ def run
21
+ exclude_dirs = ['node_modules','bower_components']
22
+ exclude_dirs = exclude_dirs.concat(@tracker.options[:exclude_dirs]).uniq if @tracker.options[:exclude_dirs]
23
+ directories_with?('package.json', exclude_dirs).each do |dir|
24
+ Glue.notify "#{@name} scanning: #{dir}"
25
+ Dir.chdir(dir) do
26
+ if @tracker.options.has_key?(:npm_registry)
27
+ registry = "--registry #{@tracker.options[:npm_registry]}"
28
+ else
29
+ registry = nil
30
+ end
31
+ @command = "npm install -q --ignore-scripts #{registry}"
32
+ @results << runsystem(true, @command)
33
+ end
34
+ end
35
+ end
36
+
37
+ def analyze
38
+ begin
39
+ if @results.include? false
40
+ Glue.warn 'Error installing javascript dependencies with #{@command}'
41
+ end
42
+ rescue Exception => e
43
+ Glue.warn e.message
44
+ Glue.warn e.backtrace
45
+ end
46
+ end
47
+
48
+ def supported?
49
+ supported = find_executable0('npm')
50
+ unless supported
51
+ Glue.notify "Install npm: https://nodejs.org/en/download/"
52
+ return false
53
+ else
54
+ return true
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,65 @@
1
+ require 'glue/tasks/base_task'
2
+ require 'glue/util'
3
+
4
+ class Glue::NodeSecurityProject < Glue::BaseTask
5
+
6
+ Glue::Tasks.add self
7
+ include Glue::Util
8
+
9
+ def initialize(trigger, tracker)
10
+ super(trigger, tracker)
11
+ @name = "NodeSecurityProject"
12
+ @description = "Node Security Project"
13
+ @stage = :code
14
+ @labels << "code"
15
+ @results = []
16
+ end
17
+
18
+ def run
19
+ exclude_dirs = ['node_modules','bower_components']
20
+ exclude_dirs = exclude_dirs.concat(@tracker.options[:exclude_dirs]).uniq if @tracker.options[:exclude_dirs]
21
+ directories_with?('package.json', exclude_dirs).each do |dir|
22
+ Glue.notify "#{@name} scanning: #{dir}"
23
+ Dir.chdir(dir) do
24
+ res = runsystem(true, "nsp", "check", "--output", "json")
25
+ @results << JSON.parse(res)
26
+ end
27
+ end
28
+ end
29
+
30
+ def analyze
31
+ begin
32
+ @results.each do |dir_result|
33
+ # This block iterates through each package name found and selects the unique nsp advisories
34
+ # regardless of version, and builds a Glue finding hash for each unique package/advisory combo.
35
+ dir_result.uniq {|finding| finding['module']}.each do |package|
36
+ dir_result.select {|f| f['module'] == package['module']}.uniq {|m| m['advisory']}.each do |unique_finding|
37
+ description = "#{unique_finding['module']} - #{unique_finding['title']}"
38
+ detail = "Upgrade to versions: #{unique_finding['patched_versions']}\n#{unique_finding['advisory']}"
39
+ source = {
40
+ :scanner => 'NodeSecurityProject',
41
+ :file => "#{unique_finding['module']} - #{unique_finding['vulnerable_versions']}",
42
+ :line => nil,
43
+ :code => nil
44
+ }
45
+ report description, detail, source, 'medium', fingerprint("#{description}#{detail}#{source}")
46
+ end
47
+ end
48
+ end
49
+ rescue Exception => e
50
+ Glue.warn e.message
51
+ Glue.warn e.backtrace
52
+ end
53
+ end
54
+
55
+ def supported?
56
+ supported=runsystem(true, "nsp", "--version")
57
+ if supported =~ /command not found/
58
+ Glue.notify "Install nodesecurity: 'npm install -g nsp'"
59
+ return false
60
+ else
61
+ return true
62
+ end
63
+ end
64
+
65
+ end