ruby-nikto 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +11 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.specopts +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +9 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +10 -0
- data/gemspec.yml +24 -0
- data/lib/nikto/command.rb +188 -0
- data/lib/nikto/version.rb +4 -0
- data/lib/nikto/xml/item.rb +55 -0
- data/lib/nikto/xml/scan_details.rb +175 -0
- data/lib/nikto/xml/statistics.rb +64 -0
- data/lib/nikto/xml.rb +230 -0
- data/lib/nikto.rb +2 -0
- data/ruby-nikto.gemspec +58 -0
- data/spec/command_spec.rb +97 -0
- data/spec/fixtures/nikto.xml +47 -0
- data/spec/nikto_spec.rb +8 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/xml/item_spec.rb +61 -0
- data/spec/xml/scan_details_spec.rb +181 -0
- data/spec/xml/statistics_spec.rb +57 -0
- data/spec/xml_spec.rb +190 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4fcc497451a7d1d6bd7ed21bd253f113afd7907e7846d78cd78fdacfa5b05038
|
4
|
+
data.tar.gz: 4e3cf53c1f2a0354720e1ebe13e4e3f2fd8da7a82bf21f9687bfdfa9a758a9da
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 388a8492bb9faa2a4ee6c3235ffd5119511b4993cac47e984f45f1498c4d12a00e6c354b1255fa9caeeb38d767cf826c91acbf60af1dfa0174ba094e28c53e16
|
7
|
+
data.tar.gz: 9ac99ff184756ae910eccc8b555393ac99f7e13fe01f16bf105c24645b805d09da9d4ddf407b2fc794373882b78cf01a3a387b6ad94e450a4e947d4d6f62defc
|
data/.editorconfig
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [ push, pull_request ]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
tests:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
fail-fast: false
|
10
|
+
matrix:
|
11
|
+
ruby:
|
12
|
+
- 2.6
|
13
|
+
- 2.7
|
14
|
+
- 3.0
|
15
|
+
- jruby
|
16
|
+
- truffleruby
|
17
|
+
name: Ruby ${{ matrix.ruby }}
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
- name: Set up Ruby
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ matrix.ruby }}
|
24
|
+
- name: Install libxml2-dev and libxslt1-dev
|
25
|
+
run: |
|
26
|
+
sudo apt update -y && \
|
27
|
+
sudo apt install -y --no-install-recommends --no-install-suggests libxml2-dev libxslt1-dev
|
28
|
+
- name: Install dependencies
|
29
|
+
run: bundle install --jobs 4 --retry 3
|
30
|
+
- name: Run tests
|
31
|
+
run: bundle exec rake test
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/.specopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format specdoc
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --title 'Ruby Nikto Documentation' --protected --files ChangeLog.md,LICENSE.txt
|
data/ChangeLog.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# gem 'command_mapper', '~> 0.1.1', github: 'postmodern/command_mapper.rb'
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem 'rake'
|
9
|
+
gem 'rubygems-tasks', '~> 0.2'
|
10
|
+
gem 'rspec', '~> 3.0'
|
11
|
+
gem 'simplecov', '~> 0.7'
|
12
|
+
|
13
|
+
gem 'kramdown'
|
14
|
+
gem 'yard', '~> 0.9'
|
15
|
+
gem 'yard-spellcheck', require: false
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2009-2021 Hal Brodigan
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# ruby-nikto
|
2
|
+
|
3
|
+
[![CI](https://github.com/postmodern/ruby-nikto/actions/workflows/ruby.yml/badge.svg)](https://github.com/postmodern/ruby-nikto/actions/workflows/ruby.yml)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/ruby-nikto.svg)](https://badge.fury.io/rb/ruby-nikto)
|
5
|
+
|
6
|
+
* [Source](https://github.com/sophsec/ruby-nikto)
|
7
|
+
* [Issues](https://github.com/sophsec/ruby-nikto/issues)
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
A Ruby interface to [nikto].
|
12
|
+
|
13
|
+
## Features
|
14
|
+
|
15
|
+
* Provides a [Ruby interface][Nikto::Command] for running the `nikto` utility.
|
16
|
+
* Provides a [parser][Nikto::XML] for enumerating Nikto XML scan files.
|
17
|
+
|
18
|
+
[Nikto::Command]: https://rubydoc.info/gems/ruby-nikto/Nikto/Command
|
19
|
+
[Nikto::XML]: https://rubydoc.info/gems/ruby-nikto/Nikto/XML
|
20
|
+
|
21
|
+
## Examples
|
22
|
+
|
23
|
+
Run Nikto from Ruby:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'nikto/command'
|
27
|
+
|
28
|
+
Nikto::Command.run(host: 'example.com', output: 'nikto.xml')
|
29
|
+
```
|
30
|
+
|
31
|
+
Parse Nikto XML scan files:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'nikto/xml'
|
35
|
+
|
36
|
+
Nikto::XML.open('nikto.xml') do |xml|
|
37
|
+
xml.each_scan_details do |scan_details|
|
38
|
+
puts "#{scan_details.site_name}"
|
39
|
+
|
40
|
+
scan_details.each_item do |item|
|
41
|
+
puts " #{item.uri}"
|
42
|
+
puts
|
43
|
+
puts " #{item.description}"
|
44
|
+
puts
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
## Requirements
|
51
|
+
|
52
|
+
* [nikto] >= 2.1.0
|
53
|
+
* [command_mapper](http://github.com/postmodern/command_mapper.rb#readme) ~> 0.1
|
54
|
+
* [nokogiri](https://github.com/sparklemotion/nokogiri#readme) ~> 1.0
|
55
|
+
|
56
|
+
## Install
|
57
|
+
|
58
|
+
```shell
|
59
|
+
$ gem install ruby-nikto
|
60
|
+
```
|
61
|
+
|
62
|
+
### gemspec
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
gemspec.add_dependency 'ruby-nikto', '~> 0.1'
|
66
|
+
```
|
67
|
+
|
68
|
+
### Gemfile
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
gem 'ruby-nikto', '~> 0.1'
|
72
|
+
```
|
73
|
+
|
74
|
+
## License
|
75
|
+
|
76
|
+
Copyright (c) 2009-2021 Hal Brodigan
|
77
|
+
|
78
|
+
See {file:LICENSE.txt} for license information.
|
79
|
+
|
80
|
+
[nikto]: https://github.com/sullo/nikto#readme
|
data/Rakefile
ADDED
data/gemspec.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
name: ruby-nikto
|
2
|
+
summary: A Ruby interface to Nikto.
|
3
|
+
description: A Ruby interface to Nikto, the Web Server scanner.
|
4
|
+
license: MIT
|
5
|
+
authors: Postmodern
|
6
|
+
email: postmodern.mod3@gmail.com
|
7
|
+
homepage: http://github.com/sophsec/ruby-nikto
|
8
|
+
has_yard: true
|
9
|
+
|
10
|
+
metadata:
|
11
|
+
documentation_uri: https://rubydoc.info/gems/ruby-nikto
|
12
|
+
source_code_uri: https://github.com/postmodern/ruby-nikto
|
13
|
+
bug_tracker_uri: https://github.com/postmodern/ruby-nikto/issues
|
14
|
+
changelog_uri: https://github.com/postmodern/ruby-nikto/blob/master/ChangeLog.md
|
15
|
+
rubygems_mfa_required: 'true'
|
16
|
+
|
17
|
+
requirements: nikto >= 2.1.0
|
18
|
+
|
19
|
+
dependencies:
|
20
|
+
command_mapper: ~> 0.1
|
21
|
+
nokogiri: ~> 1.0
|
22
|
+
|
23
|
+
development_dependencies:
|
24
|
+
bundler: ~> 2.0
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'command_mapper/command'
|
2
|
+
|
3
|
+
module Nikto
|
4
|
+
#
|
5
|
+
# Provides an interface for invoking the `nikto` utility.
|
6
|
+
#
|
7
|
+
# ## Example
|
8
|
+
#
|
9
|
+
# require 'nikto/command'
|
10
|
+
#
|
11
|
+
# Nikto::Command.run(host: 'example.com', output: 'nikto.xml')
|
12
|
+
#
|
13
|
+
# ## `nikto` options:
|
14
|
+
#
|
15
|
+
# * `-Cgidirs` - `nikto.cgi_dirs`
|
16
|
+
# * `-config` - `nikto.config`
|
17
|
+
# * `-dbcheck` - `nikto.dbcheck`
|
18
|
+
# * `-Display` - `nikto.display`
|
19
|
+
# * `-evasion` - `nikto.evasion`
|
20
|
+
# * `-findonly` - `nikto.find_only`
|
21
|
+
# * `-Format` - `nikto.format`
|
22
|
+
# * `-host` - `nikto.host`
|
23
|
+
# * `-Help` - `nikto.help`
|
24
|
+
# * `-id` - `nikto.id`
|
25
|
+
# * `-list-plugins` - `nikto.list_plugins`
|
26
|
+
# * `-mutate` - `nikto.mutate`
|
27
|
+
# * `-mutate-options` - `nikto.mutate_options`
|
28
|
+
# * `-nolookup` - `nikto.no_lookup`
|
29
|
+
# * `-nossl` - `nikto.no_ssl`
|
30
|
+
# * `-no404` - `nikto.no_404`
|
31
|
+
# * `-output` - `nikto.output`
|
32
|
+
# * `-plugins` - `nikto.plugins`
|
33
|
+
# * `-port` - `nikto.port`
|
34
|
+
# * `-Pause` - `nikto.pause`
|
35
|
+
# * `-root` - `nikto.root`
|
36
|
+
# * `-ssl` - `nikto.ssl`
|
37
|
+
# * `-Single` - `nikto.single`
|
38
|
+
# * `-timeout` - `nikto.timeout`
|
39
|
+
# * `-Tuning` - `nikto.tuning`
|
40
|
+
# * `-useproxy` - `nikto.use_proxy`
|
41
|
+
# * `-update` - `nikto.update`
|
42
|
+
# * `-Version` - `nikto.version`
|
43
|
+
# * `-vhost` - `nikto.vhost`
|
44
|
+
#
|
45
|
+
# @see http://linux.die.net/man/1/nikto
|
46
|
+
#
|
47
|
+
class Command < CommandMapper::Command
|
48
|
+
|
49
|
+
class OptionString < CommandMapper::Types::List
|
50
|
+
|
51
|
+
#
|
52
|
+
# @param [Hash{Symbol => String}] options
|
53
|
+
#
|
54
|
+
def initialize(options)
|
55
|
+
super(type: CommandMapper::Types::Map.new(options), separator: '')
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class PortList < CommandMapper::Types::Num
|
61
|
+
|
62
|
+
def validate(value)
|
63
|
+
case value
|
64
|
+
when Array
|
65
|
+
value.each do |element|
|
66
|
+
valid, message = validate(element)
|
67
|
+
|
68
|
+
unless valid
|
69
|
+
return [valid, message]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
return true
|
74
|
+
when Range
|
75
|
+
valid, message = super(value.begin)
|
76
|
+
|
77
|
+
unless valid
|
78
|
+
return [valid, message]
|
79
|
+
end
|
80
|
+
|
81
|
+
valid, message = super(value.end)
|
82
|
+
|
83
|
+
unless valid
|
84
|
+
return [valid, message]
|
85
|
+
end
|
86
|
+
|
87
|
+
return true
|
88
|
+
else
|
89
|
+
super(value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def format(value)
|
94
|
+
case value
|
95
|
+
when Array
|
96
|
+
value.map(&method(:format)).join(',')
|
97
|
+
when Range
|
98
|
+
"#{value.begin}-#{value.end}"
|
99
|
+
else
|
100
|
+
super(value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
command 'nikto' do
|
107
|
+
option '-Cgidirs', name: :cgi_dirs, value: true
|
108
|
+
option '-config', value: {type: InputFile.new}
|
109
|
+
option '-dbcheck'
|
110
|
+
option '-Display', value: {
|
111
|
+
type: OptionString.new(
|
112
|
+
:show_redirects => '1',
|
113
|
+
:show_cookies => '2',
|
114
|
+
:show_200_responses => '3',
|
115
|
+
:show_auth_urls => '4',
|
116
|
+
:debug => 'D',
|
117
|
+
:verbose => 'V'
|
118
|
+
)
|
119
|
+
}
|
120
|
+
|
121
|
+
option '-evasion', value: {
|
122
|
+
type: OptionString.new(
|
123
|
+
:random_uri_encoding => '1',
|
124
|
+
:directory_self_reference => '2',
|
125
|
+
:premature_url_ending => '3',
|
126
|
+
:prepend_random_strings => '4',
|
127
|
+
:fake_parameter => '5',
|
128
|
+
:tab_request_spacer => '6',
|
129
|
+
:random_url_case => '7',
|
130
|
+
:windows_directory_separator => '8'
|
131
|
+
)
|
132
|
+
}
|
133
|
+
option '-findonly', name: :find_only
|
134
|
+
option '-Format', name: :format, value: {
|
135
|
+
type: Enum[:csv, :htm, :txt, :xml]
|
136
|
+
}
|
137
|
+
option '-host', value: true
|
138
|
+
option '-Help', name: :help
|
139
|
+
option '-id', value: {type: KeyValue.new(separator: ':')}
|
140
|
+
option '-list-plugins'
|
141
|
+
option '-mutate', value: {
|
142
|
+
type: OptionString.new(
|
143
|
+
:test_all_files => '1',
|
144
|
+
:enum_password_file_names => '2',
|
145
|
+
:enum_user_dirs => '3',
|
146
|
+
:enum_cgi_users => '4',
|
147
|
+
:bruteforce_subcomdains => '5',
|
148
|
+
:bruteforce_directories => '6'
|
149
|
+
)
|
150
|
+
}
|
151
|
+
option '-mutate-options', value: true
|
152
|
+
option '-nolookup', name: :no_lookup
|
153
|
+
option '-nossl', name: :no_ssl
|
154
|
+
option '-no404', name: :no_404
|
155
|
+
option '-output', value: true
|
156
|
+
option '-plugins', value: {type: List.new}
|
157
|
+
option '-port', value: {type: PortList.new}
|
158
|
+
option '-Pause', name: :pause, value: {type: Num.new}
|
159
|
+
option '-root', value: true
|
160
|
+
option '-ssl', value: {type: PortList.new}
|
161
|
+
option '-Single', name: :single
|
162
|
+
option '-timeout', value: {type: Num.new}
|
163
|
+
option '-Tuning', name: :tuning, value: {
|
164
|
+
type: OptionString.new(
|
165
|
+
:file_upload => '0',
|
166
|
+
:interesting_files => '1',
|
167
|
+
:default_files => '2',
|
168
|
+
:information_disclosure => '3',
|
169
|
+
:injection => '4',
|
170
|
+
:remote_file_retriveal_inside_web_root => '5',
|
171
|
+
:denail_of_service => '6',
|
172
|
+
:remote_file_retriveal_server_wide => '7',
|
173
|
+
:command_execution => '8',
|
174
|
+
:sql_injection => '9',
|
175
|
+
:authentication_bypass => 'a',
|
176
|
+
:software_identification => 'b',
|
177
|
+
:remote_source_inclusion => 'c',
|
178
|
+
:reverse_tuning_options => 'x'
|
179
|
+
)
|
180
|
+
}
|
181
|
+
option '-useproxy', name: :use_proxy
|
182
|
+
option '-update'
|
183
|
+
option '-Version', name: :version
|
184
|
+
option '-vhost'
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Nikto
|
2
|
+
class XML
|
3
|
+
class Item
|
4
|
+
|
5
|
+
#
|
6
|
+
# Initializes the item object.
|
7
|
+
#
|
8
|
+
# @param [Nokogiri::XML::Node] node
|
9
|
+
# The XML node for the `item` XML element.
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
def initialize(node)
|
14
|
+
@node = node
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# The text of the `description` child element.
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
#
|
22
|
+
def description
|
23
|
+
@description ||= @node.at_xpath('description').inner_text
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# The text of the `uri` child element.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
#
|
31
|
+
def uri
|
32
|
+
@uri ||= @node.at_xpath('uri').inner_text
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# The text of the `namelink` child element.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
#
|
40
|
+
def name_link
|
41
|
+
@name_link ||= @node.at_xpath('namelink').inner_text
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# The text of the `iplink` child element.
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
#
|
49
|
+
def ip_link
|
50
|
+
@ip_link ||= @node.at_xpath('iplink').inner_text
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'nikto/xml/item'
|
2
|
+
require 'nikto/xml/statistics'
|
3
|
+
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
module Nikto
|
7
|
+
class XML
|
8
|
+
#
|
9
|
+
# Represents a `scandetails` XML element.
|
10
|
+
#
|
11
|
+
class ScanDetails
|
12
|
+
|
13
|
+
#
|
14
|
+
# Initializes the scan details object.
|
15
|
+
#
|
16
|
+
# @param [Nokogiri::XML::Node] node
|
17
|
+
# The XML node for the `scandetails` XML element.
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
#
|
21
|
+
def initialize(node)
|
22
|
+
@node = node
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# The target's IP address.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
# The value of the `targetip` attribute.
|
30
|
+
#
|
31
|
+
def target_ip
|
32
|
+
@node['targetip']
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# The target's hostname.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
# The value of the `targethostname` attribute.
|
40
|
+
#
|
41
|
+
def target_hostname
|
42
|
+
@node['targethostname']
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# The target's port number.
|
47
|
+
#
|
48
|
+
# @return [Integer]
|
49
|
+
# The parsed value of the `targetport` attribute.
|
50
|
+
#
|
51
|
+
def target_port
|
52
|
+
@target_port ||= @node['targetport'].to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# The target's banner value.
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
# The value of the `targetbanner` attribute.
|
60
|
+
#
|
61
|
+
def target_banner
|
62
|
+
@node['targetbanner']
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# When the target started being scanned.
|
67
|
+
#
|
68
|
+
# @return [Time]
|
69
|
+
# The parsed value `starttime` attribute.
|
70
|
+
#
|
71
|
+
def start_time
|
72
|
+
@start_time ||= Time.parse(@node['starttime'])
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# The site name.
|
77
|
+
#
|
78
|
+
# @return [String]
|
79
|
+
# The value of the `sitename` attribute.
|
80
|
+
#
|
81
|
+
def site_name
|
82
|
+
@node['sitename']
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# The site's IP address.
|
87
|
+
#
|
88
|
+
# @return [String]
|
89
|
+
# The value of the `siteip` attribute.
|
90
|
+
#
|
91
|
+
def site_ip
|
92
|
+
@node['siteip']
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# The `Host` header.
|
97
|
+
#
|
98
|
+
# @return [String]
|
99
|
+
# The value of the `hostheader` attribute.
|
100
|
+
#
|
101
|
+
def host_header
|
102
|
+
@node['hostheader']
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# How many errors occurred.
|
107
|
+
#
|
108
|
+
# @return [Integer]
|
109
|
+
# The parsed value of the `errors` attribute.
|
110
|
+
#
|
111
|
+
def errors
|
112
|
+
@errors ||= @node['errors'].to_i
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Determines if any errors occurred.
|
117
|
+
#
|
118
|
+
# @return [Boolean]
|
119
|
+
#
|
120
|
+
def errors?
|
121
|
+
errors > 0
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# How many checks were performed on the target.
|
126
|
+
#
|
127
|
+
# @return [Integer]
|
128
|
+
# The parsed value of the `checks` attribute.
|
129
|
+
#
|
130
|
+
def checks
|
131
|
+
@checks ||= @node['checks'].to_i
|
132
|
+
end
|
133
|
+
|
134
|
+
#
|
135
|
+
# Enumerates over the found items.
|
136
|
+
#
|
137
|
+
# @yield [item]
|
138
|
+
# If a block is given, it will be passed each item object.
|
139
|
+
#
|
140
|
+
# @yieldparam [Item] item
|
141
|
+
# An item object.
|
142
|
+
#
|
143
|
+
# @return [Enumerator]
|
144
|
+
# If no block is given, an Enumerator object will be returned.
|
145
|
+
#
|
146
|
+
def each_item
|
147
|
+
return enum_for(__method__) unless block_given?
|
148
|
+
|
149
|
+
@node.xpath('item').each do |node|
|
150
|
+
yield Item.new(node)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# The found items for the target.
|
156
|
+
#
|
157
|
+
# @return [Array<Item>]
|
158
|
+
#
|
159
|
+
def items
|
160
|
+
each_item.to_a
|
161
|
+
end
|
162
|
+
|
163
|
+
#
|
164
|
+
# The statistics associated with the scan.
|
165
|
+
#
|
166
|
+
# @return [Statistics]
|
167
|
+
# Represents the `statistics` XML element.
|
168
|
+
#
|
169
|
+
def statistics
|
170
|
+
@statistics ||= Statistics.new(@node.at_xpath('statistics'))
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|