odle 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/odle +31 -0
- data/lib/model/data.rb +18 -0
- data/lib/odle.rb +11 -0
- data/lib/parsers/burp.rb +54 -0
- data/lib/parsers/msfv5.rb +30 -0
- data/lib/parsers/nessus.rb +48 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d1872753a818f50f6e296e552c725cbb501d6d8f
|
4
|
+
data.tar.gz: f0f76bb273a5a1e3c08d2ac28d3c0a4c5f4e5f18
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3883cb8a3cad9fc64f347e3a90ce95bbcf4ff587cf78a2e9fa7557cc96402dcc3448c4cdf5d83b40a278f85c23b188a28d472f045abc862827dcf22b925e2006
|
7
|
+
data.tar.gz: 818aeceb1ad25ca6ae1f5e274389414f9b68d14e5f1807c27f4c21bc7efc889109d89773136ca2ebe26d5f4d05136411407b4481de00b377b1024c2e96cb1cd2
|
data/bin/odle
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'odle'
|
4
|
+
|
5
|
+
# data flags are required
|
6
|
+
flags = ARGV.shift
|
7
|
+
|
8
|
+
unless flags
|
9
|
+
puts "[!] A data type is required e.g.\n odle --burp \n\n Available types:"#+list_types()
|
10
|
+
exit(0)
|
11
|
+
end
|
12
|
+
|
13
|
+
# flags come in the form --type or --type,arg1=val1,arg2=val2
|
14
|
+
if flags =~ /,/
|
15
|
+
# complicated flags, not implemented yet
|
16
|
+
all = flags.gsub("--","").split(",")
|
17
|
+
|
18
|
+
type = all[0]
|
19
|
+
else
|
20
|
+
type = flags.gsub("--","")
|
21
|
+
end
|
22
|
+
|
23
|
+
if type.downcase == "burp"
|
24
|
+
puts Burp.new().parse(ARGF.read,"0")
|
25
|
+
elsif type.downcase == "nessus"
|
26
|
+
puts Nessus.new().parse(ARGF.read,"0")
|
27
|
+
elsif type.downcase == "msf"
|
28
|
+
puts Metasploit.new().parse(ARGF.read,"0")
|
29
|
+
else
|
30
|
+
puts "[!] Unknown data type \n\n Available types:"#+list_types()
|
31
|
+
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,: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.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
|
data/lib/parsers/burp.rb
ADDED
@@ -0,0 +1,54 @@
|
|
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
|
+
finding.overview = issue.css('issueBackground').text.to_s()+issue.css('issueDetail').text.to_s()
|
17
|
+
finding.remediation = issue.css('remediationBackground').text.to_s()
|
18
|
+
|
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 = "#{ip} #{host}"
|
38
|
+
|
39
|
+
finding.affected_hosts = "#{host} (#{ip})"
|
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
|
+
end
|
@@ -0,0 +1,30 @@
|
|
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
|
+
findings << finding.to_hash
|
21
|
+
end
|
22
|
+
vulns[host] = findings
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
#vulns["findings"] = uniq_findings(findings)
|
27
|
+
return vulns.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
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
|
+
if (hostnode["name"] != nil)
|
14
|
+
host = hostnode["name"]
|
15
|
+
end
|
16
|
+
hostnode.css("ReportItem").each do |itemnode|
|
17
|
+
if (itemnode["port"].to_s != "0" && itemnode["severity"] >= threshold)
|
18
|
+
|
19
|
+
# create a temporary finding object
|
20
|
+
finding = Finding.new()
|
21
|
+
finding.title = itemnode['pluginName'].to_s()
|
22
|
+
finding.overview = itemnode.css("description").to_s()
|
23
|
+
finding.remediation = itemnode.css("solution").to_s()
|
24
|
+
|
25
|
+
# can this be inherited from an import properly?
|
26
|
+
finding.type = "Imported"
|
27
|
+
finding.risk = itemnode["severity"]
|
28
|
+
finding.affected_hosts = hostnode["name"]
|
29
|
+
if itemnode.css("plugin_output")
|
30
|
+
finding.notes = hostnode["name"]+" ("+itemnode["protocol"]+ " port " + itemnode["port"]+"):"+itemnode.css("plugin_output").to_s()
|
31
|
+
end
|
32
|
+
|
33
|
+
finding.references = itemnode.css("see_also").to_s
|
34
|
+
finding.id = itemnode['pluginID'].to_s()
|
35
|
+
|
36
|
+
vulns[hostname] << finding.to_hash
|
37
|
+
items << itemnode['pluginID'].to_s()
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# vulns[host] = findings
|
42
|
+
items = []
|
43
|
+
end
|
44
|
+
|
45
|
+
return vulns.to_json
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: odle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Will Vandevanter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-24 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.
|
15
|
+
email: will@silentrobots.com
|
16
|
+
executables:
|
17
|
+
- odle
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/odle
|
22
|
+
- lib/model/data.rb
|
23
|
+
- lib/odle.rb
|
24
|
+
- lib/parsers/burp.rb
|
25
|
+
- lib/parsers/msfv5.rb
|
26
|
+
- lib/parsers/nessus.rb
|
27
|
+
homepage: http://rubygems.org/gems/odle
|
28
|
+
licenses:
|
29
|
+
- BSD-3-Clause-Attribution
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
- lib/parsers
|
36
|
+
- lib/model
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 2.6.12
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: odle
|
53
|
+
test_files: []
|