nipper_parser 1.0.0 → 1.2.0
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 +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
|
-
[](https://badge.fury.io/rb/nipper_parser)
|
3
3
|
[](https://codeclimate.com/github/KINGSABRI/nipper_parser)
|
4
4
|
[](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
|
[](https://inch-ci.org/github/KINGSABRI/nipper_parser)
|
6
|
-
[](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
|