ssh_scan 0.0.16 → 0.0.17.pre
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 +4 -4
- data/.gitignore +15 -1
- data/.travis.yml +2 -0
- data/Gemfile +1 -0
- data/README.md +35 -33
- data/Rakefile +40 -16
- data/bin/ssh_scan +91 -53
- data/bin/ssh_scan_worker +14 -0
- data/lib/ssh_scan.rb +0 -1
- data/lib/ssh_scan/client.rb +10 -4
- data/lib/ssh_scan/constants.rb +67 -18
- data/lib/ssh_scan/crypto.rb +3 -18
- data/lib/ssh_scan/error/closed_connection.rb +1 -1
- data/lib/ssh_scan/error/connect_timeout.rb +1 -1
- data/lib/ssh_scan/error/connection_refused.rb +1 -1
- data/lib/ssh_scan/error/disconnected.rb +1 -1
- data/lib/ssh_scan/error/no_banner.rb +1 -1
- data/lib/ssh_scan/error/no_kex_response.rb +1 -1
- data/lib/ssh_scan/os/raspbian.rb +2 -4
- data/lib/ssh_scan/os/ubuntu.rb +103 -58
- data/lib/ssh_scan/policy.rb +2 -1
- data/lib/ssh_scan/policy_manager.rb +67 -18
- data/lib/ssh_scan/protocol.rb +53 -21
- data/lib/ssh_scan/scan_engine.rb +78 -44
- data/lib/ssh_scan/ssh_lib/dropbear.rb +2 -4
- data/lib/ssh_scan/target_parser.rb +3 -3
- data/lib/ssh_scan/update.rb +3 -3
- data/lib/ssh_scan/version.rb +1 -2
- data/lib/ssh_scan/worker.rb +119 -0
- data/lib/string_ext.rb +2 -1
- data/ssh_scan.gemspec +4 -8
- metadata +28 -96
- data/bin/ssh_scan_api +0 -36
- data/lib/ssh_scan/api.rb +0 -124
- data/lib/ssh_scan/fingerprint_database.rb +0 -39
- data/policies/mozilla_intermediate.yml +0 -19
- data/policies/mozilla_modern.yml +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 377880ac09b5bd925aeb32066409dd9e4c8edc7e
|
4
|
+
data.tar.gz: c3b70dcfae67ffd84ddf0d028c67486bbf71256e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16055032c71dda26d38356da8622cd827fd6fd5dd6409325b6f66af1d38c80dff0a80e86f0416807da6663e0d2dfe7472c2f78db178a766434517e46121d67f0
|
7
|
+
data.tar.gz: 913c4870b8768f85c7ada637c76060ddc045dc64e53ef1dc8d52d717a3743b52b93793d518b55b8f55056b9eafc8501443d6514cf6c63567f9c850a4a12a348d
|
data/.gitignore
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
*.gem
|
2
2
|
*.rbc
|
3
3
|
*.db
|
4
|
+
*.key
|
5
|
+
*.crt
|
6
|
+
*.cert
|
4
7
|
/.config
|
5
8
|
/coverage/
|
6
9
|
/InstalledFiles
|
@@ -29,10 +32,21 @@ build/
|
|
29
32
|
|
30
33
|
# for a library or gem, you might want to ignore these files since the code is
|
31
34
|
# intended to run in multiple environments; otherwise, check them in:
|
32
|
-
|
35
|
+
Gemfile.lock
|
33
36
|
# .ruby-version
|
34
37
|
# .ruby-gemset
|
35
38
|
|
36
39
|
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
37
40
|
.rvmrc
|
38
41
|
gh-pages/
|
42
|
+
|
43
|
+
# https ssl certificates
|
44
|
+
cert.pem
|
45
|
+
key.pem
|
46
|
+
|
47
|
+
# API Database
|
48
|
+
#ssh_scan
|
49
|
+
|
50
|
+
# Config files
|
51
|
+
bin/ssh_scan_api_example_config.yml
|
52
|
+
bin/ssh_scan_worker_example_config.yml
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[](https://codeclimate.com/github/mozilla/ssh_scan)
|
5
5
|
[](https://badge.fury.io/rb/ssh_scan)
|
6
6
|
[](https://gitter.im/mozilla-ssh_scan/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
7
|
-
|
7
|
+
[](https://coveralls.io/github/mozilla/ssh_scan?branch=master)
|
8
8
|
|
9
9
|
A SSH configuration and policy scanner
|
10
10
|
|
@@ -59,38 +59,40 @@ bundle install
|
|
59
59
|
|
60
60
|
Run `ssh_scan -h` to get this
|
61
61
|
|
62
|
-
ssh_scan v0.0.
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
62
|
+
ssh_scan v0.0.17 (https://github.com/mozilla/ssh_scan)
|
63
|
+
|
64
|
+
Usage: ssh_scan [options]
|
65
|
+
-t, --target [IP/Range/Hostname] IP/Ranges/Hostname to scan
|
66
|
+
-f, --file [FilePath] File Path of the file containing IP/Range/Hostnames to scan
|
67
|
+
-T, --timeout [seconds] Timeout per connect after which ssh_scan gives up on the host
|
68
|
+
-L, --logger [Log File Path] Enable logger
|
69
|
+
-O, --from_json [FilePath] File to read JSON output from
|
70
|
+
-o, --output [FilePath] File to write JSON output to
|
71
|
+
-p, --port [PORT] Port (Default: 22)
|
72
|
+
-P, --policy [FILE] Custom policy file (Default: Mozilla Modern)
|
73
|
+
--threads [NUMBER] Number of worker threads (Default: 5)
|
74
|
+
--fingerprint-db [FILE] File location of fingerprint database (Default: ./fingerprints.db)
|
75
|
+
--suppress-update-status Do not check for updates
|
76
|
+
-u, --unit-test [FILE] Throw appropriate exit codes based on compliance status
|
77
|
+
-V [STD_LOGGING_LEVEL], File to write JSON output to
|
78
|
+
--verbosity
|
79
|
+
-v, --version Display just version info
|
80
|
+
-l, --listen Listen and serve API requests
|
81
|
+
-h, --help Show this message
|
82
|
+
|
83
|
+
Examples:
|
84
|
+
|
85
|
+
ssh_scan -t 192.168.1.1
|
86
|
+
ssh_scan -t server.example.com
|
87
|
+
ssh_scan -t ::1
|
88
|
+
ssh_scan -t ::1 -T 5
|
89
|
+
ssh_scan -f hosts.txt
|
90
|
+
ssh_scan -o output.json
|
91
|
+
ssh_scan -O output.json -o rescan_output.json
|
92
|
+
ssh_scan -t 192.168.1.1 -p 22222
|
93
|
+
ssh_scan -t 192.168.1.1 -p 22222 -L output.log -V INFO
|
94
|
+
ssh_scan -t 192.168.1.1 -P custom_policy.yml
|
95
|
+
ssh_scan -t 192.168.1.1 --unit-test -P custom_policy.yml
|
94
96
|
|
95
97
|
- See here for [example video](https://asciinema.org/a/7pliiw5zqhj7eqvz7q437u6vx)
|
96
98
|
- See here for [example output](https://github.com/mozilla/ssh_scan/blob/master/examples/192.168.1.1.json)
|
data/Rakefile
CHANGED
@@ -22,14 +22,20 @@ TRAVELING_RUBY_VERSION = "20150210-2.1.5"
|
|
22
22
|
SQLITE3_VERSION = "1.3.9" # Must match Gemfile
|
23
23
|
|
24
24
|
desc "Package your app"
|
25
|
-
task :package => [
|
25
|
+
task :package => [
|
26
|
+
'package:linux:x86',
|
27
|
+
'package:linux:x86_64',
|
28
|
+
'package:osx',
|
29
|
+
'package:win32'
|
30
|
+
]
|
26
31
|
|
27
32
|
namespace :package do
|
28
33
|
namespace :linux do
|
29
34
|
desc "Package your app for Linux x86"
|
30
35
|
task :x86 => [:bundle_install,
|
31
36
|
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86.tar.gz",
|
32
|
-
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86-sqlite3
|
37
|
+
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86-sqlite3\
|
38
|
+
-#{SQLITE3_VERSION}.tar.gz"
|
33
39
|
] do
|
34
40
|
create_package("linux-x86")
|
35
41
|
end
|
@@ -37,7 +43,8 @@ namespace :package do
|
|
37
43
|
desc "Package your app for Linux x86_64"
|
38
44
|
task :x86_64 => [:bundle_install,
|
39
45
|
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64.tar.gz",
|
40
|
-
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64-sqlite3
|
46
|
+
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64-sqlite3\
|
47
|
+
-#{SQLITE3_VERSION}.tar.gz"
|
41
48
|
] do
|
42
49
|
create_package("linux-x86_64")
|
43
50
|
end
|
@@ -46,20 +53,23 @@ namespace :package do
|
|
46
53
|
desc "Package your app for OS X"
|
47
54
|
task :osx => [:bundle_install,
|
48
55
|
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx.tar.gz",
|
49
|
-
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx-sqlite3
|
56
|
+
"packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx-sqlite3\
|
57
|
+
-#{SQLITE3_VERSION}.tar.gz"
|
50
58
|
] do
|
51
59
|
create_package("osx")
|
52
60
|
end
|
53
61
|
|
54
62
|
desc "Package your app for Windows x86"
|
55
|
-
task :win32 => [:bundle_install, "packaging/traveling-ruby
|
63
|
+
task :win32 => [:bundle_install, "packaging/traveling-ruby\
|
64
|
+
-#{TRAVELING_RUBY_VERSION}-win32.tar.gz"] do
|
56
65
|
create_package("win32", :windows)
|
57
66
|
end
|
58
67
|
|
59
68
|
desc "Install gems to local directory"
|
60
69
|
task :bundle_install do
|
61
70
|
if RUBY_VERSION !~ /^2\.3\./
|
62
|
-
abort "You can only 'bundle install' using Ruby 2.3, because
|
71
|
+
abort "You can only 'bundle install' using Ruby 2.3, because \
|
72
|
+
that's what Traveling Ruby uses."
|
63
73
|
end
|
64
74
|
sh "rm -rf packaging/tmp"
|
65
75
|
sh "mkdir packaging/tmp"
|
@@ -69,7 +79,8 @@ namespace :package do
|
|
69
79
|
sh "cp -R bin/* packaging/tmp/bin"
|
70
80
|
sh "cp Gemfile Gemfile.lock #{PACKAGE_NAME}.gemspec packaging/tmp/"
|
71
81
|
Bundler.with_clean_env do
|
72
|
-
sh "cd packaging/tmp && env BUNDLE_IGNORE_CONFIG=1 bundle install
|
82
|
+
sh "cd packaging/tmp && env BUNDLE_IGNORE_CONFIG=1 bundle install \
|
83
|
+
--path ../vendor --without development"
|
73
84
|
end
|
74
85
|
sh "rm -rf packaging/tmp"
|
75
86
|
sh "rm -f packaging/vendor/*/*/cache/*"
|
@@ -96,15 +107,18 @@ file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-win32.tar.gz" do
|
|
96
107
|
download_runtime("win32")
|
97
108
|
end
|
98
109
|
|
99
|
-
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86-sqlite3
|
110
|
+
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86-sqlite3\
|
111
|
+
-#{SQLITE3_VERSION}.tar.gz" do
|
100
112
|
download_native_extension("linux-x86", "sqlite3-#{SQLITE3_VERSION}")
|
101
113
|
end
|
102
114
|
|
103
|
-
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64-sqlite3
|
115
|
+
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64-sqlite3\
|
116
|
+
-#{SQLITE3_VERSION}.tar.gz" do
|
104
117
|
download_native_extension("linux-x86_64", "sqlite3-#{SQLITE3_VERSION}")
|
105
118
|
end
|
106
119
|
|
107
|
-
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx-sqlite3
|
120
|
+
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx-sqlite3\
|
121
|
+
-#{SQLITE3_VERSION}.tar.gz" do
|
108
122
|
download_native_extension("osx", "sqlite3-#{SQLITE3_VERSION}")
|
109
123
|
end
|
110
124
|
|
@@ -115,7 +129,8 @@ def create_package(target, os_type = :unix)
|
|
115
129
|
sh "mkdir -p #{package_dir}/lib/app"
|
116
130
|
sh "cp bin/#{PACKAGE_NAME} #{package_dir}/lib/app/"
|
117
131
|
sh "mkdir #{package_dir}/lib/ruby"
|
118
|
-
sh "tar -xzf packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-#{target}
|
132
|
+
sh "tar -xzf packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-#{target}\
|
133
|
+
.tar.gz -C #{package_dir}/lib/ruby"
|
119
134
|
if os_type == :unix
|
120
135
|
sh "cp packaging/wrapper.sh #{package_dir}/#{PACKAGE_NAME}"
|
121
136
|
else
|
@@ -127,8 +142,14 @@ def create_package(target, os_type = :unix)
|
|
127
142
|
sh "cp Gemfile Gemfile.lock #{PACKAGE_NAME}.gemspec #{package_dir}/lib/vendor/"
|
128
143
|
sh "mkdir #{package_dir}/lib/vendor/.bundle"
|
129
144
|
sh "cp packaging/bundler-config #{package_dir}/lib/vendor/.bundle/config"
|
130
|
-
|
131
|
-
"-
|
145
|
+
if os_type == :unix
|
146
|
+
sh "tar -xzf packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-#{target}-\
|
147
|
+
sqlite3-#{SQLITE3_VERSION}.tar.gz " +
|
148
|
+
"-C #{package_dir}/lib/vendor/ruby"
|
149
|
+
else
|
150
|
+
sh "tar -xzf packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-#{target}\
|
151
|
+
.tar.gz " + "-C #{package_dir}/lib/vendor/ruby"
|
152
|
+
end
|
132
153
|
if !ENV['DIR_ONLY']
|
133
154
|
if os_type == :unix
|
134
155
|
sh "tar -czf #{package_dir}.tar.gz #{package_dir}"
|
@@ -142,10 +163,13 @@ end
|
|
142
163
|
|
143
164
|
def download_runtime(target)
|
144
165
|
sh "cd packaging && curl -L -O --fail " +
|
145
|
-
"https://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby
|
166
|
+
"https://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby-\
|
167
|
+
#{TRAVELING_RUBY_VERSION}-#{target}.tar.gz"
|
146
168
|
end
|
147
169
|
|
148
170
|
def download_native_extension(target, gem_name_and_version)
|
149
|
-
sh "curl -L --fail -o packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}
|
150
|
-
|
171
|
+
sh "curl -L --fail -o packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}\
|
172
|
+
-#{target}-#{gem_name_and_version}.tar.gz " +
|
173
|
+
"https://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby-gems-\
|
174
|
+
#{TRAVELING_RUBY_VERSION}-#{target}/#{gem_name_and_version}.tar.gz"
|
151
175
|
end
|
data/bin/ssh_scan
CHANGED
@@ -11,61 +11,83 @@ require 'logger'
|
|
11
11
|
|
12
12
|
#Default options
|
13
13
|
options = {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
"sockets" => [],
|
15
|
+
"policy" => File.join(Dir.pwd, '/config/policies/mozilla_modern.yml'),
|
16
|
+
"unit_test" => false,
|
17
|
+
"timeout" => 2,
|
18
|
+
"threads" => 5,
|
19
|
+
"verbosity" => nil,
|
20
|
+
"logger" => Logger.new(STDERR),
|
21
|
+
"fingerprint_database" => "./fingerprints.db"
|
22
22
|
}
|
23
23
|
|
24
|
+
# Reorder arguments before parsing
|
25
|
+
def reorder_args!(order, opt_parser)
|
26
|
+
old_args = opt_parser.default_argv
|
27
|
+
new_args = []
|
28
|
+
len = opt_parser.default_argv.length
|
29
|
+
order.each do |next_keyset|
|
30
|
+
i = 0
|
31
|
+
(0...len).each do
|
32
|
+
if next_keyset.include?(opt_parser.default_argv[i])
|
33
|
+
new_args << old_args.delete_at(i) << old_args.delete_at(i)
|
34
|
+
else
|
35
|
+
i += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
new_args += old_args
|
40
|
+
opt_parser.default_argv = new_args
|
41
|
+
end
|
42
|
+
|
24
43
|
target_parser = SSHScan::TargetParser.new()
|
25
44
|
|
26
45
|
opt_parser = OptionParser.new do |opts|
|
27
|
-
opts.banner =
|
28
|
-
|
46
|
+
opts.banner =
|
47
|
+
"ssh_scan v#{SSHScan::VERSION} (https://github.com/mozilla/ssh_scan)\n\n\
|
48
|
+
Usage: ssh_scan [options]"
|
29
49
|
|
30
50
|
opts.on("-t", "--target [IP/Range/Hostname]", Array,
|
31
51
|
"IP/Ranges/Hostname to scan") do |sockets|
|
32
52
|
sockets.each do |socket|
|
33
53
|
ip, port = socket.chomp.split(':')
|
34
|
-
options[
|
54
|
+
options["sockets"] += target_parser.enumerateIPRange(ip, port)
|
35
55
|
end
|
36
56
|
end
|
37
57
|
|
38
58
|
opts.on("-f", "--file [FilePath]",
|
39
|
-
"File Path of the file containing IP/Range/Hostnames to
|
40
|
-
|
59
|
+
"File Path of the file containing IP/Range/Hostnames to \
|
60
|
+
scan") do |file|
|
61
|
+
unless File.exist?(file)
|
41
62
|
puts "\nReason: input file supplied is not a file"
|
42
63
|
exit
|
43
64
|
end
|
44
65
|
File.open(file).each do |line|
|
45
66
|
line.chomp.split(',').each do |socket|
|
46
67
|
ip, port = socket.chomp.split(':')
|
47
|
-
options[
|
68
|
+
options["sockets"] += target_parser.enumerateIPRange(ip, port)
|
48
69
|
end
|
49
70
|
end
|
50
71
|
end
|
51
72
|
|
52
73
|
opts.on("-T", "--timeout [seconds]",
|
53
|
-
"Timeout per connect after which ssh_scan gives up on the
|
54
|
-
|
74
|
+
"Timeout per connect after which ssh_scan gives up on the\
|
75
|
+
host") do |timeout|
|
76
|
+
options["timeout"] = timeout.to_i
|
55
77
|
end
|
56
78
|
|
57
79
|
opts.on("-L", "--logger [Log File Path]",
|
58
80
|
"Enable logger") do |log_file|
|
59
81
|
if log_file.nil?
|
60
|
-
options[
|
82
|
+
options["logger"] = Logger.new(STDERR)
|
61
83
|
else
|
62
|
-
options[
|
84
|
+
options["logger"] = Logger.new $stdout.reopen(log_file, "w")
|
63
85
|
end
|
64
86
|
end
|
65
87
|
|
66
88
|
opts.on("-O", "--from_json [FilePath]",
|
67
89
|
"File to read JSON output from") do |file|
|
68
|
-
unless File.
|
90
|
+
unless File.exist?(file)
|
69
91
|
puts "\nReason: Invalid file"
|
70
92
|
exit
|
71
93
|
end
|
@@ -73,7 +95,10 @@ opt_parser = OptionParser.new do |opts|
|
|
73
95
|
json = file.read
|
74
96
|
parsed_json = JSON.parse(json)
|
75
97
|
parsed_json.each do |host|
|
76
|
-
options[
|
98
|
+
options["sockets"] += target_parser.enumerateIPRange(
|
99
|
+
host['ip'],
|
100
|
+
host['port']
|
101
|
+
)
|
77
102
|
end
|
78
103
|
end
|
79
104
|
|
@@ -85,54 +110,61 @@ opt_parser = OptionParser.new do |opts|
|
|
85
110
|
opts.on("-p", "--port [PORT]", Array,
|
86
111
|
"Port (Default: 22)") do |ports|
|
87
112
|
temp = []
|
88
|
-
options[
|
113
|
+
options["sockets"].each do |socket|
|
89
114
|
ports.each do |port|
|
90
115
|
ip, old_port = socket.chomp.split(':')
|
91
116
|
if !old_port.nil?
|
92
|
-
puts "Specifying port simultaneously with -t and -p is not
|
117
|
+
puts "Specifying port simultaneously with -t and -p is not\
|
118
|
+
allowed. Please fix this and try again"
|
93
119
|
exit 1
|
94
120
|
end
|
95
121
|
temp += target_parser.enumerateIPRange(ip, port)
|
96
122
|
end
|
97
123
|
end
|
98
|
-
options[
|
124
|
+
options["sockets"] = temp
|
99
125
|
end
|
100
126
|
|
101
127
|
opts.on("-P", "--policy [FILE]",
|
102
128
|
"Custom policy file (Default: Mozilla Modern)") do |policy|
|
103
|
-
options[
|
129
|
+
options["policy"] = policy
|
104
130
|
end
|
105
131
|
|
106
132
|
opts.on("--threads [NUMBER]",
|
107
133
|
"Number of worker threads (Default: 5)") do |threads|
|
108
|
-
options[
|
134
|
+
options["threads"] = threads.to_i
|
109
135
|
end
|
110
136
|
|
111
137
|
opts.on("--fingerprint-db [FILE]",
|
112
|
-
"File location of fingerprint database (Default:
|
113
|
-
|
138
|
+
"File location of fingerprint database (Default: \
|
139
|
+
./fingerprints.db)") do |fingerprint_db|
|
140
|
+
options["fingerprint_database"] = fingerprint_db
|
114
141
|
end
|
115
142
|
|
116
143
|
opts.on("--suppress-update-status", "Do not check for updates") do
|
117
|
-
options[
|
144
|
+
options["suppress_update_status"] = true
|
118
145
|
end
|
119
146
|
|
120
147
|
opts.on("-u", "--unit-test [FILE]",
|
121
148
|
"Throw appropriate exit codes based on compliance status") do
|
122
|
-
options[
|
149
|
+
options["unit_test"] = true
|
123
150
|
end
|
124
151
|
|
125
|
-
opts.on("-V", "--verbosity",
|
126
|
-
"
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
152
|
+
opts.on("-V", "--verbosity [STD_LOGGING_LEVEL]",
|
153
|
+
"File to write JSON output to") do |verb|
|
154
|
+
case verb
|
155
|
+
when "INFO"
|
156
|
+
options["logger"].level == Logger::INFO
|
157
|
+
when "WARN"
|
158
|
+
options["logger"].level == Logger::WARN
|
159
|
+
when "DEBUG"
|
160
|
+
options["logger"].level == Logger::DEBUG
|
161
|
+
when "ERROR"
|
162
|
+
options["logger"].level == Logger::ERROR
|
163
|
+
when "FATAL"
|
164
|
+
options["logger"].level == Logger::FATAL
|
165
|
+
else
|
166
|
+
options["logger"].fatal("Unrecognized logging verbosity level #{verb}")
|
167
|
+
exit 1
|
136
168
|
end
|
137
169
|
end
|
138
170
|
|
@@ -166,16 +198,17 @@ opt_parser = OptionParser.new do |opts|
|
|
166
198
|
end
|
167
199
|
end
|
168
200
|
|
201
|
+
reorder_args!([["-t", "--target"], ["-p", "--port"]], opt_parser)
|
169
202
|
opt_parser.parse!
|
170
203
|
|
171
|
-
if options[
|
204
|
+
if options["sockets"].nil?
|
172
205
|
puts opt_parser.help
|
173
206
|
puts "\nReason: no target specified"
|
174
207
|
exit 1
|
175
208
|
end
|
176
209
|
|
177
|
-
options[
|
178
|
-
ip
|
210
|
+
options["sockets"].each do |socket|
|
211
|
+
ip = socket.chomp.split(':')[0]
|
179
212
|
unless ip.ip_addr? || ip.fqdn?
|
180
213
|
puts opt_parser.help
|
181
214
|
puts "\nReason: #{socket} is not a valid target"
|
@@ -183,8 +216,8 @@ options[:sockets].each do |socket|
|
|
183
216
|
end
|
184
217
|
end
|
185
218
|
|
186
|
-
options[
|
187
|
-
|
219
|
+
options["sockets"].each do |socket|
|
220
|
+
port = socket.chomp.split(':')[1]
|
188
221
|
unless (0..65535).include?(port.to_i)
|
189
222
|
puts opt_parser.help
|
190
223
|
puts "\nReason: port supplied is not within acceptable range"
|
@@ -192,29 +225,34 @@ options[:sockets].each do |socket|
|
|
192
225
|
end
|
193
226
|
end
|
194
227
|
|
195
|
-
unless File.
|
228
|
+
unless File.exist?(options["policy"])
|
196
229
|
puts opt_parser.help
|
197
230
|
puts "\nReason: policy file supplied is not a file"
|
198
231
|
exit 1
|
199
232
|
end
|
200
233
|
|
201
234
|
# Check to see if we're running the latest released version
|
202
|
-
if !options[
|
235
|
+
if !options["suppress_update_status"]
|
203
236
|
update = SSHScan::Update.new
|
204
237
|
if update.newer_gem_available?
|
205
|
-
options[
|
238
|
+
options["logger"].warn(
|
239
|
+
"You're NOT using the latest version of ssh_scan, try 'gem update \
|
240
|
+
ssh_scan' to get the latest"
|
241
|
+
)
|
206
242
|
else
|
207
|
-
if update.errors.
|
243
|
+
if update.errors.any?
|
208
244
|
update.errors.each do |error|
|
209
|
-
options[
|
245
|
+
options["logger"].error(error)
|
210
246
|
end
|
211
247
|
else
|
212
|
-
options[
|
248
|
+
options["logger"].info(
|
249
|
+
"You're using the latest version of ssh_scan #{SSHScan::VERSION}"
|
250
|
+
)
|
213
251
|
end
|
214
252
|
end
|
215
253
|
end
|
216
254
|
|
217
|
-
options[
|
255
|
+
options["policy_file"] = SSHScan::Policy.from_file(options["policy"])
|
218
256
|
|
219
257
|
# Perform scan and get results
|
220
258
|
scan_engine = SSHScan::ScanEngine.new()
|
@@ -222,7 +260,7 @@ results = scan_engine.scan(options)
|
|
222
260
|
|
223
261
|
puts JSON.pretty_generate(results)
|
224
262
|
|
225
|
-
if options[
|
263
|
+
if options["unit_test"] == true
|
226
264
|
results.each do |result|
|
227
265
|
if result["compliance"] &&
|
228
266
|
result["compliance"][:compliant] == false
|