ronin-nmap 0.1.0.rc1

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.document +4 -0
  3. data/.github/workflows/ruby.yml +47 -0
  4. data/.gitignore +14 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +15 -0
  7. data/.ruby-version +1 -0
  8. data/.yardopts +1 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +10 -0
  11. data/Gemfile +42 -0
  12. data/README.md +238 -0
  13. data/Rakefile +43 -0
  14. data/bin/ronin-nmap +32 -0
  15. data/data/completions/ronin-nmap +79 -0
  16. data/data/templates/script.rb.erb +58 -0
  17. data/gemspec.yml +42 -0
  18. data/lib/ronin/nmap/cli/command.rb +40 -0
  19. data/lib/ronin/nmap/cli/commands/completion.rb +61 -0
  20. data/lib/ronin/nmap/cli/commands/convert.rb +108 -0
  21. data/lib/ronin/nmap/cli/commands/dump.rb +293 -0
  22. data/lib/ronin/nmap/cli/commands/grep.rb +378 -0
  23. data/lib/ronin/nmap/cli/commands/import.rb +79 -0
  24. data/lib/ronin/nmap/cli/commands/new.rb +226 -0
  25. data/lib/ronin/nmap/cli/commands/print.rb +133 -0
  26. data/lib/ronin/nmap/cli/commands/scan.rb +233 -0
  27. data/lib/ronin/nmap/cli/filtering_options.rb +355 -0
  28. data/lib/ronin/nmap/cli/importable.rb +68 -0
  29. data/lib/ronin/nmap/cli/port_list.rb +102 -0
  30. data/lib/ronin/nmap/cli.rb +50 -0
  31. data/lib/ronin/nmap/converter.rb +114 -0
  32. data/lib/ronin/nmap/converters/csv.rb +162 -0
  33. data/lib/ronin/nmap/converters/json.rb +562 -0
  34. data/lib/ronin/nmap/converters.rb +54 -0
  35. data/lib/ronin/nmap/exceptions.rb +47 -0
  36. data/lib/ronin/nmap/importer.rb +369 -0
  37. data/lib/ronin/nmap/root.rb +28 -0
  38. data/lib/ronin/nmap/version.rb +26 -0
  39. data/lib/ronin/nmap.rb +223 -0
  40. data/man/ronin-nmap-completion.1 +76 -0
  41. data/man/ronin-nmap-completion.1.md +78 -0
  42. data/man/ronin-nmap-convert.1 +33 -0
  43. data/man/ronin-nmap-convert.1.md +36 -0
  44. data/man/ronin-nmap-dump.1 +141 -0
  45. data/man/ronin-nmap-dump.1.md +119 -0
  46. data/man/ronin-nmap-grep.1 +33 -0
  47. data/man/ronin-nmap-grep.1.md +36 -0
  48. data/man/ronin-nmap-import.1 +52 -0
  49. data/man/ronin-nmap-import.1.md +57 -0
  50. data/man/ronin-nmap-new.1 +81 -0
  51. data/man/ronin-nmap-new.1.md +73 -0
  52. data/man/ronin-nmap-print.1 +61 -0
  53. data/man/ronin-nmap-print.1.md +63 -0
  54. data/man/ronin-nmap-scan.1 +86 -0
  55. data/man/ronin-nmap-scan.1.md +84 -0
  56. data/man/ronin-nmap.1 +58 -0
  57. data/man/ronin-nmap.1.md +57 -0
  58. data/ronin-nmap.gemspec +62 -0
  59. data/scripts/setup +161 -0
  60. metadata +168 -0
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
4
+ #
5
+ # Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
6
+ #
7
+ # ronin-nmap is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-nmap is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-nmap. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/nmap/cli/command'
22
+ require 'ronin/nmap/cli/filtering_options'
23
+ require 'nmap/xml'
24
+
25
+ module Ronin
26
+ module Nmap
27
+ class CLI
28
+ module Commands
29
+ #
30
+ # Prints the scanned hosts from nmap XML file(s).
31
+ #
32
+ # ## Usage
33
+ #
34
+ # ronin-nmap print [options] XML_FILE [...]
35
+ #
36
+ # ## Options
37
+ #
38
+ # --ip IP Filters the targets by IP
39
+ # --ip-range CIDR Filter the targets by IP range
40
+ # --domain DOMAIN Filters the targets by domain
41
+ # --with-os OS Filters the targets by OS
42
+ # --with-ports {PORT | PORT1-PORT2},...
43
+ # Filter targets by port numbers
44
+ # --with-service SERVICE[,...] Filters targets by service
45
+ # --with-script SCRIPT[,...] Filters targets with the script
46
+ # --with-script-output STRING Filters targets containing the script output
47
+ # --with-script-regex /REGEX/ Filters targets containing the script output
48
+ # -h, --help Print help information
49
+ #
50
+ # ## Arguments
51
+ #
52
+ # XML_FILE ... The nmap XML file(s) to parse
53
+ #
54
+ class Print < Command
55
+
56
+ usage '[options] XML_FILE [...]'
57
+
58
+ include FilteringOptions
59
+
60
+ argument :xml_file, required: true,
61
+ repeats: true,
62
+ desc: 'The nmap XML file(s) to parse'
63
+
64
+ description 'Prints the scanned hosts from nmap XML file(s)'
65
+
66
+ man_page 'ronin-nmap-print.1'
67
+
68
+ #
69
+ # Runs the `ronin-nmap print` command.
70
+ #
71
+ # @param [Array<String>] xml_files
72
+ # The nmap XML files to parse.
73
+ #
74
+ def run(*xml_files)
75
+ xml_files.each do |xml_file|
76
+ xml = ::Nmap::XML.open(xml_file)
77
+
78
+ filter_targets(xml).each do |host|
79
+ print_target(host)
80
+ puts
81
+ end
82
+ end
83
+ end
84
+
85
+ #
86
+ # Prints the targets.
87
+ #
88
+ # @param [::Nmap::XML::Host] host
89
+ #
90
+ def print_target(host)
91
+ puts "[ #{host} ]"
92
+ puts
93
+
94
+ unless host.addresses.empty?
95
+ puts " Addresses:"
96
+ host.addresses.each do |address|
97
+ puts " #{address}"
98
+ end
99
+ puts
100
+ end
101
+
102
+ unless host.hostnames.empty?
103
+ puts " Hostnames:"
104
+ host.hostnames.each do |hostname|
105
+ puts " #{hostname}"
106
+ end
107
+ puts
108
+ end
109
+
110
+ host.each_open_port do |port|
111
+ puts " #{port.number}/#{port.protocol}\t#{port.state}\t#{port.service}"
112
+
113
+ unless port.scripts.empty?
114
+ puts
115
+
116
+ port.scripts.each_value do |script|
117
+ puts " #{script.id}:"
118
+
119
+ script.output.strip.each_line do |line|
120
+ puts " #{line}"
121
+ end
122
+
123
+ puts
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-nmap - A Ruby library for automating nmap and importing nmap scans.
4
+ #
5
+ # Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
6
+ #
7
+ # ronin-nmap is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-nmap is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-nmap. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/nmap/cli/command'
22
+ require 'ronin/nmap/cli/importable'
23
+ require 'ronin/nmap/converter'
24
+ require 'ronin/core/cli/logging'
25
+
26
+ require 'tempfile'
27
+ require 'set'
28
+
29
+ module Ronin
30
+ module Nmap
31
+ class CLI
32
+ module Commands
33
+ #
34
+ # Runs nmap and outputs data as JSON or CSV or imports into the
35
+ # database.
36
+ #
37
+ # ## Usage
38
+ #
39
+ # ronin-nmap scan [options] -- [nmap_options]
40
+ #
41
+ # ## Options
42
+ #
43
+ # --db NAME The database to connect to (Default: default)
44
+ # --db-uri URI The database URI to connect to
45
+ # --sudo Runs the nmap command under sudo
46
+ # -o, --output FILE The output file
47
+ # -F, --output-format xml|json|csv The output format
48
+ # --import Imports the scan results into the database
49
+ # -h, --help Print help information
50
+ #
51
+ # ## Arguments
52
+ #
53
+ # nmap_options ... Additional arguments for nmap
54
+ #
55
+ # ## Examples
56
+ #
57
+ # ronin-nmap scan -o scan.json -- -sV 192.168.1.1
58
+ # ronin-nmap scan --import -- -sV 192.168.1.1
59
+ #
60
+ class Scan < Command
61
+
62
+ include Importable
63
+ include Core::CLI::Logging
64
+
65
+ usage '[options] -- [nmap_options]'
66
+
67
+ option :sudo, desc: 'Runs the nmap command under sudo'
68
+
69
+ option :output, short: '-o',
70
+ value: {
71
+ type: String,
72
+ usage: 'FILE'
73
+ },
74
+ desc: 'The output file'
75
+
76
+ option :output_format, short: '-F',
77
+ value: {
78
+ type: [:xml, :json, :csv]
79
+ },
80
+ desc: 'The output format'
81
+
82
+ option :import, desc: 'Imports the scan results into the database'
83
+
84
+ argument :nmap_args, required: true,
85
+ repeats: true,
86
+ usage: 'nmap_options',
87
+ desc: 'Additional arguments for nmap'
88
+
89
+ description 'Runs nmap and outputs data as JSON or CSV or imports into the database'
90
+
91
+ examples [
92
+ '-o scan.json -- -sV 192.168.1.1',
93
+ '--import -- -sV 192.168.1.1'
94
+ ]
95
+
96
+ man_page 'ronin-nmap-scan.1'
97
+
98
+ #
99
+ # Runs the `ronin-nmap scan` command.
100
+ #
101
+ # @param [Array<String>] nmap_args
102
+ def run(*nmap_args)
103
+ if (output = options[:output])
104
+ output_format = options.fetch(:output_format) do
105
+ infer_output_format(output)
106
+ end
107
+
108
+ if output_format.nil?
109
+ print_error "cannot infer the output format of the output file (#{output.inspect}), please specify --output-format"
110
+ exit(1)
111
+ end
112
+ end
113
+
114
+ tempfile = Tempfile.new(['ronin-nmap', '.xml'])
115
+
116
+ log_info "Running nmap #{nmap_args.join(' ')} ..."
117
+
118
+ unless run_nmap(*nmap_args, output: tempfile.path)
119
+ print_error "failed to run nmap"
120
+ exit(1)
121
+ end
122
+
123
+ if output
124
+ log_info "Saving #{output_format.upcase} output to #{output} ..."
125
+ save_output(tempfile.path,output, format: output_format)
126
+ end
127
+
128
+ if options[:import]
129
+ log_info "Importing scan XML ..."
130
+ import_scan(tempfile.path)
131
+ end
132
+ end
133
+
134
+ # `nmap` options that require `sudo`.
135
+ SUDO_OPTIONS = Set[
136
+ '-sS',
137
+ '-sA',
138
+ '-sW',
139
+ '-sM',
140
+ '-sN',
141
+ '-sF',
142
+ '-sX',
143
+ '--scanflags',
144
+ '-sO',
145
+ '-O',
146
+ '--traceroute'
147
+ ]
148
+
149
+ #
150
+ # Runs the `nmap` command.
151
+ #
152
+ # @param [Array<String>] nmap_args
153
+ # Additional arguments for `nmap`.
154
+ #
155
+ # @param [String] output
156
+ # The XML output file to save the scan data to.
157
+ #
158
+ # @return [Boolean, nil]
159
+ # Indicates whether the `nmap` command was successful.
160
+ #
161
+ def run_nmap(*nmap_args, output: )
162
+ sudo = options.fetch(:sudo) do
163
+ nmap_args.any? do |arg|
164
+ SUDO_OPTIONS.include?(arg)
165
+ end
166
+ end
167
+
168
+ nmap_command = ['nmap', '-v', *nmap_args, '-oX', output]
169
+ nmap_command.unshift('sudo') if sudo
170
+
171
+ return system(*nmap_command)
172
+ end
173
+
174
+ #
175
+ # Saves the nmap scan results to an output file in the given format.
176
+ #
177
+ # @param [String] path
178
+ # The path to the nmap XML file.
179
+ #
180
+ # @param [String] output
181
+ # The path to the desired output file.
182
+ #
183
+ # @param [:xml, :json, :csv] format
184
+ # The desired output format.
185
+ #
186
+ def save_output(path,output, format: )
187
+ case format
188
+ when :xml
189
+ # copy the file if the output format is xml
190
+ FileUtils.cp(path,output)
191
+ else
192
+ # the format has been explicitly specified
193
+ Nmap::Converter.convert_file(path,output, format: format)
194
+ end
195
+ end
196
+
197
+ #
198
+ # Imports a nmap XML scan file.
199
+ #
200
+ # @param [String] path
201
+ # The path to the XML file.
202
+ #
203
+ def import_scan(path)
204
+ db_connect
205
+ import_file(path)
206
+ end
207
+
208
+ # Supported output formats.
209
+ OUTPUT_FORMATS = {
210
+ '.xml' => :xml,
211
+ '.json' => :json,
212
+ '.csv' => :csv
213
+ }
214
+
215
+ #
216
+ # Infers the output format from the given path's file extension.
217
+ #
218
+ # @param [String] path
219
+ # The path to infer the output format from.
220
+ #
221
+ # @return [:xml, :json, :csv, nil]
222
+ # The output format or `nil` if the path's file extension is
223
+ # unknown.
224
+ #
225
+ def infer_output_format(path)
226
+ OUTPUT_FORMATS[File.extname(path)]
227
+ end
228
+
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end