odle-m 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 800485a35d15ab752e25eb7674789d55d5088b426b81d8ade19e9208d9ad5f96
4
+ data.tar.gz: 5a6c62f31f4b151915d0956664af7266d8f027ed52343b26109936f3f449013d
5
+ SHA512:
6
+ metadata.gz: bdd83324fd4da125739552100bcb71711aec892ac7aef948d8a3817075090eaea9921adb7fccf3db38efd0761d7c6b4dc554dd294bc59e2c593555ca5339cd1d
7
+ data.tar.gz: 63fd19799c46cc92643b877454104cf2e1eb21b509bc7bc3a4820bf2db00165c6ca8bc337baf115b54a32dcf4e597a3ea666b57bce1299ff8f2cd47ab48d78e7
data/bin/odle-m ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ require 'odle-m'
3
+
4
+ def list_types()
5
+ return ["","--burp","--burp2","--nessus","--msf","--nmap"].join("\n")
6
+ end
7
+
8
+ # data flags are required
9
+ flags = ARGV.shift
10
+
11
+ unless flags
12
+ puts "[!] A data type is required e.g.\n cat MYDATA_FILE | odle --burp \n\n Available types:"+list_types()
13
+ exit(0)
14
+ end
15
+
16
+ # flags come in the form --type or --type,arg1=val1,arg2=val2
17
+ if flags =~ /,/
18
+ # complicated flags, not implemented yet
19
+ all = flags.gsub("--","").split(",")
20
+
21
+ type = all[0]
22
+ else
23
+ type = flags.gsub("--","")
24
+ end
25
+
26
+ if type.downcase == "burp"
27
+ puts Burp.new().parse(ARGF.read,"0")
28
+ elsif type.downcase == "burp2"
29
+ puts Burp2.new().parse(ARGF.read,"0")
30
+ elsif type.downcase == "nessus"
31
+ puts Nessus.new().parse(ARGF.read,"0")
32
+ elsif type.downcase == "msf"
33
+ puts Metasploit.new().parse(ARGF.read,"0")
34
+ elsif type.downcase == "nmap"
35
+ puts Nmap.new().parse(ARGF.read,"0")
36
+ else
37
+ puts "[!] Unknown data type \n\n Available types:"+list_types()
38
+ end
data/lib/model/data.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ class Host
4
+ attr_accessor :ip, :port
5
+ end
6
+
7
+ class Finding
8
+ attr_accessor :title,:id,:description,:effort,:type,:dread_total,:overview,:poc,:remediation,:notes,:assessment_type,:references,:risk,:damage,:reproducability,:exploitability,:affected_users,:discoverability,:av,:ac,:au,:c,:i,:a,:e,:rl,:rc,:cdp,:td,:cr,:ir,:ar,:cvss_base,:cvss_impact,:cvss_exploitability,:cvss_temporal,:cvss_environmental,:cvss_modified_impact,:cvss_total,:ease,:c2_vs,:attack_vector,:attack_complexity,:privileges_required,:user_interaction,:scope_cvss,:confidentiality,:integrity,:availability,:exploit_maturity,:remeditation_level,:report_confidence,:confidentiality_requirement,:integrity_requirement,:availability_requirement,:mod_attack_vector,:mod_attack_complexity,:mod_privileges_required,:mod_user_interaction,:mod_scope,:mod_confidentiality,:mod_integrity,:mod_availability,:cvss_base_score,:cvss_impact_score,:cvss_mod_impact_score,:c3_vs,:severity,:likelihood,:severity_rationale,:likelihood_rationale,:affected_hosts
9
+
10
+ def to_hash
11
+ hash = {}
12
+ self.instance_variables.each do |var|
13
+ #p var.to_s.gsub("@","")
14
+ hash[var.to_s.gsub("@","").gsub("\"","")] = self.instance_variable_get var
15
+ end
16
+ return hash
17
+ end
18
+ end
data/lib/odle-m.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'nokogiri'
2
+ require 'json'
3
+
4
+ module Odle
5
+ # load the parsers
6
+ Dir[File.join(File.dirname(__FILE__), "parsers", "*.rb")].each { |lib| require lib }
7
+
8
+ # load the data model
9
+ Dir[File.join(File.dirname(__FILE__), "model", "*.rb")].each { |lib| require lib }
10
+
11
+ end
@@ -0,0 +1,57 @@
1
+ require 'json'
2
+
3
+ class Burp
4
+
5
+ def parse(xml,threshold)
6
+ vulns = Hash.new
7
+ findings = Array.new
8
+ vulns["findings"] = []
9
+
10
+ doc = Nokogiri::XML(xml)
11
+ doc.css('//issues/issue').each do |issue|
12
+ if issue.css('severity').text
13
+ # create a temporary finding object
14
+ finding = Finding.new()
15
+ finding.title = issue.css('name').text.to_s()
16
+ puts "#{finding.title}"
17
+ finding.overview = issue.css('issueBackground').text.to_s()+issue.css('issueDetail').text.to_s()
18
+ finding.remediation = issue.css('remediationBackground').text.to_s() + issue.css('remediationDetail').text.to_s()
19
+ finding.references=issue.css('references').text.to_s() + issue.css('vulnerabilityClassifications').text.to_s()
20
+
21
+ if issue.css('severity').text == 'Low'
22
+ finding.risk = 1
23
+ elsif issue.css('severity').text == 'Medium'
24
+ finding.risk = 2
25
+ elsif issue.css('severity').text =='High'
26
+ finding.risk = 3
27
+ else
28
+ finding.risk = 1
29
+ end
30
+
31
+
32
+ finding.type = "Web Application"
33
+
34
+ findings << finding
35
+
36
+ host = issue.css('host').text
37
+ ip = issue.css('host').attr('ip')
38
+ id = issue.css('type').text
39
+ hostname = "#{host}"
40
+
41
+ finding.affected_hosts = "#{host}" + issue.css('location').text.to_s()
42
+
43
+ finding.id = id
44
+ if vulns[hostname]
45
+ vulns[hostname] << finding.to_hash
46
+ else
47
+ vulns[hostname] = []
48
+ vulns[hostname] << finding.to_hash
49
+ end
50
+ end
51
+ end
52
+
53
+ #vulns["findings"] = uniq_findings(findings)
54
+ return vulns.to_json
55
+ end
56
+
57
+ end
@@ -0,0 +1,55 @@
1
+ require 'json'
2
+
3
+ class Burp2
4
+
5
+ def parse(xml,threshold)
6
+ vulns = Hash.new
7
+ findings = Array.new
8
+ vulns["findings"] = []
9
+
10
+ doc = Nokogiri::XML(xml)
11
+ doc.css('//issues/issue').each do |issue|
12
+ if issue.css('severity').text
13
+ # create a temporary finding object
14
+ finding = Finding.new()
15
+ finding.title = issue.css('name').text.to_s()
16
+ finding.overview = issue.css('issueBackground').text.to_s()+issue.css('issueDetail').text.to_s()
17
+ finding.remediation = issue.css('remediationBackground').text.to_s() + issue.css('remediationDetail').text.to_s()
18
+ finding.references=issue.css('references').text.to_s()
19
+ if issue.css('severity').text == 'Low'
20
+ finding.risk = 1
21
+ elsif issue.css('severity').text == 'Medium'
22
+ finding.risk = 2
23
+ elsif issue.css('severity').text =='High'
24
+ finding.risk = 3
25
+ else
26
+ finding.risk = 1
27
+ end
28
+
29
+
30
+ finding.type = "Web Application"
31
+
32
+ findings << finding
33
+
34
+ host = issue.css('host').text
35
+ ip = issue.css('host').attr('ip')
36
+ id = issue.css('type').text
37
+ hostname = "#{host}"
38
+
39
+ finding.affected_hosts = "#{host}" + issue.css('location').text.to_s()
40
+
41
+ finding.id = id
42
+ if vulns[hostname]
43
+ vulns[hostname] << finding.to_hash
44
+ else
45
+ vulns[hostname] = []
46
+ vulns[hostname] << finding.to_hash
47
+ end
48
+ end
49
+ end
50
+
51
+ #vulns["findings"] = uniq_findings(findings)
52
+ return vulns.to_json
53
+ end
54
+
55
+ end
@@ -0,0 +1,32 @@
1
+ require 'json'
2
+
3
+ class Metasploit
4
+
5
+ def parse(xml,threshold)
6
+ vulns = Hash.new
7
+ vulns["findings"] = []
8
+
9
+ doc = Nokogiri::XML(xml)
10
+ doc.css('//hosts/host').each do |hostnode|
11
+ findings = Array.new
12
+
13
+ host = hostnode.css('/name').text.to_s
14
+
15
+ hostnode.css('/vulns/vuln').each do |issue|
16
+ # create a temporary finding object
17
+ finding = Finding.new()
18
+ finding.title = issue.css('name').text.to_s()
19
+ finding.overview = issue.css('info').text.to_s()
20
+ finding.risk = 0 # this needs to be fixed
21
+ finding.remediation = ""
22
+ finding.id = issue.css('id').text.to_s()
23
+ findings << finding.to_hash
24
+ end
25
+ vulns[host] = findings
26
+ end
27
+
28
+ #vulns["findings"] = uniq_findings(findings)
29
+ return vulns.to_json
30
+ end
31
+
32
+ end
@@ -0,0 +1,54 @@
1
+ require 'json'
2
+
3
+ class Nessus
4
+
5
+ def parse(xml,threshold)
6
+ vulns = Hash.new
7
+ findings = Array.new
8
+ items = Array.new
9
+
10
+ doc = Nokogiri::XML(xml)
11
+
12
+ doc.css("//ReportHost").each do |hostnode|
13
+ host = hostnode['name'] unless hostnode['name'].nil?
14
+ host = " " unless host
15
+ vulns[host] = []
16
+
17
+ hostnode.css("ReportItem").each do |itemnode|
18
+
19
+ if (itemnode["port"].to_s != "0" && itemnode["severity"] >= threshold)
20
+
21
+ # create a temporary finding object
22
+ finding = Finding.new()
23
+ finding.title = itemnode['pluginName'].to_s()
24
+ finding.poc = itemnode.css("description").to_s()
25
+ finding.remediation = itemnode.css("solution").to_s()
26
+
27
+ finding.cvss_total = itemnode.css("cvss3_base_score").to_s()
28
+ finding.c3_vs=itemnode.css("cvss3_vector").to_s()
29
+ finding.description = itemnode.css("synopsis").to_s()
30
+
31
+ # can this be inherited from an import properly?
32
+ finding.type = "Imported"
33
+ finding.risk = itemnode["severity"]
34
+ if itemnode.css("plugin_output")
35
+ finding.notes = hostnode["name"]+" ("+itemnode["protocol"]+ " port " + itemnode["port"]+"):"+itemnode.css("plugin_output").to_s()
36
+ finding.affected_hosts = hostnode["name"] + " [" + itemnode["port"] + "/" +itemnode["protocol"] + "]"
37
+ finding.references = itemnode.css("cvss3_vector").to_s() + " " + itemnode.css("see_also").to_s
38
+ end
39
+
40
+ finding.id = itemnode['pluginID'].to_s()
41
+
42
+ vulns[host] << finding.to_hash
43
+ items << itemnode['pluginID'].to_s()
44
+ end
45
+ end
46
+
47
+ # vulns[host] = findings
48
+ items = []
49
+ end
50
+
51
+ return vulns.to_json
52
+ end
53
+
54
+ end
@@ -0,0 +1,70 @@
1
+ require 'json'
2
+
3
+ class Nmap
4
+
5
+ def parse(xml,threshold)
6
+ vulns = Hash.new
7
+ findings = Array.new
8
+ items = Array.new
9
+
10
+ doc = Nokogiri::XML(xml)
11
+
12
+ #p doc
13
+ doc.css("//host").each do |hostnode|
14
+ address = hostnode.css("address")
15
+ host = address.attr("addr")
16
+ host = " " unless host
17
+ vulns[host] = []
18
+ affected_hosts = ""
19
+
20
+ hostnode.css("/hostnames").each do |hname|
21
+ hostname = hname.attr("hostname")
22
+
23
+ hname.traverse do |x|
24
+ if x.values[0]
25
+ if affected_hosts == ""
26
+ affected_hosts = x.values[0]
27
+ else
28
+ affected_hosts = affected_hosts + " " + x.values[0]
29
+ end
30
+ end
31
+ end
32
+
33
+ # finding is one per host
34
+ finding = Finding.new()
35
+ finding.affected_hosts = affected_hosts
36
+ vulns[host] << finding.to_hash
37
+
38
+ # finding is one per open port
39
+ hostnode.css("/ports/port").each do |port|
40
+ proto = port.attr("protocol")
41
+ portid = port.attr("portid")
42
+ state = port.css("/state").attr("state").value
43
+ service = port.css("/service").attr("name").value
44
+
45
+ # iterate the state
46
+ finding = Finding.new()
47
+ finding.affected_hosts = affected_hosts
48
+
49
+ # if a script was run, grab the results
50
+ if port.css("/script").size > 0
51
+ finding.title = "Script Scan:"+port.css("/script").attr("id").value+" [#{state} #{portid} (#{service})]"
52
+ finding.overview = port.css("/script").attr("output").value
53
+ vulns[host] << finding.to_hash
54
+ else
55
+ if state == "open"
56
+ finding.title = "Open port [#{state} #{portid} (#{service})]"
57
+ vulns[host] << finding.to_hash
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+ items = []
65
+ end
66
+
67
+ return vulns.to_json
68
+ end
69
+
70
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: odle-m
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Shyam Ganesh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-11-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An easy to use security data parsing tool. Takes in data from different
14
+ tools and outputs standardized JSON with extra parsing
15
+ email: ''
16
+ executables:
17
+ - odle-m
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/odle-m
22
+ - lib/model/data.rb
23
+ - lib/odle-m.rb
24
+ - lib/parsers/burp.rb
25
+ - lib/parsers/burp2.rb
26
+ - lib/parsers/msfv5.rb
27
+ - lib/parsers/nessus.rb
28
+ - lib/parsers/nmap.rb
29
+ homepage: http://rubygems.org/gems/odle
30
+ licenses:
31
+ - BSD-3-Clause-Attribution
32
+ metadata: {}
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ - lib/parsers
38
+ - lib/model
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubygems_version: 3.1.6
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: odle-m
54
+ test_files: []