ronin-nmap 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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