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.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.github/workflows/ruby.yml +47 -0
- data/.gitignore +14 -0
- data/.rspec +1 -0
- data/.rubocop.yml +15 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +10 -0
- data/Gemfile +42 -0
- data/README.md +238 -0
- data/Rakefile +43 -0
- data/bin/ronin-nmap +32 -0
- data/data/completions/ronin-nmap +79 -0
- data/data/templates/script.rb.erb +58 -0
- data/gemspec.yml +42 -0
- data/lib/ronin/nmap/cli/command.rb +40 -0
- data/lib/ronin/nmap/cli/commands/completion.rb +61 -0
- data/lib/ronin/nmap/cli/commands/convert.rb +108 -0
- data/lib/ronin/nmap/cli/commands/dump.rb +293 -0
- data/lib/ronin/nmap/cli/commands/grep.rb +378 -0
- data/lib/ronin/nmap/cli/commands/import.rb +79 -0
- data/lib/ronin/nmap/cli/commands/new.rb +226 -0
- data/lib/ronin/nmap/cli/commands/print.rb +133 -0
- data/lib/ronin/nmap/cli/commands/scan.rb +233 -0
- data/lib/ronin/nmap/cli/filtering_options.rb +355 -0
- data/lib/ronin/nmap/cli/importable.rb +68 -0
- data/lib/ronin/nmap/cli/port_list.rb +102 -0
- data/lib/ronin/nmap/cli.rb +50 -0
- data/lib/ronin/nmap/converter.rb +114 -0
- data/lib/ronin/nmap/converters/csv.rb +162 -0
- data/lib/ronin/nmap/converters/json.rb +562 -0
- data/lib/ronin/nmap/converters.rb +54 -0
- data/lib/ronin/nmap/exceptions.rb +47 -0
- data/lib/ronin/nmap/importer.rb +369 -0
- data/lib/ronin/nmap/root.rb +28 -0
- data/lib/ronin/nmap/version.rb +26 -0
- data/lib/ronin/nmap.rb +223 -0
- data/man/ronin-nmap-completion.1 +76 -0
- data/man/ronin-nmap-completion.1.md +78 -0
- data/man/ronin-nmap-convert.1 +33 -0
- data/man/ronin-nmap-convert.1.md +36 -0
- data/man/ronin-nmap-dump.1 +141 -0
- data/man/ronin-nmap-dump.1.md +119 -0
- data/man/ronin-nmap-grep.1 +33 -0
- data/man/ronin-nmap-grep.1.md +36 -0
- data/man/ronin-nmap-import.1 +52 -0
- data/man/ronin-nmap-import.1.md +57 -0
- data/man/ronin-nmap-new.1 +81 -0
- data/man/ronin-nmap-new.1.md +73 -0
- data/man/ronin-nmap-print.1 +61 -0
- data/man/ronin-nmap-print.1.md +63 -0
- data/man/ronin-nmap-scan.1 +86 -0
- data/man/ronin-nmap-scan.1.md +84 -0
- data/man/ronin-nmap.1 +58 -0
- data/man/ronin-nmap.1.md +57 -0
- data/ronin-nmap.gemspec +62 -0
- data/scripts/setup +161 -0
- 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
|