ruby-nikto 0.1.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.
@@ -0,0 +1,181 @@
1
+ require 'spec_helper'
2
+ require 'nikto/xml/scan_details'
3
+ require 'nokogiri'
4
+
5
+ describe Nikto::XML::ScanDetails do
6
+ let(:fixtures_dir) { File.expand_path(File.join(__dir__,'..','fixtures')) }
7
+ let(:path) { File.join(fixtures_dir,'nikto.xml') }
8
+ let(:xml) { File.read(path) }
9
+ let(:doc) { Nokogiri::XML(File.open(path)) }
10
+ let(:node) { doc.at_xpath('/niktoscan/scandetails') }
11
+
12
+ subject { described_class.new(node) }
13
+
14
+ describe "#target_ip" do
15
+ subject { super().target_ip }
16
+
17
+ it "must return a String" do
18
+ expect(subject).to be_kind_of(String)
19
+ end
20
+
21
+ it "must return the 'targetip' attribute" do
22
+ expect(subject).to eq(node['targetip'])
23
+ end
24
+ end
25
+
26
+ describe "#target_hostname" do
27
+ subject { super().target_hostname }
28
+
29
+ it "must return a String" do
30
+ expect(subject).to be_kind_of(String)
31
+ end
32
+
33
+ it "must return the 'targethostname' attribute" do
34
+ expect(subject).to eq(node['targethostname'])
35
+ end
36
+ end
37
+
38
+ describe "#target_port" do
39
+ subject { super().target_port }
40
+
41
+ it "must return the 'targetport' attribute as an Integer" do
42
+ expect(subject).to eq(node['targetport'].to_i)
43
+ end
44
+
45
+ it "must be > 0" do
46
+ expect(subject).to be > 0
47
+ end
48
+ end
49
+
50
+ describe "#target_banner" do
51
+ subject { super().target_banner }
52
+
53
+ it "must return a String" do
54
+ expect(subject).to be_kind_of(String)
55
+ end
56
+
57
+ it "must return the 'targetbanner' attribute" do
58
+ expect(subject).to eq(node['targetbanner'])
59
+ end
60
+ end
61
+
62
+ describe "#start_time" do
63
+ subject { super().start_time }
64
+
65
+ it "must return the 'starttime' attribute as a Time object" do
66
+ expect(subject).to eq(Time.parse(node['starttime']))
67
+ end
68
+ end
69
+
70
+ describe "#site_name" do
71
+ subject { super().site_name }
72
+
73
+ it "must return a String" do
74
+ expect(subject).to be_kind_of(String)
75
+ end
76
+
77
+ it "must return the 'sitename' attribute" do
78
+ expect(subject).to eq(node['sitename'])
79
+ end
80
+ end
81
+
82
+ describe "#site_ip" do
83
+ subject { super().site_ip }
84
+
85
+ it "must return a String" do
86
+ expect(subject).to be_kind_of(String)
87
+ end
88
+
89
+ it "must return the 'siteip' attribute" do
90
+ expect(subject).to eq(node['siteip'])
91
+ end
92
+ end
93
+
94
+ describe "#host_header" do
95
+ subject { super().host_header }
96
+
97
+ it "must return a String" do
98
+ expect(subject).to be_kind_of(String)
99
+ end
100
+
101
+ it "must return the 'hostheader' attribute" do
102
+ expect(subject).to eq(node['hostheader'])
103
+ end
104
+ end
105
+
106
+ describe "#errors" do
107
+ subject { super().errors }
108
+
109
+ it "must return the 'errors' attribute as an Integer" do
110
+ expect(subject).to eq(node['errors'].to_i)
111
+ end
112
+ end
113
+
114
+ describe "#errors?" do
115
+ context "when #errors is 0" do
116
+ before { allow(subject).to receive(:errors).and_return(0) }
117
+
118
+ it "must return false" do
119
+ expect(subject.errors?).to be(false)
120
+ end
121
+ end
122
+
123
+ context "when #errors is greater than 0" do
124
+ before { allow(subject).to receive(:errors).and_return(1) }
125
+
126
+ it "must return true" do
127
+ expect(subject.errors?).to be(true)
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "#checks" do
133
+ subject { super().checks }
134
+
135
+ it "must return the 'checks' attribute as an Integer" do
136
+ expect(subject).to eq(node['checks'].to_i)
137
+ end
138
+
139
+ it "must be > 0" do
140
+ expect(subject).to be > 0
141
+ end
142
+ end
143
+
144
+ let(:item_count) { node.xpath('item').count }
145
+
146
+ describe "#each_item" do
147
+ context "when given a block" do
148
+ it "must yield each Item object" do
149
+ expect { |b|
150
+ subject.each_item(&b)
151
+ }.to yield_successive_args(*Array.new(item_count,Nikto::XML::Item))
152
+ end
153
+ end
154
+
155
+ context "when no block is given" do
156
+ subject { super().each_item.to_a }
157
+
158
+ it "must return an Enumerator of Nikto::XML::Item objects" do
159
+ expect(subject.length).to be(item_count)
160
+ expect(subject).to all(be_kind_of(Nikto::XML::Item))
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "#items" do
166
+ subject { super().items}
167
+
168
+ it "must return an Array of Nikto::XML::ScanDetails" do
169
+ expect(subject.length).to be(item_count)
170
+ expect(subject).to all(be_kind_of(Nikto::XML::Item))
171
+ end
172
+ end
173
+
174
+ describe "#statistics" do
175
+ subject { super().statistics }
176
+
177
+ it "must return a Statistics object" do
178
+ expect(subject).to be_kind_of(Nikto::XML::Statistics)
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'nikto/xml/statistics'
3
+ require 'nokogiri'
4
+
5
+ describe Nikto::XML::Statistics do
6
+ let(:fixtures_dir) { File.expand_path(File.join(__dir__,'..','fixtures')) }
7
+ let(:path) { File.join(fixtures_dir,'nikto.xml') }
8
+ let(:xml) { File.read(path) }
9
+ let(:doc) { Nokogiri::XML(File.open(path)) }
10
+ let(:node) { doc.at_xpath('/niktoscan/scandetails/statistics') }
11
+
12
+ subject { described_class.new(node) }
13
+
14
+ describe "#elapsed" do
15
+ subject { super().elapsed }
16
+
17
+ it "must return the 'elapsed' attribute as an Integer" do
18
+ expect(subject).to eq(node['elapsed'].to_i)
19
+ end
20
+
21
+ it "must be greater than 0" do
22
+ expect(subject).to be > 0
23
+ end
24
+ end
25
+
26
+ describe "#items_found" do
27
+ subject { super().items_found }
28
+
29
+ it "must return the 'itemsfound' attribute as an Integer" do
30
+ expect(subject).to eq(node['itemsfound'].to_i)
31
+ end
32
+
33
+ it "must be greater than 0" do
34
+ expect(subject).to be > 0
35
+ end
36
+ end
37
+
38
+ describe "#items_tested" do
39
+ subject { super().items_tested }
40
+
41
+ it "must return the 'itemstested' attribute as an Integer" do
42
+ expect(subject).to eq(node['itemstested'].to_i)
43
+ end
44
+
45
+ it "must be greater than 0" do
46
+ expect(subject).to be > 0
47
+ end
48
+ end
49
+
50
+ describe "#end_time" do
51
+ subject { super().end_time }
52
+
53
+ it "must return the 'endtime' attribute as a Time object" do
54
+ expect(subject).to eq(Time.parse(node['endtime']))
55
+ end
56
+ end
57
+ end
data/spec/xml_spec.rb ADDED
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+ require 'nikto/xml'
3
+
4
+ describe Nikto::XML do
5
+ let(:fixtures_dir) { File.expand_path(File.join(__dir__,'fixtures')) }
6
+ let(:path) { File.join(fixtures_dir,'nikto.xml') }
7
+ let(:xml) { File.read(path) }
8
+ let(:doc) { Nokogiri::XML(File.open(path)) }
9
+
10
+ subject { described_class.new(doc, path: path) }
11
+
12
+ describe "#initialize" do
13
+ it "must set #doc" do
14
+ expect(subject.doc).to eq(doc)
15
+ end
16
+
17
+ context "when given a block" do
18
+ it "must yield the new XML object" do
19
+ expect { |b|
20
+ described_class.new(xml,&b)
21
+ }.to yield_with_args(described_class)
22
+ end
23
+ end
24
+
25
+ context "when the path: keyword argument is not given" do
26
+ subject { described_class.new(xml) }
27
+
28
+ it "must set #path to nil" do
29
+ expect(subject.path).to be(nil)
30
+ end
31
+ end
32
+
33
+ context "when the path: keyword argument is given" do
34
+ subject { described_class.new(xml, path: path) }
35
+
36
+ it "must set #path" do
37
+ expect(subject.path).to eq(path)
38
+ end
39
+ end
40
+ end
41
+
42
+ describe ".parse" do
43
+ subject { described_class.parse(xml) }
44
+
45
+ it "must parse the XML data" do
46
+ expect(subject.doc).to be_kind_of(Nokogiri::XML::Document)
47
+ end
48
+
49
+ it "must set #path to nil" do
50
+ expect(subject.path).to be(nil)
51
+ end
52
+ end
53
+
54
+ describe ".open" do
55
+ subject { described_class.open(path) }
56
+
57
+ it "must open the file and parse the XML" do
58
+ expect(subject.doc).to be_kind_of(Nokogiri::XML::Document)
59
+ end
60
+
61
+ it "must set #path" do
62
+ expect(subject.path).to eq(path)
63
+ end
64
+ end
65
+
66
+ describe "#hosts_test" do
67
+ subject { super().hosts_test }
68
+
69
+ it "must return the 'hoststest' attribute as an Integer" do
70
+ expect(subject).to eq(doc.root['hoststest'].to_i)
71
+ end
72
+ end
73
+
74
+ describe "#options" do
75
+ subject { super().options }
76
+
77
+ it "must return a String" do
78
+ expect(subject).to be_kind_of(String)
79
+ end
80
+
81
+ it "must return the 'options' attribute" do
82
+ expect(subject).to eq(doc.root['options'])
83
+ end
84
+ end
85
+
86
+ describe "#scan_start" do
87
+ subject { super().scan_start }
88
+
89
+ it "must return the 'scanstart' attribute as a Time object" do
90
+ expect(subject).to eq(Time.parse(doc.root['scanstart']))
91
+ end
92
+ end
93
+
94
+ describe "#scan_end" do
95
+ subject { super().scan_end }
96
+
97
+ it "must return the 'scanend' attribute as a Time object" do
98
+ expect(subject).to eq(Time.parse(doc.root['scanend']))
99
+ end
100
+ end
101
+
102
+ describe "#scan_elapsed" do
103
+ subject { super().scan_elapsed }
104
+
105
+ it "must return a String" do
106
+ expect(subject).to be_kind_of(String)
107
+ end
108
+
109
+ it "must return the 'scanelapsed' attribute" do
110
+ expect(subject).to eq(doc.root['scanelapsed'])
111
+ end
112
+ end
113
+
114
+ describe "#nikto_xml_version" do
115
+ subject { super().nikto_xml_version }
116
+
117
+ it "must return a String" do
118
+ expect(subject).to be_kind_of(String)
119
+ end
120
+
121
+ it "must return the 'nxmlversion' attribute" do
122
+ expect(subject).to eq(doc.root['nxmlversion'])
123
+ end
124
+ end
125
+
126
+ describe "#each_scan_details" do
127
+ context "when given a block" do
128
+ it "must yield each ScanDetails object" do
129
+ expect { |b|
130
+ subject.each_scan_details(&b)
131
+ }.to yield_successive_args(described_class::ScanDetails)
132
+ end
133
+ end
134
+
135
+ context "when no block is given" do
136
+ subject { super().each_scan_details.to_a }
137
+
138
+ it "must return an Enumerator of #{described_class}::ScanDetails objects" do
139
+ expect(subject.length).to be(1)
140
+ expect(subject[0]).to be_kind_of(described_class::ScanDetails)
141
+ end
142
+ end
143
+ end
144
+
145
+ describe "#scan_details" do
146
+ subject { super().scan_details }
147
+
148
+ it "must return an Array of #{described_class}::ScanDetails" do
149
+ expect(subject).to be_kind_of(Array)
150
+ expect(subject.length).to be(1)
151
+ expect(subject[0]).to be_kind_of(described_class::ScanDetails)
152
+ end
153
+ end
154
+
155
+ describe "#target" do
156
+ let(:first_scan_details) { subject.scan_details.first }
157
+ let(:target) { subject.target }
158
+
159
+ it "must return the first #scan_details" do
160
+ expect(target.target_ip).to eq(first_scan_details.target_ip)
161
+ expect(target.target_hostname).to eq(first_scan_details.target_hostname)
162
+ expect(target.target_port).to eq(first_scan_details.target_port)
163
+ expect(target.target_banner).to eq(first_scan_details.target_banner)
164
+ expect(target.start_time).to eq(first_scan_details.start_time)
165
+ expect(target.site_name).to eq(first_scan_details.site_name)
166
+ expect(target.site_ip).to eq(first_scan_details.site_ip)
167
+ expect(target.host_header).to eq(first_scan_details.host_header)
168
+ expect(target.errors).to eq(first_scan_details.errors)
169
+ expect(target.checks).to eq(first_scan_details.checks)
170
+ end
171
+ end
172
+
173
+ describe "#to_s" do
174
+ context "when #path is set" do
175
+ subject { described_class.open(path) }
176
+
177
+ it "must return the #path" do
178
+ expect(subject.to_s).to eq(path)
179
+ end
180
+ end
181
+
182
+ context "when #path is nil" do
183
+ subject { described_class.parse(xml) }
184
+
185
+ it "must return the XML" do
186
+ expect(subject.to_s).to eq(doc.to_s)
187
+ end
188
+ end
189
+ end
190
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-nikto
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Postmodern
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: command_mapper
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ description: A Ruby interface to Nikto, the Web Server scanner.
56
+ email: postmodern.mod3@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files:
60
+ - ChangeLog.md
61
+ - LICENSE.txt
62
+ - README.md
63
+ files:
64
+ - ".editorconfig"
65
+ - ".github/workflows/ruby.yml"
66
+ - ".gitignore"
67
+ - ".rspec"
68
+ - ".specopts"
69
+ - ".yardopts"
70
+ - ChangeLog.md
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - gemspec.yml
76
+ - lib/nikto.rb
77
+ - lib/nikto/command.rb
78
+ - lib/nikto/version.rb
79
+ - lib/nikto/xml.rb
80
+ - lib/nikto/xml/item.rb
81
+ - lib/nikto/xml/scan_details.rb
82
+ - lib/nikto/xml/statistics.rb
83
+ - ruby-nikto.gemspec
84
+ - spec/command_spec.rb
85
+ - spec/fixtures/nikto.xml
86
+ - spec/nikto_spec.rb
87
+ - spec/spec_helper.rb
88
+ - spec/xml/item_spec.rb
89
+ - spec/xml/scan_details_spec.rb
90
+ - spec/xml/statistics_spec.rb
91
+ - spec/xml_spec.rb
92
+ homepage: http://github.com/sophsec/ruby-nikto
93
+ licenses:
94
+ - MIT
95
+ metadata:
96
+ documentation_uri: https://rubydoc.info/gems/ruby-nikto
97
+ source_code_uri: https://github.com/postmodern/ruby-nikto
98
+ bug_tracker_uri: https://github.com/postmodern/ruby-nikto/issues
99
+ changelog_uri: https://github.com/postmodern/ruby-nikto/blob/master/ChangeLog.md
100
+ rubygems_mfa_required: 'true'
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements:
116
+ - nikto >= 2.1.0
117
+ rubygems_version: 3.2.22
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: A Ruby interface to Nikto.
121
+ test_files: []