nipper_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5eb54da76791f956afd5e6c7c845127c02bbb39b
4
+ data.tar.gz: 68702d1dd51b46f06b97d82bfb45940d5137dc0f
5
+ SHA512:
6
+ metadata.gz: 3c1e8c381bf6ced1f2324841c17a3b3f6e873744914b902a0bf408e5d0ce3956b28f9b7a025396378f6f2729b826c6e298f7f1a55e6b41bce9e58803af0bc2f6
7
+ data.tar.gz: afa11d53d7ae2ca158ca347cd3279d893a64f1f3c5b852e0985bddc49c331999499e1249483e6c7e9ffeb495c68a551fad2fca6208ec0231462fc2c644665ba9
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea/
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.14.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nipper_parser.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 KING SABRI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,95 @@
1
+ # NipperParser
2
+ [![travis-cli](https://api.travis-ci.org/KINGSABRI/nipper_parser.svg)](https://travis-ci.org/KINGSABRI/nipper_parser/)
3
+ [![Code Climate](https://codeclimate.com/github/KINGSABRI/nipper_parser/badges/gpa.svg)](https://codeclimate.com/github/KINGSABRI/nipper_parser)
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
+ [![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
+
8
+ NipperParser gem is an unofficial parser for [Titania Nipper Studio](https://www.titania.com/products/nipper-studio) XML report.
9
+
10
+
11
+ #### Nipper Modules/Sections
12
+
13
+ | Modules / Sections | Supported |
14
+ |------------------------|-----------|
15
+ | Information | x |
16
+ | Security Audit | x |
17
+ | Vulnerability Audit | x |
18
+ | CIS Benchmarks | |
19
+ | STIG Compliance | |
20
+ | SANS Policy Compliance | |
21
+ | PCI Audit | |
22
+ | Filtering Complexity | |
23
+ | Configuration Report | |
24
+ | Raw Configuration | |
25
+ | Raw Change Tracking | |
26
+ | Appendix | |
27
+
28
+
29
+ ## Installation (not published yet)
30
+
31
+ ```ruby
32
+ gem install nipper_parser
33
+ ```
34
+ ## Usage
35
+
36
+ ##### Report information
37
+ ```ruby
38
+ require 'nipper_parser'
39
+ nipper_parser = NipperParser::Config.open('network-devices.xml')
40
+ puts nipper_parser.information.title
41
+ puts nipper_parser.information.author
42
+ puts nipper_parser.information.date
43
+ puts nipper_parser.information.devices
44
+ ```
45
+ ##### Dealing with Security Audit
46
+ ```ruby
47
+ pp security_audit = nipper_parser.security_audit
48
+ pp security_audit.findings
49
+ finding = security_audit.findings[0] # Play wit a finding
50
+ pp finding.class
51
+ pp finding.index
52
+ pp finding.title
53
+ pp finding.rating
54
+ pp finding.ref
55
+ pp finding.affected_devices
56
+ pp finding.finding
57
+ pp finding.impact
58
+ pp finding.recommendation
59
+ ```
60
+
61
+ ##### Report Summaries
62
+ ```ruby
63
+ pp security_audit.introduction.class
64
+ pp security_audit.introduction.title
65
+ pp security_audit.introduction.date
66
+ pp security_audit.introduction.security_issue_overview
67
+
68
+ pp security_audit.conclusions.class
69
+ pp security_audit.conclusions.per_device
70
+ pp security_audit.conclusions.list_critical
71
+
72
+ pp security_audit.recommendations.list
73
+
74
+ pp security_audit.mitigation_classification.class
75
+ pp security_audit.mitigation_classification.list_by.fixing[:involved]
76
+ pp security_audit.mitigation_classification.list_by.fixing[:involved][0].rating[:rating]
77
+ pp security_audit.mitigation_classification.list_by.rating[:high]
78
+ pp security_audit.mitigation_classification.list_by.rating[:high][0].rating[:fix]
79
+ pp security_audit.mitigation_classification.statistics.class
80
+ pp security_audit.mitigation_classification.statistics.findings
81
+ pp security_audit.mitigation_classification.statistics.report
82
+ ```
83
+ Fore more comprehensive usage, please refer to [Parsers ReadMe](lib/nipper_parser/parsers/README.md)
84
+
85
+ Download a dummy XML report to test the library from [**here**](https://gist.github.com/KINGSABRI/3dfcb821ea29f918f74c8e1979c5a71f).
86
+
87
+ ## Contributing
88
+
89
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/nipper_parser.
90
+
91
+
92
+ ## License
93
+
94
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
95
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nipper_parser"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,67 @@
1
+ # lib = File.expand_path('..', __FILE__)
2
+ # $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'nokogiri'
5
+ require 'nipper_parser/version'
6
+ require 'nipper_parser/parsers/parser_utils'
7
+ require 'nipper_parser/parsers/information'
8
+ require 'nipper_parser/parsers/security_audit'
9
+
10
+ module NipperParser
11
+
12
+ # Config opens nipper studio XML generated report and initially parses the XML file
13
+ #
14
+ # @example Basic usage
15
+ # nipper_parser = NipperParser::Config.open('nipper-network-devices.xml')
16
+ # pp nipper_parser.information.title
17
+ # pp nipper_parser.information.author
18
+ # pp nipper_parser.information.date
19
+ # pp nipper_parser.security_audit
20
+ # pp nipper_parser.security_audit.findings
21
+ # pp nipper_parser.security_audit.findings[0]
22
+ # pp nipper_parser.security_audit.findings[0].title
23
+ # pp nipper_parser.security_audit.findings[0].impact
24
+ # pp nipper_parser.security_audit.conclusions
25
+ # pp nipper_parser.security_audit.conclusions.per_device
26
+ # pp nipper_parser.security_audit.recommendations.list
27
+ # pp nipper_parser.security_audit.mitigation_classification
28
+ #
29
+ # @param file [File]
30
+ # @attr_reader information [Information] object of Information parser
31
+ # @attr_reader security_audit [SecurityAudit] object of SecurityAudit parser
32
+ class Config
33
+ # create an alias for new method.
34
+ # just wanted to call open instead of #new method
35
+ class << self
36
+ alias_method :open, :new
37
+ end
38
+
39
+ attr_reader :information, :security_audit
40
+ def initialize(file)
41
+ config_parsed = Nokogiri::XML(File.open(file))
42
+ # instantiate all parsers
43
+ @information = Information.new(config_parsed)
44
+ @security_audit = SecurityAudit.new(config_parsed)
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+
51
+
52
+ if __FILE__ == $0
53
+ require 'pp'
54
+ nipper_parser = NipperParser::Config.open(ARGV[0])
55
+ pp nipper_parser.information.title
56
+ pp nipper_parser.information.author
57
+ pp nipper_parser.information.date
58
+ pp nipper_parser.security_audit
59
+ pp nipper_parser.security_audit.findings
60
+ pp nipper_parser.security_audit.findings[0].class
61
+ pp nipper_parser.security_audit.findings[0].title
62
+ pp nipper_parser.security_audit.findings[0].impact
63
+ pp nipper_parser.security_audit.conclusions
64
+ pp nipper_parser.security_audit.conclusions.per_device
65
+ pp nipper_parser.security_audit.recommendations.list
66
+ pp nipper_parser.security_audit.mitigation_classification
67
+ end
@@ -0,0 +1,239 @@
1
+ # Nipper Parsers
2
+ This part contains all Nipper Studio Plugins/Sections that might be selected during the configuration audit.
3
+ Each parser is divided in a separate class and file.
4
+
5
+ ### General Report Information
6
+
7
+ **General Report Information Contains:**
8
+ - Introduction [implemented]
9
+ - Report Conventions [not yet implemented - PR is welcome]
10
+ - Network Filtering Actions [not yet implemented - PR is welcome]
11
+ - Object Filter Types [not yet implemented - PR is welcome]
12
+
13
+ #### Usage
14
+
15
+ ```ruby
16
+ require 'nipper_parser'
17
+ nipper_parser = NipperParser::Config.open('network-devices.xml')
18
+
19
+ # - Introduction
20
+ puts nipper_parser.information.title
21
+ puts nipper_parser.information.author
22
+ puts nipper_parser.information.date
23
+ puts nipper_parser.information.devices
24
+
25
+ # - Report Conventions
26
+ # - Network Filtering Actions
27
+ # - Object Filter Types
28
+ ```
29
+
30
+ ### Security Audit
31
+ Perform a "best practice" security audit that combines checks from many different sources including penetration testing
32
+ experience.
33
+
34
+ **Security Audit Section Contains:**
35
+ - Introduction [implemented]
36
+ - Findings [implemented]
37
+ - Conclusions [implemented]
38
+ - Recommendations [implemented]
39
+ - Mitigation Classification [implemented]
40
+
41
+ #### Usage
42
+
43
+ ```ruby
44
+ # - Introduction
45
+ pp security_audit.introduction.class
46
+ pp security_audit.introduction.title
47
+ pp security_audit.introduction.date
48
+ pp security_audit.introduction.security_issue_overview
49
+
50
+ # - Findings
51
+ pp security_audit = nipper_parser.security_audit
52
+ pp security_audit.findings
53
+ finding = security_audit.findings[0] # Play wit a finding
54
+ pp finding.class
55
+ pp finding.index
56
+ pp finding.title
57
+ pp finding.rating
58
+ pp finding.ref
59
+ pp finding.affected_devices
60
+ pp finding.finding
61
+ pp finding.impact
62
+ pp finding.recommendation
63
+
64
+ # - Conclusions
65
+ pp security_audit.conclusions.class
66
+ pp security_audit.conclusions.per_device
67
+ pp security_audit.conclusions.list_critical
68
+
69
+ # - Recommendations
70
+ pp security_audit.recommendations.list
71
+
72
+ # - Mitigation Classification
73
+ pp security_audit.mitigation_classification.class
74
+ pp security_audit.mitigation_classification.list_by.fixing[:involved]
75
+ pp security_audit.mitigation_classification.list_by.fixing[:involved][0].rating[:rating]
76
+ pp security_audit.mitigation_classification.list_by.rating[:high]
77
+ pp security_audit.mitigation_classification.list_by.rating[:high][0].rating[:fix]
78
+ pp security_audit.mitigation_classification.statistics.class
79
+ pp security_audit.mitigation_classification.statistics.findings
80
+ pp security_audit.mitigation_classification.statistics.report
81
+ ```
82
+
83
+ ### Vulnerability Audit
84
+ A report detailing publically known software vulnerabilities in the device firmware/software versions, including to
85
+ manufacturer and third-party references.
86
+
87
+ **Vulnerability Audit Section Contains:**
88
+ - Introduction [not yet implemented - PR is welcome]
89
+ - CVEs list [not yet implemented - PR is welcome]
90
+ - Conclusions [not yet implemented - PR is welcome]
91
+ - Recommendations [not yet implemented - PR is welcome]
92
+
93
+ #### Usage
94
+
95
+ ```ruby
96
+ # - Introduction
97
+ # - CVEs
98
+ # - Conclusions
99
+ # - Recommendations
100
+ ```
101
+
102
+ ### CIS Benchmarks
103
+ A CIS Benchmarks audit using select profile. Note, support is currently limited to specific devices, any included in the
104
+ report that are not supported will be ignored.
105
+
106
+ **CIS Benchmarks Section Contains:**
107
+ - Introduction [not yet implemented - PR is welcome]
108
+ - Conclusions [not yet implemented - PR is welcome]
109
+
110
+ #### Usage
111
+
112
+ ```ruby
113
+ # - Introduction
114
+ # - Conclusions
115
+ ```
116
+
117
+ ### STIG Compliance
118
+ A DISA STIG compliance audit against specific STIG checklist.
119
+
120
+ **STIG Compliance Section Contains:**
121
+ - Introduction [not yet implemented - PR is welcome]
122
+ - Compliance Observations list [not yet implemented - PR is welcome]
123
+ - Conclusions [not yet implemented - PR is welcome]
124
+ - Recommendations [not yet implemented - PR is welcome]
125
+
126
+ #### Usage
127
+
128
+ ```ruby
129
+ # - Introduction
130
+ # - Observations
131
+ # - Conclusions
132
+ # - Recommendations
133
+ ```
134
+
135
+ ### SANS Policy Compliance
136
+ A SANS policy compliance audit against specific SANS policy document.
137
+
138
+ **SANS Policy Compliance Section Contains:**
139
+ - Introduction [not yet implemented - PR is welcome]
140
+ - Compliance Observations list [not yet implemented - PR is welcome]
141
+
142
+ #### Usage
143
+
144
+ ```ruby
145
+ # - Introduction
146
+ # - Observations
147
+ # - Conclusions
148
+ # - Recommendations
149
+ ```
150
+
151
+ ### PCI Audit
152
+ An audit of Requirement and Security Assessment Procedures against PCI DSS 3.2.
153
+
154
+ **PCI Audit Section Contains:**
155
+ - Introduction [not yet implemented - PR is welcome]
156
+ - Compliance Requirements list [not yet implemented - PR is welcome]
157
+
158
+ #### Usage
159
+
160
+ ```ruby
161
+ # - Introduction
162
+ # - Requirements
163
+ ```
164
+
165
+ ### Filtering Complexity
166
+ A report examining the network filtering rules and objects, highlighting unused objects, overlapping or contradictory rules,
167
+ group recursion and more.
168
+
169
+ **Filtering Complexity Section Contains:**
170
+ - Introduction [not yet implemented - PR is welcome]
171
+ - Observations [not yet implemented - PR is welcome]
172
+
173
+ #### Usage
174
+
175
+ ```ruby
176
+ # - Introduction
177
+ # - Observations
178
+ ```
179
+
180
+ ### Configuration Report
181
+ A detailed report on how the device has been configured.
182
+
183
+ **Configuration Report Section Contains:**
184
+ - Introduction [not yet implemented - PR is welcome]
185
+ - Devices Config Audit [not yet implemented - PR is welcome]
186
+
187
+ #### Usage
188
+
189
+ ```ruby
190
+ # - Introduction
191
+ # - Configuration
192
+ ```
193
+
194
+ ### Raw Configuration
195
+ The raw configuration reporting details the actual device configuration data(excluding directory-based configurations).
196
+
197
+ **Raw Configuration Section Contains:**
198
+ - Introduction [not yet implemented - PR is welcome]
199
+ - Devices configuration raw [not yet implemented - PR is welcome]
200
+
201
+ #### Usage
202
+
203
+ ```ruby
204
+ # - Introduction
205
+ # - configuration
206
+ ```
207
+
208
+ ### Raw Change Tracking
209
+ The raw change tracking reporting will detail all the configuration lies that have changes since the previous report.
210
+
211
+ **Raw Change Tracking Section Contains:**
212
+ - Introduction [not yet implemented - PR is welcome]
213
+
214
+ #### Usage
215
+
216
+ ```ruby
217
+ # - Introduction
218
+ ```
219
+
220
+ ### Appendix
221
+ Appendix report section which can include a list of abbreviations, references and other information related to the report contents.
222
+
223
+ **Appendix Section Contains:**
224
+ - Introduction [not yet implemented - PR is welcome]
225
+ - Logging Severity Levels [not yet implemented - PR is welcome]
226
+ - Common Time Zones [not yet implemented - PR is welcome]
227
+ - IP Protocols [not yet implemented - PR is welcome]
228
+ - ICMP Types [not yet implemented - PR is welcome]
229
+ - Abbreviations [not yet implemented - PR is welcome]
230
+ - Nipper Studio Version [not yet implemented - PR is welcome]
231
+
232
+
233
+ #### Usage
234
+
235
+ ```ruby
236
+ # - Introduction
237
+ # - Requirements
238
+ ```
239
+
@@ -0,0 +1,65 @@
1
+ module NipperParser
2
+ class Information
3
+ # include ParserUtils
4
+
5
+ # Information parses the 'Information' part
6
+ #
7
+ # @example Basic Usage
8
+ # require 'nokogiri'
9
+ # require 'pp'
10
+ # config = Nokogiri::XML open(ARGV[0])
11
+ # pp information.title
12
+ # pp information.author
13
+ # pp information.date
14
+ # pp information.version
15
+ # pp information.devices
16
+ #
17
+ # @param config [Nokogiri::XML] parsed XML
18
+ # @attr_reader config [Nokogiri::XML] parsed XML object
19
+ # @attr_reader title [Sting] report title
20
+ # @attr_reader author [Sting] report author
21
+ # @attr_reader date [Sting] report generation date
22
+ # @attr_reader version [Sting] Nipper Studio version
23
+ # @attr_reader the tested devices
24
+ attr_reader :config, :title, :author, :date, :version, :devices
25
+
26
+ # @config The configuration [File]
27
+ def initialize(config)
28
+ @config = config.xpath('//information')[0]
29
+ @title = @config.elements[0].text
30
+ @author = @config.elements[1].text
31
+ @date = @config.elements[2].text
32
+ @version = @config.elements[3].elements[3].text
33
+ @devices = parse_devices
34
+ end
35
+
36
+ # parse_devices parse first devices list of the report
37
+ # @return [Array<Hash{Symbol => String}>]
38
+ def parse_devices
39
+ @config.xpath('devices')[0].elements.map do |device|
40
+ {
41
+ name: device.attributes['name'].text,
42
+ type: device.attributes['type'].text,
43
+ os: device.attributes['os'].text
44
+ }
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+
52
+
53
+ if __FILE__ == $0
54
+ require 'nokogiri'
55
+ require_relative 'parser_utils'
56
+ require 'pp'
57
+ config = Nokogiri::XML open(ARGV[0])
58
+ information = NipperParser::Information.new(config)
59
+ pp information.title
60
+ pp information.author
61
+ pp information.date
62
+ pp information.version
63
+ pp information.devices
64
+ pp information.devices[0].name
65
+ end
@@ -0,0 +1,40 @@
1
+ module NipperParser
2
+
3
+ # ParserUtils is a helper module for parsers' quick and dirty operations.
4
+ module ParserUtils
5
+
6
+ # generate_table parses the table elements
7
+ # @param elements [Nokogiri::XML::Element]
8
+ # @return [Hash]
9
+ def generate_table(elements)
10
+ headers = elements[0].elements.map{|header| header.text.downcase.tr(' ', '_').to_sym}
11
+ body = elements[1].elements.map{|e1| e1.elements.map{|e2| e2.text}}
12
+
13
+ body.map{|element| headers.zip(element).to_h}
14
+ end
15
+
16
+ # risk_table parses risk elements
17
+ # @param elements [Nokogiri::XML::Element]
18
+ # @return [Hash]
19
+ def rating_table(elements)
20
+ {
21
+ elements[0].name.to_sym => elements[0].text,
22
+ elements[1].name.to_sym => elements[1].text,
23
+ elements[2].name.to_sym => elements[2].text,
24
+ elements[3].name.to_sym => elements[3].text
25
+ }
26
+ end
27
+
28
+ Attribute = Struct.new(:index, :title, :ref)
29
+ # @param attr [Nokogiri::XML::Element] attributes
30
+ # @return [Hash<Attribute>]
31
+ def attributes(attr)
32
+ Attribute.new(
33
+ attr.attributes['index'].text,
34
+ attr.attributes['title'].text,
35
+ attr.attributes['ref'].text
36
+ )
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ module NipperParser
2
+ class PCIAudit
3
+ #TODO
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module NipperParser
2
+ class SANSCompliance
3
+ #TODO
4
+ end
5
+ end
@@ -0,0 +1,323 @@
1
+ require 'date'
2
+ require_relative 'parser_utils'
3
+ module NipperParser
4
+
5
+ # SecurityAudit parses the 'Security Audit' part including all it's sections.
6
+ # Security Audit part contains the following sections:
7
+ # - introduction
8
+ # - findings
9
+ # - Conclusions
10
+ # - Recommendations
11
+ # - Mitigation Classification
12
+ #
13
+ # @example Basic Usage
14
+ # require 'nokogiri'
15
+ # require 'pp'
16
+ # config = Nokogiri::XML open(ARGV[0])
17
+ # security_audit = NipperParser::SecurityAudit.new(config)
18
+ # pp security_audit.introduction.class
19
+ # pp security_audit.introduction.index
20
+ # pp security_audit.introduction.title
21
+ # pp security_audit.introduction.devices
22
+ # @example Dealing with findings
23
+ # finding = security_audit.findings[0]
24
+ # pp finding.class
25
+ # pp finding.index
26
+ # pp finding.title
27
+ # pp finding.ref
28
+ # pp finding.affected_devices
29
+ # pp finding.finding
30
+ # pp finding.impact
31
+ # pp finding.recommendation
32
+ # @example Dealing with report summaries
33
+ # pp security_audit.conclusions.class
34
+ # pp security_audit.conclusions.per_device
35
+ # pp security_audit.conclusions.list_critical
36
+ # pp security_audit.recommendations.class
37
+ # pp security_audit.recommendations.list
38
+ # pp security_audit.mitigation_classification.class
39
+ # pp security_audit.mitigation_classification.list_by.fixing[:involved]
40
+ # pp security_audit.mitigation_classification.list_by.fixing[:involved][0].rating[:rating]
41
+ # pp security_audit.mitigation_classification.list_by.rating[:high]
42
+ # pp security_audit.mitigation_classification.list_by.rating[:high][0].rating[:fix]
43
+ # pp security_audit.mitigation_classification.statistics.class
44
+ # pp security_audit.mitigation_classification.statistics.critical
45
+ # pp security_audit.mitigation_classification.statistics.quick
46
+ # pp security_audit.mitigation_classification.statistics.report
47
+ #
48
+ # @param config [Nokogiri::XML] parsed XML
49
+ # @attr_reader title the report title
50
+ # @attr_reader config a parsed XML [Nokogiri::XML] object
51
+ class SecurityAudit
52
+ include ParserUtils
53
+
54
+ # Skeleton for SecurityAudit parts
55
+
56
+ Introduction = Struct.new(
57
+ # introduction's index
58
+ :index,
59
+ :title, :ref, :date, :devices,
60
+ :security_issue_overview, :rating
61
+ )
62
+ Finding = Struct.new(
63
+ :index, :title, :ref,
64
+ :affected_devices, :rating,
65
+ :finding, :impact, :ease, :recommendation
66
+ )
67
+ Conclusion = Struct.new(
68
+ :index, :title, :ref,
69
+ :per_device, :per_rating,
70
+ :list_critical, :list_high,
71
+ :list_medium, :list_low, :list_info
72
+ )
73
+ Recommendations = Struct.new(
74
+ :index, :title, :ref,
75
+ :list
76
+ )
77
+ MitigationClassification = Struct.new(
78
+ :index, :title, :ref,
79
+ :list_by, :statistics
80
+ )
81
+ ListBy = Struct.new(
82
+ :fixing,
83
+ :rating, :all
84
+ )
85
+ Statistics = Struct.new(
86
+ :findings,
87
+ :critical,
88
+ :high,
89
+ :medium,
90
+ :low,
91
+ :informational,
92
+ :quick,
93
+ :planned,
94
+ :involved,
95
+ :report
96
+ )
97
+
98
+ attr_reader :config, :title
99
+ # @param config [Nokogiri::XML::Document]
100
+ def initialize(config)
101
+ @config = config.xpath("//report/part[@ref='SECURITYAUDIT']")[0].elements
102
+ @title = @config[0].elements[1].attributes['title'].text
103
+ introduction
104
+ findings
105
+ end
106
+
107
+ # Introduction of the Security Audit report
108
+ def introduction
109
+ intro = @config[0]
110
+ index = attributes(intro).index
111
+ title = attributes(intro).title
112
+ reference = attributes(intro).ref.to_i
113
+ date = Date.parse(intro.elements[0].text).to_s
114
+ devices = generate_table(intro.elements[1].elements)
115
+ security_issue_overview = {}
116
+ intro.elements[2].elements[1..4].map do |issue|
117
+ security_issue_overview[issue['title']] = issue.text
118
+ end
119
+ rating = generate_table(intro.elements[3].elements[2].elements[1].elements)
120
+
121
+ Introduction.new(
122
+ index, title, reference, date, devices,
123
+ security_issue_overview, rating
124
+ )
125
+ end
126
+
127
+ # Parse findings from given configurations
128
+ # @return [Array<Finding>]
129
+ def findings
130
+ findings = @config.to_a.clone
131
+ findings.shift # pop first item, the introduction
132
+ findings.pop(3) # pop last 3 item, conclusion, recommendations, Mitigation Classification
133
+
134
+ @findings = findings.map do |finding|
135
+ Finding.new(
136
+ attributes(finding).index.to_f,
137
+ attributes(finding).title,
138
+ attributes(finding).ref,
139
+ finding.elements[0].elements[0].elements.map(&:attributes), # affected_devices
140
+ rating_table(finding.elements[0].elements[1].elements), # Rating table
141
+ finding.elements[2].elements.first(2).map(&:text).join("\n"), # finding
142
+ finding.elements[3].elements.text, # impact
143
+ finding.elements[4].elements.text, # ease
144
+ finding.elements[5].elements.text # recommendation
145
+ )
146
+ end
147
+ end
148
+
149
+ # Conclusions
150
+ def conclusions
151
+ conc = @config.search("section[@ref='SECURITY.CONCLUSIONS']")[0]
152
+ index = attributes(conc).index.to_f
153
+ title = attributes(conc).title
154
+ reference = attributes(conc).ref
155
+ per_device = generate_table(conc.elements[1].elements)
156
+ per_rating = {
157
+ critical: conc.elements[3].elements.map(&:text),
158
+ high: conc.elements[5].elements.map(&:text),
159
+ medium: conc.elements[7].elements.map(&:text),
160
+ low: conc.elements[9].elements.map(&:text),
161
+ info: conc.elements[11].elements.map(&:text)
162
+ }
163
+
164
+ Conclusion.new(
165
+ index, title, reference, per_device, per_rating,
166
+ per_rating[:critical], per_rating[:high],
167
+ per_rating[:medium], per_rating[:low], per_rating[:info],
168
+ )
169
+ end
170
+
171
+ # Recommendations
172
+ def recommendations
173
+ recom = @config.search("section[@ref='SECURITY.RECOMMENDATIONS']")[0]
174
+ index = attributes(recom).index.to_f
175
+ title = attributes(recom).title
176
+ reference = attributes(recom).ref
177
+ list = generate_table(recom.elements[1].elements)
178
+
179
+ Recommendations.new(
180
+ index, title, reference,
181
+ list
182
+ )
183
+ end
184
+
185
+ def mitigation_classification
186
+ @mitigation = @config.search("section[@ref='SECURITY.MITIGATIONS']")[0] # @config[-1]
187
+
188
+ index = attributes(@mitigation).index
189
+ title = attributes(@mitigation).title
190
+ reference = attributes(@mitigation).ref
191
+ MitigationClassification.new(
192
+ index, title, reference,
193
+ list_by,
194
+ statistics
195
+ )
196
+
197
+ end
198
+
199
+ private
200
+ # list_by list different type of mitigation, by fixing type, and by rating type.
201
+ #
202
+ # @example:
203
+ # list_by.fixing # @return [Hash]
204
+ # list_by.fixing[:quick] # @return [Array<Findings>]
205
+ # list_by.rating # @return [Hash]
206
+ # list_by.rating[:critical] # @return [Array<Findings>]
207
+ # list_by.all # @return [Hash]
208
+ #
209
+ # @return [ListBy]
210
+ def list_by
211
+ @fixing_lists = @mitigation.search('list')
212
+ _by_fixing = by_fixing # @see by_fixing
213
+ _by_rating = by_rating # @see by_rating
214
+ fixing = {quick: _by_fixing[0], planned: _by_fixing[1], involved: _by_fixing[2]}
215
+ rating = {critical: _by_rating[:critical], high: _by_rating[:high],
216
+ medium: _by_rating[:medium], low: _by_rating[:low],
217
+ informational: _by_rating[:informational]}
218
+ _by_all = {fixing: fixing, rating: rating}
219
+
220
+ ListBy.new(
221
+ _by_all[:fixing],
222
+ _by_all[:rating],
223
+ _by_all
224
+ )
225
+ end
226
+
227
+ # finding_objects maps finding listitems text with the findings object
228
+ def by_fixing
229
+ findings = @findings.dup
230
+ @fixing_lists.map do |_class|
231
+ _class.search('listitem').map do |item|
232
+ # if 'finding' reference = item mentioned index (extracted from text 'See section' ),
233
+ # then return the finding object
234
+ findings.select{|finding| finding.index == item.text.match(/\d+\.\d+/).to_s.to_f}[0]
235
+ end
236
+ end
237
+ end
238
+
239
+ # search in all finding by rating
240
+ def by_rating
241
+ findings = @findings.dup
242
+ rating = {critical: nil, high: nil, medium: nil, low: nil, informational: nil}
243
+ rating.keys.each do |rate|
244
+ rating[rate] = findings.select {|finding| finding.rating[:rating].downcase == rate.to_s}
245
+ end
246
+
247
+ rating
248
+ end
249
+
250
+ # mitigation statistics regarding to number of:
251
+ # - findings
252
+ # - findings by rating
253
+ # - findings by fixing
254
+ # @return [Statistics]
255
+ def statistics
256
+ findings = @findings.size
257
+ ratings = {critical: nil, high: nil, medium: nil, low: nil, informational: nil}
258
+ ratings.keys.each do |rating|
259
+ ratings[rating] = {total: list_by.rating[rating].size,
260
+ perce: ( (list_by.rating[rating].size/@findings.size.to_f) * 100.0 ).round(2)}
261
+ end
262
+ fixing = {quick: nil, involved: nil, planned: nil}
263
+ fixing.keys.each do |fix|
264
+ fixing[fix] = {total: list_by.fixing[fix].size,
265
+ perce: ( (list_by.fixing[fix].size/@findings.size.to_f) * 100.0 ).round(2)}
266
+ end
267
+ report = {ratings: ratings, fixing: fixing}
268
+ Statistics.new(
269
+ findings,
270
+ ratings[:critical],
271
+ ratings[:high],
272
+ ratings[:medium],
273
+ ratings[:low],
274
+ ratings[:informational],
275
+ fixing[:quick],
276
+ fixing[:involved],
277
+ fixing[:planned],
278
+ report
279
+ )
280
+ end
281
+ end
282
+ end
283
+
284
+
285
+
286
+ if __FILE__ == $0
287
+ require 'nokogiri'
288
+ require 'pp'
289
+ require_relative 'parser_utils'
290
+ config = Nokogiri::XML open(ARGV[0])
291
+ security_audit = NipperParser::SecurityAudit.new(config)
292
+ pp security_audit.introduction.class
293
+ pp security_audit.introduction.index
294
+ pp security_audit.introduction.title
295
+ pp security_audit.introduction.rating
296
+ pp security_audit.introduction.security_issue_overview
297
+ pp security_audit.introduction.ref
298
+ pp security_audit.introduction.devices
299
+ finding = security_audit.findings[0]
300
+ pp finding.class
301
+ pp finding.index
302
+ pp finding.title
303
+ pp finding.rating
304
+ pp finding.ref
305
+ pp finding.affected_devices
306
+ pp finding.finding
307
+ pp finding.impact
308
+ pp finding.recommendation
309
+ pp security_audit.introduction
310
+ pp security_audit.conclusions.class
311
+ pp security_audit.conclusions.per_device
312
+ pp security_audit.conclusions.list_critical
313
+ pp security_audit.recommendations.class
314
+ pp security_audit.recommendations.list
315
+ pp security_audit.mitigation_classification.class
316
+ pp security_audit.mitigation_classification.list_by.fixing[:involved]
317
+ pp security_audit.mitigation_classification.list_by.fixing[:involved][0].rating[:rating]
318
+ pp security_audit.mitigation_classification.list_by.rating[:high]
319
+ pp security_audit.mitigation_classification.list_by.rating[:high][0].rating[:fix]
320
+ pp security_audit.mitigation_classification.statistics.class
321
+ pp security_audit.mitigation_classification.statistics.findings
322
+ pp security_audit.mitigation_classification.statistics.report
323
+ end
@@ -0,0 +1,5 @@
1
+ module NipperParser
2
+ class STIGCompliance
3
+ #TODO
4
+ end
5
+ end
@@ -0,0 +1,102 @@
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
@@ -0,0 +1,3 @@
1
+ module NipperParser
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nipper_parser/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nipper_parser"
8
+ spec.version = NipperParser::VERSION
9
+ spec.authors = ["KING SABRI"]
10
+ spec.email = ["king.sabri@gmail.com"]
11
+
12
+ spec.summary = %q{Unofficial parser for Titania Nipper Studio XML report.}
13
+ spec.description = spec.summary
14
+ spec.homepage = "https://github.com/KINGSABRI/nipper_parser"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.required_ruby_version = '>= 2.3.0'
25
+
26
+ spec.add_dependency "nokogiri", ">= 1.8.0"
27
+ spec.add_development_dependency "bundler", "~> 1.14"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nipper_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - KING SABRI
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-08-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.8.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.8.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description: Unofficial parser for Titania Nipper Studio XML report.
56
+ email:
57
+ - king.sabri@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - bin/console
70
+ - bin/setup
71
+ - lib/nipper_parser.rb
72
+ - lib/nipper_parser/parsers/README.md
73
+ - lib/nipper_parser/parsers/cis_compliance.rb
74
+ - lib/nipper_parser/parsers/information.rb
75
+ - lib/nipper_parser/parsers/parser_utils.rb
76
+ - lib/nipper_parser/parsers/pci_audit.rb
77
+ - lib/nipper_parser/parsers/sans_compliance.rb
78
+ - lib/nipper_parser/parsers/security_audit.rb
79
+ - lib/nipper_parser/parsers/stig_compliance.rb
80
+ - lib/nipper_parser/parsers/vulnerabilty_audit.rb
81
+ - lib/nipper_parser/version.rb
82
+ - nipper_parser.gemspec
83
+ homepage: https://github.com/KINGSABRI/nipper_parser
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 2.3.0
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.6.11
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Unofficial parser for Titania Nipper Studio XML report.
107
+ test_files: []