ruby-nikto 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,11 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ tab_width = 8
7
+ trim_trailing_whitespace = true
8
+
9
+ [{Gemfile,Rakefile,*.rb,*.gemspec,*.yml}]
10
+ indent_style = space
11
+ indent_size = 2
@@ -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
@@ -0,0 +1,9 @@
1
+ /Gemfile.lock
2
+ /doc
3
+ /pkg
4
+ .DS_Store
5
+ .yardoc
6
+ *.db
7
+ *.log
8
+ *.swp
9
+ *~
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
@@ -0,0 +1,9 @@
1
+ ### 0.1.0 / 2021-11-30
2
+
3
+ * Initial release:
4
+ * Added {Nikto::Command}.
5
+ * Added {Nikto::XML}.
6
+ * Added {Nikto::XML::ScanDetails}.
7
+ * Added {Nikto::XML::Item}.
8
+ * Added {Nikto::XML::Statistics}.
9
+
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
@@ -0,0 +1,10 @@
1
+ require 'rubygems/tasks'
2
+ Gem::Tasks.new
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+ task :test => :spec
7
+ task :default => :spec
8
+
9
+ require 'yard'
10
+ YARD::Rake::YardocTask.new
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,4 @@
1
+ module Nikto
2
+ # ruby-nikto version
3
+ VERSION = '0.1.0'
4
+ 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