nipper_parser 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -2
- data/README.md +6 -7
- data/lib/nipper_parser.rb +57 -9
- data/lib/nipper_parser/parsers/README.md +38 -6
- data/lib/nipper_parser/parsers/filtering_complexity.rb +155 -0
- data/lib/nipper_parser/parsers/parser_utils.rb +10 -4
- data/lib/nipper_parser/parsers/security_audit.rb +13 -9
- data/lib/nipper_parser/parsers/vulnerability_audit.rb +158 -0
- data/lib/nipper_parser/version.rb +1 -1
- metadata +4 -3
- data/lib/nipper_parser/parsers/vulnerabilty_audit.rb +0 -102
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a042f45d32532f487c29dca148378d91aa7e599
|
4
|
+
data.tar.gz: 6403288acfcc080a3e27bac6c0a91ae450b9ed3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb512be1015bfd3c4cab072828b6122cdb9062b76dc127ea8058fd2c97e62743961fd505930890fedcc931d8b1f4f0a5d577806076049927e407be6fb7bc3d40
|
7
|
+
data.tar.gz: 718322087f9b8c07cb6c4ac02f110402c742383447b0b9265880ab8ee6d3cf16df3e22ab2213bd4c9a905f425140c677815363072b13881bcd3c26d46ba36847
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# NipperParser
|
2
|
-
[![
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/nipper_parser.svg)](https://badge.fury.io/rb/nipper_parser)
|
3
3
|
[![Code Climate](https://codeclimate.com/github/KINGSABRI/nipper_parser/badges/gpa.svg)](https://codeclimate.com/github/KINGSABRI/nipper_parser)
|
4
4
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/8c81748967664cc5bb92147581fb6802)](https://www.codacy.com/app/king-sabri/attack-domain?utm_source=github.com&utm_medium=referral&utm_content=KINGSABRI/nipper_parser&utm_campaign=Badge_Grade)
|
5
5
|
[![inch-ci](https://inch-ci.org/github/KINGSABRI/nipper_parser.svg?branch=master)](https://inch-ci.org/github/KINGSABRI/nipper_parser)
|
6
|
-
[![Gem Version](https://badge.fury.io/rb/nipper_parser.svg)](https://badge.fury.io/rb/nipper_parser)
|
7
6
|
|
8
7
|
NipperParser gem is an unofficial parser for [Titania Nipper Studio](https://www.titania.com/products/nipper-studio) XML report.
|
9
8
|
|
@@ -12,21 +11,21 @@ NipperParser gem is an unofficial parser for [Titania Nipper Studio](https://www
|
|
12
11
|
|
13
12
|
| Modules / Sections | Supported |
|
14
13
|
|------------------------|-----------|
|
15
|
-
| Information |
|
16
|
-
| Security Audit |
|
17
|
-
| Vulnerability Audit |
|
14
|
+
| Information | ✓ |
|
15
|
+
| Security Audit | ✓ |
|
16
|
+
| Vulnerability Audit | ✓ |
|
18
17
|
| CIS Benchmarks | |
|
19
18
|
| STIG Compliance | |
|
20
19
|
| SANS Policy Compliance | |
|
21
20
|
| PCI Audit | |
|
22
|
-
| Filtering Complexity |
|
21
|
+
| Filtering Complexity | ✓ |
|
23
22
|
| Configuration Report | |
|
24
23
|
| Raw Configuration | |
|
25
24
|
| Raw Change Tracking | |
|
26
25
|
| Appendix | |
|
27
26
|
|
28
27
|
|
29
|
-
## Installation
|
28
|
+
## Installation
|
30
29
|
|
31
30
|
```ruby
|
32
31
|
gem install nipper_parser
|
data/lib/nipper_parser.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
lib = File.expand_path('..', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
|
4
4
|
require 'nokogiri'
|
5
5
|
require 'nipper_parser/version'
|
6
6
|
require 'nipper_parser/parsers/parser_utils'
|
7
7
|
require 'nipper_parser/parsers/information'
|
8
8
|
require 'nipper_parser/parsers/security_audit'
|
9
|
+
require 'nipper_parser/parsers/vulnerability_audit'
|
10
|
+
require 'nipper_parser/parsers/filtering_complexity'
|
9
11
|
|
10
12
|
module NipperParser
|
11
13
|
|
@@ -36,12 +38,23 @@ module NipperParser
|
|
36
38
|
alias_method :open, :new
|
37
39
|
end
|
38
40
|
|
39
|
-
|
41
|
+
# @!attribute #information for report general information section, it calls [Information] class
|
42
|
+
attr_reader :information
|
43
|
+
# @!attribute #security_audit for security audit section, it calls [SecurityAudit] class
|
44
|
+
attr_reader :security_audit
|
45
|
+
# @!attribute #vulnerability_audit for report vulnerability audit section, it calls [VulnerabilityAudit] class
|
46
|
+
attr_reader :vulnerability_audit
|
47
|
+
# @!attribute #filtering_complexity for report filtering complexity section, it calls [FilteringComplexity] class
|
48
|
+
attr_reader :filtering_complexity
|
49
|
+
|
40
50
|
def initialize(file)
|
41
51
|
config_parsed = Nokogiri::XML(File.open(file))
|
52
|
+
|
42
53
|
# instantiate all parsers
|
43
|
-
@information
|
44
|
-
@security_audit
|
54
|
+
@information = Information.new(config_parsed)
|
55
|
+
@security_audit = SecurityAudit.new(config_parsed)
|
56
|
+
@vulnerability_audit = VulnerabilityAudit.new(config_parsed)
|
57
|
+
@filtering_complexity = FilteringComplexity.new(config_parsed)
|
45
58
|
end
|
46
59
|
end
|
47
60
|
|
@@ -55,13 +68,48 @@ if __FILE__ == $0
|
|
55
68
|
pp nipper_parser.information.title
|
56
69
|
pp nipper_parser.information.author
|
57
70
|
pp nipper_parser.information.date
|
58
|
-
pp nipper_parser.security_audit
|
71
|
+
pp nipper_parser.security_audit.title
|
72
|
+
pp nipper_parser.security_audit.introduction.security_issue_overview
|
59
73
|
pp nipper_parser.security_audit.findings
|
60
|
-
|
61
|
-
pp
|
62
|
-
pp
|
74
|
+
finding = nipper_parser.security_audit.findings[0]
|
75
|
+
pp finding.class
|
76
|
+
pp finding.title
|
77
|
+
pp finding.impact
|
63
78
|
pp nipper_parser.security_audit.conclusions
|
64
79
|
pp nipper_parser.security_audit.conclusions.per_device
|
65
80
|
pp nipper_parser.security_audit.recommendations.list
|
66
81
|
pp nipper_parser.security_audit.mitigation_classification
|
82
|
+
pp nipper_parser.vulnerability_audit.class
|
83
|
+
pp nipper_parser.vulnerability_audit.title
|
84
|
+
pp nipper_parser.vulnerability_audit.introduction
|
85
|
+
pp nipper_parser.vulnerability_audit.introduction.excluded_devices
|
86
|
+
cve = nipper_parser.vulnerability_audit.cves[0]
|
87
|
+
pp cve.title
|
88
|
+
pp cve.rating
|
89
|
+
pp cve.summary
|
90
|
+
pp cve.affected_devices
|
91
|
+
pp cve.vendor_sec_advisories
|
92
|
+
pp cve.references
|
93
|
+
pp nipper_parser.vulnerability_audit.conclusions
|
94
|
+
pp nipper_parser.vulnerability_audit.conclusions.list_critical
|
95
|
+
pp nipper_parser.vulnerability_audit.recommendations
|
96
|
+
pp nipper_parser.filtering_complexity
|
97
|
+
pp nipper_parser.filtering_complexity.title
|
98
|
+
pp nipper_parser.filtering_complexity.introduction
|
99
|
+
pp nipper_parser.filtering_complexity.introduction.devices
|
100
|
+
observations = nipper_parser.filtering_complexity.observations
|
101
|
+
puts "Number of observations: #{observations.size}"
|
102
|
+
observation = observations[2]
|
103
|
+
pp observation.title
|
104
|
+
pp observation.index
|
105
|
+
pp observation.ref
|
106
|
+
pp observation.overview
|
107
|
+
pp observation.affected_devices
|
108
|
+
pp observation.affected_devices[0].title
|
109
|
+
puts
|
110
|
+
pp observation.affected_devices[0].details
|
111
|
+
puts
|
112
|
+
pp observation.affected_devices[0].details_tables[0].title
|
113
|
+
pp observation.affected_devices[0].details_tables[0].tables
|
114
|
+
|
67
115
|
end
|
@@ -41,14 +41,14 @@ experience.
|
|
41
41
|
#### Usage
|
42
42
|
|
43
43
|
```ruby
|
44
|
+
pp security_audit = nipper_parser.security_audit
|
45
|
+
|
44
46
|
# - Introduction
|
45
47
|
pp security_audit.introduction.class
|
46
48
|
pp security_audit.introduction.title
|
47
49
|
pp security_audit.introduction.date
|
48
50
|
pp security_audit.introduction.security_issue_overview
|
49
|
-
|
50
51
|
# - Findings
|
51
|
-
pp security_audit = nipper_parser.security_audit
|
52
52
|
pp security_audit.findings
|
53
53
|
finding = security_audit.findings[0] # Play wit a finding
|
54
54
|
pp finding.class
|
@@ -85,18 +85,33 @@ A report detailing publically known software vulnerabilities in the device firmw
|
|
85
85
|
manufacturer and third-party references.
|
86
86
|
|
87
87
|
**Vulnerability Audit Section Contains:**
|
88
|
-
- Introduction [
|
89
|
-
- CVEs list [
|
90
|
-
- Conclusions [
|
91
|
-
- Recommendations [
|
88
|
+
- Introduction [implemented]
|
89
|
+
- CVEs list [implemented]
|
90
|
+
- Conclusions [implemented]
|
91
|
+
- Recommendations [implemented]
|
92
92
|
|
93
93
|
#### Usage
|
94
94
|
|
95
95
|
```ruby
|
96
|
+
vulnerability_audit = nipper_parser.vulnerability_audit
|
97
|
+
|
96
98
|
# - Introduction
|
99
|
+
pp vulnerability_audit.class
|
100
|
+
pp vulnerability_audit.introduction
|
101
|
+
pp vulnerability_audit.introduction.excluded_devices
|
97
102
|
# - CVEs
|
103
|
+
cve = vulnerability_audit.cves[0]
|
104
|
+
pp cve.title
|
105
|
+
pp cve.rating
|
106
|
+
pp cve.summary
|
107
|
+
pp cve.affected_devices
|
108
|
+
pp cve.vendor_sec_advisories
|
109
|
+
pp cve.references
|
98
110
|
# - Conclusions
|
111
|
+
pp vulnerability_audit.conclusions.class
|
112
|
+
pp vulnerability_audit.conclusions.list_critical
|
99
113
|
# - Recommendations
|
114
|
+
pp vulnerability_audit.recommendations.list
|
100
115
|
```
|
101
116
|
|
102
117
|
### CIS Benchmarks
|
@@ -174,7 +189,24 @@ group recursion and more.
|
|
174
189
|
|
175
190
|
```ruby
|
176
191
|
# - Introduction
|
192
|
+
filtering = nipper_parser.filtering_complexity
|
193
|
+
pp filtering.title
|
194
|
+
pp filtering.introduction
|
195
|
+
pp filtering.introduction.devices
|
196
|
+
|
177
197
|
# - Observations
|
198
|
+
observations = filtering.observations
|
199
|
+
puts "Number of observations: #{observations.size}"
|
200
|
+
observation = observations[0]
|
201
|
+
pp observation.title
|
202
|
+
pp observation.index
|
203
|
+
pp observation.ref
|
204
|
+
pp observation.overview
|
205
|
+
pp observation.affected_devices
|
206
|
+
pp observation.affected_devices[0].title
|
207
|
+
pp observation.affected_devices[0].details
|
208
|
+
pp observation.affected_devices[0].details_tables[0].title
|
209
|
+
pp observation.affected_devices[0].details_tables[0].tables
|
178
210
|
```
|
179
211
|
|
180
212
|
### Configuration Report
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module NipperParser
|
2
|
+
|
3
|
+
# FilteringComplexity parses the 'Filtering Complexity' part.
|
4
|
+
# Filtering Complexity part contains the following sections:
|
5
|
+
# - introduction
|
6
|
+
# - Observations
|
7
|
+
#
|
8
|
+
# @example Basic Usage:
|
9
|
+
# require 'nokogiri'
|
10
|
+
# require 'pp'
|
11
|
+
# config = Nokogiri::XML open(ARGV[0])
|
12
|
+
# vulnerability_audit = NipperParser::FilteringComplexity.new(config)
|
13
|
+
# pp FilteringComplexity.class
|
14
|
+
# pp FilteringComplexity.introduction
|
15
|
+
# pp FilteringComplexity.introduction.excluded_devices
|
16
|
+
# filter = FilteringComplexity.cves[0]
|
17
|
+
#
|
18
|
+
# @param config [Nokogiri::XML] parsed XML
|
19
|
+
# @attr_reader title the report title
|
20
|
+
# @attr_reader config a parsed XML [Nokogiri::XML] object
|
21
|
+
class FilteringComplexity
|
22
|
+
include ParserUtils
|
23
|
+
|
24
|
+
# Skeleton for SecurityAudit parts
|
25
|
+
|
26
|
+
Introduction = Struct.new(
|
27
|
+
:index,
|
28
|
+
:title, :ref, :devices,
|
29
|
+
:security_issue_overview, :rating
|
30
|
+
)
|
31
|
+
|
32
|
+
Observation = Struct.new(
|
33
|
+
:index, :title, :ref, :overview,
|
34
|
+
:affected_devices, :false_positive
|
35
|
+
)
|
36
|
+
|
37
|
+
attr_reader :config, :title
|
38
|
+
|
39
|
+
# @param config [Nokogiri::XML::Document]
|
40
|
+
def initialize(config)
|
41
|
+
part = config.xpath("//report/part[@ref='COMPLEXITY']")
|
42
|
+
@config = part[0].elements
|
43
|
+
@title = part[0].attributes['title'].text
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# Introduction of the Security Audit report
|
48
|
+
def introduction
|
49
|
+
intro = @config[0]
|
50
|
+
attribute = attributes(intro)
|
51
|
+
index = attribute.index
|
52
|
+
title = attribute.title
|
53
|
+
reference = attribute.ref
|
54
|
+
devices = generate_table(intro.elements[1].elements)
|
55
|
+
|
56
|
+
Introduction.new(index, title, reference, devices)
|
57
|
+
end
|
58
|
+
|
59
|
+
# observations parses observations
|
60
|
+
#
|
61
|
+
# @return [Array<Observation>]
|
62
|
+
def observations
|
63
|
+
obs = @config.to_a.clone
|
64
|
+
obs.shift # pop first item, the introduction
|
65
|
+
@observations = obs.map do |observation|
|
66
|
+
|
67
|
+
Observation.new(
|
68
|
+
attributes(observation).index,
|
69
|
+
attributes(observation).title,
|
70
|
+
attributes(observation).ref,
|
71
|
+
observation.elements[0].text.strip, # overview
|
72
|
+
affected_devices(observation), # affected_devices
|
73
|
+
false # observation can be marked as a false positive
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
# List all false positive observations
|
80
|
+
#
|
81
|
+
# @return [Array<Observation>]
|
82
|
+
def false_positive
|
83
|
+
observations.select(&:false_positive)
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
AffectedDevice = Struct.new(
|
88
|
+
:index, :title, :ref,
|
89
|
+
:details, :details_tables
|
90
|
+
)
|
91
|
+
# affected_devices parses affected devices from give Observation object. @see #observations
|
92
|
+
#
|
93
|
+
# @param observation [Nokogiri::XML::Element]
|
94
|
+
# @return [Array<AffectedDevices>]
|
95
|
+
def affected_devices(observation)
|
96
|
+
obs_devices = observation.elements
|
97
|
+
obs_devices.shift # pop first item, the overview
|
98
|
+
|
99
|
+
obs_devices.map do |device|
|
100
|
+
AffectedDevice.new(
|
101
|
+
attributes(device).index, #fixme affected device index should not be same as observation index
|
102
|
+
attributes(device).title,
|
103
|
+
attributes(device).ref,
|
104
|
+
device.elements[0].text, # details
|
105
|
+
details_tables(device) # details tables
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
DetailsTable = Struct.new(
|
111
|
+
:index, :title, :ref,
|
112
|
+
:tables
|
113
|
+
)
|
114
|
+
# details_tables parses tables of affected devices from give device. @see #affected_devices
|
115
|
+
#
|
116
|
+
# @param device [Nokogiri::XML::Element]
|
117
|
+
# @return [Array<AffectedDevices>]
|
118
|
+
def details_tables(device)
|
119
|
+
tables = device.elements
|
120
|
+
tables.shift
|
121
|
+
begin
|
122
|
+
tables.map do |table|
|
123
|
+
DetailsTable.new(
|
124
|
+
attributes(table).index,
|
125
|
+
attributes(table).title,
|
126
|
+
attributes(table).ref,
|
127
|
+
generate_table(table.elements) # tables
|
128
|
+
)
|
129
|
+
end
|
130
|
+
rescue
|
131
|
+
# tables.map do |table|
|
132
|
+
# DetailsTable.new(
|
133
|
+
# nil, nil, nil,
|
134
|
+
# tables.xpath('listitem').map(&:text)
|
135
|
+
# )
|
136
|
+
# end
|
137
|
+
|
138
|
+
tables.xpath('listitem').map(&:text)
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
if __FILE__ == $0
|
149
|
+
require 'nokogiri'
|
150
|
+
require 'pp'
|
151
|
+
config = Nokogiri::XML open(ARGV[0])
|
152
|
+
filter = NipperParser::FilteringComplexity.new(config)
|
153
|
+
pp filter.introduction.class
|
154
|
+
pp filter.introduction.index
|
155
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
|
1
4
|
module NipperParser
|
2
5
|
|
3
6
|
# ParserUtils is a helper module for parsers' quick and dirty operations.
|
@@ -26,13 +29,16 @@ module NipperParser
|
|
26
29
|
end
|
27
30
|
|
28
31
|
Attribute = Struct.new(:index, :title, :ref)
|
29
|
-
# @param attr [Nokogiri::XML::Element]
|
30
|
-
# @return [
|
32
|
+
# @param attr [Nokogiri::XML::Element]
|
33
|
+
# @return [ParserUtils::Attribute]
|
31
34
|
def attributes(attr)
|
35
|
+
require 'pp'
|
36
|
+
# pp caller_locations
|
37
|
+
|
32
38
|
Attribute.new(
|
33
|
-
attr.attributes['index'].text,
|
39
|
+
attr.attributes['index'].text.to_f,
|
34
40
|
attr.attributes['title'].text,
|
35
|
-
attr.attributes['ref'].text
|
41
|
+
attr.attributes['ref'].text,
|
36
42
|
)
|
37
43
|
end
|
38
44
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'date'
|
2
2
|
require_relative 'parser_utils'
|
3
|
+
|
3
4
|
module NipperParser
|
4
5
|
|
5
6
|
# SecurityAudit parses the 'Security Audit' part including all it's sections.
|
@@ -96,10 +97,13 @@ module NipperParser
|
|
96
97
|
)
|
97
98
|
|
98
99
|
attr_reader :config, :title
|
100
|
+
|
99
101
|
# @param config [Nokogiri::XML::Document]
|
100
102
|
def initialize(config)
|
101
|
-
|
102
|
-
@
|
103
|
+
part = config.xpath("//report/part[@ref='SECURITYAUDIT']")
|
104
|
+
@config = part[0].elements
|
105
|
+
@title = part[0].attributes['title'].text
|
106
|
+
|
103
107
|
introduction
|
104
108
|
findings
|
105
109
|
end
|
@@ -107,9 +111,10 @@ module NipperParser
|
|
107
111
|
# Introduction of the Security Audit report
|
108
112
|
def introduction
|
109
113
|
intro = @config[0]
|
110
|
-
|
111
|
-
|
112
|
-
|
114
|
+
attribute = attributes(intro)
|
115
|
+
index = attribute.index
|
116
|
+
title = attribute.title
|
117
|
+
reference = attribute.ref
|
113
118
|
date = Date.parse(intro.elements[0].text).to_s
|
114
119
|
devices = generate_table(intro.elements[1].elements)
|
115
120
|
security_issue_overview = {}
|
@@ -133,7 +138,7 @@ module NipperParser
|
|
133
138
|
|
134
139
|
@findings = findings.map do |finding|
|
135
140
|
Finding.new(
|
136
|
-
attributes(finding).index
|
141
|
+
attributes(finding).index,
|
137
142
|
attributes(finding).title,
|
138
143
|
attributes(finding).ref,
|
139
144
|
finding.elements[0].elements[0].elements.map(&:attributes), # affected_devices
|
@@ -149,7 +154,7 @@ module NipperParser
|
|
149
154
|
# Conclusions
|
150
155
|
def conclusions
|
151
156
|
conc = @config.search("section[@ref='SECURITY.CONCLUSIONS']")[0]
|
152
|
-
index = attributes(conc).index
|
157
|
+
index = attributes(conc).index
|
153
158
|
title = attributes(conc).title
|
154
159
|
reference = attributes(conc).ref
|
155
160
|
per_device = generate_table(conc.elements[1].elements)
|
@@ -171,7 +176,7 @@ module NipperParser
|
|
171
176
|
# Recommendations
|
172
177
|
def recommendations
|
173
178
|
recom = @config.search("section[@ref='SECURITY.RECOMMENDATIONS']")[0]
|
174
|
-
index = attributes(recom).index
|
179
|
+
index = attributes(recom).index
|
175
180
|
title = attributes(recom).title
|
176
181
|
reference = attributes(recom).ref
|
177
182
|
list = generate_table(recom.elements[1].elements)
|
@@ -286,7 +291,6 @@ end
|
|
286
291
|
if __FILE__ == $0
|
287
292
|
require 'nokogiri'
|
288
293
|
require 'pp'
|
289
|
-
require_relative 'parser_utils'
|
290
294
|
config = Nokogiri::XML open(ARGV[0])
|
291
295
|
security_audit = NipperParser::SecurityAudit.new(config)
|
292
296
|
pp security_audit.introduction.class
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module NipperParser
|
2
|
+
|
3
|
+
# VulnerabilityAudit parse the 'Vulnerability Audit' part.
|
4
|
+
# Vulnerability Audit part contains the following sections:
|
5
|
+
# - introduction
|
6
|
+
# - CVEs
|
7
|
+
# - Conclusions
|
8
|
+
# - Recommendations
|
9
|
+
#
|
10
|
+
# @example Basic Usage:
|
11
|
+
# require 'nokogiri'
|
12
|
+
# require 'pp'
|
13
|
+
# config = Nokogiri::XML open(ARGV[0])
|
14
|
+
# vulnerability_audit = NipperParser::VulnerabilityAudit.new(config)
|
15
|
+
# pp vulnerability_audit.class
|
16
|
+
# pp vulnerability_audit.introduction
|
17
|
+
# pp vulnerability_audit.introduction.excluded_devices
|
18
|
+
# cve = vulnerability_audit.cves[0]
|
19
|
+
# pp cve.title
|
20
|
+
# pp cve.rating
|
21
|
+
# pp cve.summary
|
22
|
+
# pp cve.affected_devices
|
23
|
+
# pp cve.vendor_sec_advisories
|
24
|
+
# pp cve.references
|
25
|
+
# pp nipper_parser.vulnerability_audit.conclusions
|
26
|
+
# pp nipper_parser.vulnerability_audit.conclusions.list_critical
|
27
|
+
# pp nipper_parser.vulnerability_audit.recommendations
|
28
|
+
#
|
29
|
+
# @param config [Nokogiri::XML] parsed XML
|
30
|
+
# @attr_reader title the report title
|
31
|
+
# @attr_reader config a parsed XML [Nokogiri::XML] object
|
32
|
+
class VulnerabilityAudit
|
33
|
+
include ParserUtils
|
34
|
+
|
35
|
+
# Skeleton for SecurityAudit parts
|
36
|
+
Introduction = Struct.new(
|
37
|
+
:index, :title, :ref, :date, :devices,
|
38
|
+
:excluded_devices
|
39
|
+
)
|
40
|
+
CVE = Struct.new(
|
41
|
+
:index, :title, :ref,
|
42
|
+
:rating, :summary, :affected_devices,
|
43
|
+
:vendor_sec_advisories, :references
|
44
|
+
)
|
45
|
+
Conclusion = Struct.new(
|
46
|
+
:index, :title, :ref,
|
47
|
+
:per_device, :per_rating,
|
48
|
+
:list_critical, :list_high,
|
49
|
+
:list_medium, :list_low
|
50
|
+
)
|
51
|
+
Recommendations = Struct.new(
|
52
|
+
:index, :title, :ref,
|
53
|
+
:list
|
54
|
+
)
|
55
|
+
|
56
|
+
attr_reader :config, :title
|
57
|
+
|
58
|
+
# @param config [Nokogiri::XML::Document]
|
59
|
+
def initialize(config)
|
60
|
+
part = config.xpath("//report/part[@ref='VULNAUDIT']")
|
61
|
+
@config = part[0].elements
|
62
|
+
@title = part[0].attributes['title'].text
|
63
|
+
end
|
64
|
+
|
65
|
+
# Introduction of the Security Audit report
|
66
|
+
def introduction
|
67
|
+
intro = @config[0]
|
68
|
+
attribute = attributes(intro)
|
69
|
+
index = attribute.index
|
70
|
+
title = attribute.title
|
71
|
+
reference = attribute.ref
|
72
|
+
date = Date.parse(intro.elements[0].text).to_s
|
73
|
+
devices = generate_table(intro.elements[1].elements)
|
74
|
+
excluded = {devices: @config[0].elements[3].elements.map(&:text), # TODO enhance excluded results, need more excluded cases to see structure
|
75
|
+
reason: @config[0].elements[2].text}
|
76
|
+
|
77
|
+
Introduction.new(
|
78
|
+
index, title, reference,
|
79
|
+
date, devices, excluded
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def cves
|
85
|
+
cves = @config.to_a.clone
|
86
|
+
cves.shift # pop first item, the introduction
|
87
|
+
cves.pop(2) # pop last 2 items, conclusion, recommendations
|
88
|
+
|
89
|
+
cves.map.with_index do |cve, i|
|
90
|
+
CVE.new(
|
91
|
+
attributes(cve).index,
|
92
|
+
attributes(cve).title,
|
93
|
+
attributes(cve).ref,
|
94
|
+
cve.elements[0], # FIXME rating
|
95
|
+
cve.elements[1].elements.text, # summary
|
96
|
+
# cve.elements[2].elements[1].nil?? cve.elements[2].elements.map{|d| d.text} : cve.elements[2].elements[1].elements.map(&:text),
|
97
|
+
# this fix some affected devices scenario
|
98
|
+
if cve.elements[2].elements[1].nil?
|
99
|
+
cve.elements[2].elements.map{|d| d.text}
|
100
|
+
else
|
101
|
+
cve.elements[2].elements[1].elements.map(&:text)
|
102
|
+
end,
|
103
|
+
cve.elements[3].elements[1].elements.map(&:text), # vendor_sec_advisories
|
104
|
+
cve.elements[4].nil?? [] : cve.elements[4].elements[1].elements.map(&:text) # references, check if no references
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Conclusions
|
110
|
+
def conclusions
|
111
|
+
conc = @config.search("section[@ref='VULNAUDIT.CONCLUSIONS']")[0]
|
112
|
+
attribute = attributes(conc)
|
113
|
+
index = attribute.index
|
114
|
+
title = attribute.title
|
115
|
+
reference = attribute.ref
|
116
|
+
per_device = generate_table(conc.elements[1].elements)
|
117
|
+
summary_findings = generate_table(conc.elements[3].elements)
|
118
|
+
per_rating = {
|
119
|
+
critical: summary_findings.select{|finding| finding[:rating] == 'Critical'},
|
120
|
+
high: summary_findings.select{|finding| finding[:rating] == 'High'},
|
121
|
+
medium: summary_findings.select{|finding| finding[:rating] == 'Medium'},
|
122
|
+
low: summary_findings.select{|finding| finding[:rating] == 'Low'},
|
123
|
+
}
|
124
|
+
|
125
|
+
Conclusion.new(
|
126
|
+
index, title, reference, per_device, per_rating,
|
127
|
+
per_rating[:critical], per_rating[:high],
|
128
|
+
per_rating[:medium], per_rating[:low]
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Recommendations
|
133
|
+
def recommendations
|
134
|
+
recom = @config.search("section[@ref='VULNAUDIT.RECOMMENDATIONS']")[0]
|
135
|
+
attribute = attributes(recom)
|
136
|
+
index = attribute.index
|
137
|
+
title = attribute.title
|
138
|
+
reference = attribute.ref
|
139
|
+
list = recom.elements[2].elements.map(&:text)
|
140
|
+
|
141
|
+
Recommendations.new(
|
142
|
+
index, title, reference,
|
143
|
+
list
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
if __FILE__ == $0
|
153
|
+
require 'nokogiri'
|
154
|
+
require 'pp'
|
155
|
+
require_relative 'parser_utils'
|
156
|
+
|
157
|
+
|
158
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nipper_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KING SABRI
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -71,13 +71,14 @@ files:
|
|
71
71
|
- lib/nipper_parser.rb
|
72
72
|
- lib/nipper_parser/parsers/README.md
|
73
73
|
- lib/nipper_parser/parsers/cis_compliance.rb
|
74
|
+
- lib/nipper_parser/parsers/filtering_complexity.rb
|
74
75
|
- lib/nipper_parser/parsers/information.rb
|
75
76
|
- lib/nipper_parser/parsers/parser_utils.rb
|
76
77
|
- lib/nipper_parser/parsers/pci_audit.rb
|
77
78
|
- lib/nipper_parser/parsers/sans_compliance.rb
|
78
79
|
- lib/nipper_parser/parsers/security_audit.rb
|
79
80
|
- lib/nipper_parser/parsers/stig_compliance.rb
|
80
|
-
- lib/nipper_parser/parsers/
|
81
|
+
- lib/nipper_parser/parsers/vulnerability_audit.rb
|
81
82
|
- lib/nipper_parser/version.rb
|
82
83
|
- nipper_parser.gemspec
|
83
84
|
homepage: https://github.com/KINGSABRI/nipper_parser
|
@@ -1,102 +0,0 @@
|
|
1
|
-
module NipperParser
|
2
|
-
|
3
|
-
# VulnerabilityAudit parse the 'Vulnerability Audit' part.
|
4
|
-
# Vulnerability Audit part contains the following sections:
|
5
|
-
# - introduction
|
6
|
-
# - CVEs
|
7
|
-
# - Conclusions
|
8
|
-
# - Recommendations
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
class VulnerabilityAudit
|
14
|
-
include ParserUtils
|
15
|
-
|
16
|
-
# Skeleton for SecurityAudit parts
|
17
|
-
Introduction = Struct.new(
|
18
|
-
:index, :title, :ref, :date, :devices,
|
19
|
-
:security_issue_overview, :rating
|
20
|
-
)
|
21
|
-
CVE = Struct.new(
|
22
|
-
:index, :title, :ref,
|
23
|
-
:rating, :summary, :affected_devices,
|
24
|
-
:vendor_sec_advisories, :references
|
25
|
-
)
|
26
|
-
Conclusion = Struct.new(
|
27
|
-
:index, :title, :ref,
|
28
|
-
:per_device, :per_rating,
|
29
|
-
:list_critical, :list_high,
|
30
|
-
:list_medium, :list_low, :list_info
|
31
|
-
)
|
32
|
-
Recommendations = Struct.new(
|
33
|
-
:index, :title, :ref,
|
34
|
-
:list
|
35
|
-
)
|
36
|
-
|
37
|
-
attr_reader :config, :title
|
38
|
-
|
39
|
-
def initialize(config)
|
40
|
-
@config = config.xpath("//report/part[@ref='VULNAUDIT']")[0].elements
|
41
|
-
@title = @config[0].elements[1].attributes['title'].text
|
42
|
-
end
|
43
|
-
|
44
|
-
# CVEs
|
45
|
-
def cves
|
46
|
-
cves = @config.to_a.clone
|
47
|
-
cves.shift # pop first item, the introduction
|
48
|
-
cves.pop(2) # pop last 2 item, conclusion, recommendations
|
49
|
-
|
50
|
-
cves.map do |cve|
|
51
|
-
CVE.new(
|
52
|
-
attributes(cve).index,
|
53
|
-
attributes(cve).title,
|
54
|
-
attributes(cve).ref,
|
55
|
-
cve.elements[0], # FIXME
|
56
|
-
cve.elements[1].elements.text, # summary
|
57
|
-
cve.elements[2].elements[1].elements.map(&:text), # affect_devices
|
58
|
-
cve.elements[3].elements[1].elements.map(&:text), # vendor_sec_advisories
|
59
|
-
cve.elements[4].elements[1].elements.map(&:text), # references
|
60
|
-
)
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
# Conclusions
|
66
|
-
def conclusions
|
67
|
-
conc = @config[-2]
|
68
|
-
index = attributes(conc).index
|
69
|
-
title = attributes(conc).title
|
70
|
-
reference = attributes(conc).ref
|
71
|
-
per_device = generate_table(conc.elements[1].elements)
|
72
|
-
per_rating = {
|
73
|
-
critical: conc.elements[3].elements.map(&:text),
|
74
|
-
high: conc.elements[5].elements.map(&:text),
|
75
|
-
medium: conc.elements[7].elements.map(&:text),
|
76
|
-
low: conc.elements[9].elements.map(&:text),
|
77
|
-
info: conc.elements[11].elements.map(&:text)
|
78
|
-
}
|
79
|
-
|
80
|
-
Conclusion.new(
|
81
|
-
index, title, reference, per_device, per_rating,
|
82
|
-
per_rating[:critical], per_rating[:high],
|
83
|
-
per_rating[:medium], per_rating[:low], per_rating[:info],
|
84
|
-
)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Recommendations
|
88
|
-
def recommendations
|
89
|
-
recom = @config[-1]
|
90
|
-
index = attributes(recom).index
|
91
|
-
title = attributes(recom).title
|
92
|
-
reference = attributes(recom).ref
|
93
|
-
list = generate_table(recom.elements[1].elements)
|
94
|
-
|
95
|
-
Recommendations.new(
|
96
|
-
index, title, reference,
|
97
|
-
list
|
98
|
-
)
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
end
|