ssh_scan 0.0.39 → 0.0.44
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +15 -8
- data/CONTRIBUTING.md +3 -3
- data/README.md +3 -4
- data/bin/ssh_scan +19 -5
- data/config/policies/just_etm_macs.yaml +24 -0
- data/lib/ssh_scan/client.rb +3 -0
- data/lib/ssh_scan/public_key.rb +7 -2
- data/lib/ssh_scan/result.rb +11 -2
- data/lib/ssh_scan/scan_engine.rb +22 -2
- data/lib/ssh_scan/ssh_fp.rb +57 -0
- data/lib/ssh_scan/target_parser.rb +11 -18
- data/lib/ssh_scan/version.rb +1 -1
- data/lib/string_ext.rb +30 -1
- data/ssh_scan.gemspec +5 -3
- metadata +44 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6174ee5e2ad23ab2ba83ecb51af937fba17db13e8dba7590ccf4b2cdb93c9aa5
|
4
|
+
data.tar.gz: dbad23e44d2f0b06625a8ae62eae20e7a7bc94a0aecadf01d143e0c9c1d4d373
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1acd0b7879e43c38b9ff19487a7a4c4c8e6bb1598a27977dfb13d1c9559d5a222d7cf1a2762325deb29536ce055f6295cbc49382f858f9211639d1de5b0891e9
|
7
|
+
data.tar.gz: 0e880c12f64ece3ba79880f880ff7b7e1fa5b916636518b373bf40985ea4f7be3a3dfca0da9fd1d974364ca26bf8ef52dda798a9357b40f2dc896520cc0ef9b2
|
data/.travis.yml
CHANGED
@@ -11,37 +11,44 @@ matrix:
|
|
11
11
|
- LABEL=unit_tests
|
12
12
|
after_success:
|
13
13
|
- coveralls
|
14
|
-
- rvm: 2.
|
14
|
+
- rvm: 2.6.7
|
15
15
|
env:
|
16
16
|
- LABEL=unit_tests
|
17
|
-
- rvm: 2.
|
17
|
+
- rvm: 2.7.3
|
18
18
|
env:
|
19
19
|
- LABEL=unit_tests
|
20
|
-
- rvm:
|
20
|
+
- rvm: 3.0.1
|
21
21
|
env:
|
22
22
|
- LABEL=unit_tests
|
23
|
-
- rvm: 2.
|
23
|
+
- rvm: 2.6.7
|
24
24
|
env:
|
25
25
|
- LABEL=gem_integration_tests
|
26
26
|
script:
|
27
27
|
- gem install ssh_scan
|
28
28
|
- chmod 755 ./spec/ssh_scan/integration.sh
|
29
29
|
- ./spec/ssh_scan/integration.sh
|
30
|
-
- rvm: 2.
|
30
|
+
- rvm: 2.7.3
|
31
31
|
env:
|
32
32
|
- LABEL=gem_integration_tests
|
33
33
|
script:
|
34
34
|
- gem install ssh_scan
|
35
35
|
- chmod 755 ./spec/ssh_scan/integration.sh
|
36
36
|
- ./spec/ssh_scan/integration.sh
|
37
|
-
- rvm:
|
37
|
+
- rvm: 3.0.1
|
38
|
+
env:
|
39
|
+
- LABEL=gem_integration_tests
|
40
|
+
script:
|
41
|
+
- gem install ssh_scan
|
42
|
+
- chmod 755 ./spec/ssh_scan/integration.sh
|
43
|
+
- ./spec/ssh_scan/integration.sh
|
44
|
+
- rvm: 2.7.3
|
38
45
|
env:
|
39
46
|
- LABEL=src_integration_tests
|
40
47
|
script:
|
41
48
|
- bundle install
|
42
49
|
- chmod 755 ./spec/ssh_scan/integration.sh
|
43
50
|
- ./spec/ssh_scan/integration.sh
|
44
|
-
- rvm:
|
51
|
+
- rvm: 3.0.1
|
45
52
|
env:
|
46
53
|
- LABEL=docker_integration_tests
|
47
54
|
services:
|
@@ -49,7 +56,7 @@ matrix:
|
|
49
56
|
script:
|
50
57
|
- docker build -t mozilla/ssh_scan .
|
51
58
|
- docker run -it mozilla/ssh_scan /app/spec/ssh_scan/integration.sh
|
52
|
-
- rvm:
|
59
|
+
- rvm: 3.0.1
|
53
60
|
env:
|
54
61
|
- LABEL=docker_build_and_push
|
55
62
|
services:
|
data/CONTRIBUTING.md
CHANGED
@@ -27,9 +27,9 @@ inclusion, but sending a pull request is much more awesome.
|
|
27
27
|
|
28
28
|
If you want your pull requests to be accepted, please follow the following guidelines:
|
29
29
|
|
30
|
-
- [**Add tests!**](
|
30
|
+
- [**Add tests!**](https://rspec.info/) Your patch won't be accepted (or will be delayed) if it doesn't have tests.
|
31
31
|
|
32
|
-
- [**Document any change in behaviour**](
|
32
|
+
- [**Document any change in behaviour**](https://yardoc.org/) Make sure the README and any other
|
33
33
|
relevant documentation are kept up-to-date.
|
34
34
|
|
35
35
|
- [**Create topic branches**](https://github.com/dchelimsky/rspec/wiki/Topic-Branches) Don't ask us to pull from your master branch.
|
@@ -37,7 +37,7 @@ If you want your pull requests to be accepted, please follow the following guide
|
|
37
37
|
- [**One pull request per feature**](https://help.github.com/articles/using-pull-requests) If you want to do more than one thing, send
|
38
38
|
multiple pull requests.
|
39
39
|
|
40
|
-
- [**Send coherent history**](
|
40
|
+
- [**Send coherent history**](https://stackoverflow.com/questions/6934752/git-combining-multiple-commits-before-pushing) Make sure each individual commit in your pull
|
41
41
|
request is meaningful. If you had to make multiple intermediate commits while
|
42
42
|
developing, please squash them before sending them to us.
|
43
43
|
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@ A SSH configuration and policy scanner
|
|
9
9
|
|
10
10
|
## Key Benefits
|
11
11
|
|
12
|
-
- **Minimal
|
12
|
+
- **Minimal Dependencies** - Uses native Ruby and BinData to do its work, no heavy dependencies.
|
13
13
|
- **Not Just a Script** - Implementation is portable for use in another project or for automation of tasks.
|
14
14
|
- **Simple** - Just point `ssh_scan` at an SSH service and get a JSON report of what it supports and its policy status.
|
15
15
|
- **Configurable** - Make your own custom policies that fit your unique policy requirements.
|
@@ -27,7 +27,7 @@ To run from a docker container, type:
|
|
27
27
|
|
28
28
|
```bash
|
29
29
|
docker pull mozilla/ssh_scan
|
30
|
-
docker run -it mozilla/ssh_scan
|
30
|
+
docker run -it mozilla/ssh_scan -t sshscan.rubidus.com
|
31
31
|
```
|
32
32
|
|
33
33
|
To install and run from source, type:
|
@@ -83,13 +83,12 @@ Examples:
|
|
83
83
|
ssh_scan -t 192.168.1.1 --unit-test -P custom_policy.yml
|
84
84
|
```
|
85
85
|
|
86
|
-
- See here for [example video](https://asciinema.org/a/7pliiw5zqhj7eqvz7q437u6vx)
|
87
86
|
- See here for [example output](https://github.com/mozilla/ssh_scan/blob/master/examples/192.168.1.1.json)
|
88
87
|
- See here for [example policies](https://github.com/mozilla/ssh_scan/blob/master/config/policies)
|
89
88
|
|
90
89
|
## ssh_scan as a service/api?
|
91
90
|
|
92
|
-
This project is
|
91
|
+
This project is solely for ssh_scan engine/command-line usage.
|
93
92
|
|
94
93
|
If you would like to run ssh_scan as a service, please refer to [the ssh_scan_api project](https://github.com/mozilla/ssh_scan_api)
|
95
94
|
|
data/bin/ssh_scan
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__), "../lib")
|
5
5
|
|
6
6
|
require 'json'
|
7
|
-
require 'netaddr'
|
8
7
|
require 'optparse'
|
9
8
|
require 'ssh_scan'
|
10
9
|
require 'logger'
|
@@ -20,7 +19,7 @@ options = {
|
|
20
19
|
"verbosity" => nil,
|
21
20
|
"logger" => Logger.new(STDERR),
|
22
21
|
"fingerprint_database" => ENV['HOME']+'/.ssh_scan_fingerprints.yml',
|
23
|
-
"output_type" =>
|
22
|
+
"output_type" => nil
|
24
23
|
}
|
25
24
|
|
26
25
|
# Reorder arguments before parsing
|
@@ -106,7 +105,8 @@ scan") do |file|
|
|
106
105
|
|
107
106
|
opts.on("-o", "--output [FilePath]",
|
108
107
|
"File to write JSON output to") do |file|
|
109
|
-
|
108
|
+
options["output"] = file
|
109
|
+
# $stdout.reopen(file, "w")
|
110
110
|
end
|
111
111
|
|
112
112
|
opts.on("--output-type [json, yaml]",
|
@@ -238,9 +238,23 @@ options["policy_file"] = SSHScan::Policy.from_file(options["policy"])
|
|
238
238
|
scan_engine = SSHScan::ScanEngine.new()
|
239
239
|
results = scan_engine.scan(options)
|
240
240
|
|
241
|
-
if options["output_type"] == "yaml"
|
241
|
+
if options["output_type"] == "yaml" && (options["output"].nil? || options["output"].empty?)
|
242
242
|
puts YAML.dump(results)
|
243
|
-
elsif options["output_type"] == "json"
|
243
|
+
elsif options["output_type"] == "json" && (options["output"].nil? || options["output"].empty?)
|
244
|
+
puts JSON.pretty_generate(results)
|
245
|
+
elsif (options["output_type"].nil? || options["output_type"].empty?) && (!options["output"].nil? && options["output"].split(".").last.downcase == "yml")
|
246
|
+
open(options["output"], 'w') do |f|
|
247
|
+
f.puts YAML.dump(results)
|
248
|
+
end
|
249
|
+
elsif (options["output_type"].nil? || options["output_type"].empty?) && (!options["output"].nil? && options["output"].split(".").last.downcase == "json")
|
250
|
+
open(options["output"], 'w') do |f|
|
251
|
+
f.puts JSON.pretty_generate(results)
|
252
|
+
end
|
253
|
+
elsif (options["output_type"].nil? || options["output_type"].empty?) && options["output"]
|
254
|
+
open(options["output"], 'w') do |f|
|
255
|
+
f.puts JSON.pretty_generate(results)
|
256
|
+
end
|
257
|
+
else
|
244
258
|
puts JSON.pretty_generate(results)
|
245
259
|
end
|
246
260
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
name: Mozilla Modern - with just ETM macs
|
3
|
+
ssh_version: 2.0
|
4
|
+
auth_methods:
|
5
|
+
- publickey
|
6
|
+
kex:
|
7
|
+
- curve25519-sha256@libssh.org
|
8
|
+
- ecdh-sha2-nistp521
|
9
|
+
- ecdh-sha2-nistp384
|
10
|
+
- ecdh-sha2-nistp256
|
11
|
+
- diffie-hellman-group-exchange-sha256
|
12
|
+
encryption:
|
13
|
+
- chacha20-poly1305@openssh.com
|
14
|
+
- aes256-gcm@openssh.com
|
15
|
+
- aes128-gcm@openssh.com
|
16
|
+
- aes256-ctr
|
17
|
+
- aes192-ctr
|
18
|
+
- aes128-ctr
|
19
|
+
macs:
|
20
|
+
- hmac-sha2-512-etm@openssh.com
|
21
|
+
- hmac-sha2-256-etm@openssh.com
|
22
|
+
- umac-128-etm@openssh.com
|
23
|
+
references:
|
24
|
+
- https://example.com/custom_policy
|
data/lib/ssh_scan/client.rb
CHANGED
@@ -70,6 +70,9 @@ module SSHScan
|
|
70
70
|
rescue Errno::EHOSTUNREACH => e
|
71
71
|
@error = SSHScan::Error::ConnectionRefused.new(e.message)
|
72
72
|
@sock = nil
|
73
|
+
rescue Errno::ENOPROTOOPT => e
|
74
|
+
@error = SSHScan::Error::ConnectionRefused.new(e.message)
|
75
|
+
@sock = nil
|
73
76
|
else
|
74
77
|
if @raw_server_banner.nil?
|
75
78
|
@error = SSHScan::Error::NoBanner.new(
|
data/lib/ssh_scan/public_key.rb
CHANGED
@@ -20,6 +20,10 @@ module SSHScan
|
|
20
20
|
return "rsa"
|
21
21
|
elsif @key_string.start_with?("ssh-dss")
|
22
22
|
return "dsa"
|
23
|
+
elsif @key_string.start_with?("ecdsa-sha2-nistp256")
|
24
|
+
return "ecdsa-sha2-nistp256"
|
25
|
+
elsif @key_string.start_with?("ssh-ed25519")
|
26
|
+
return "ed25519"
|
23
27
|
else
|
24
28
|
return "unknown"
|
25
29
|
end
|
@@ -35,10 +39,11 @@ module SSHScan
|
|
35
39
|
|
36
40
|
def fingerprint_sha1
|
37
41
|
SSHKey.sha1_fingerprint(@key_string)
|
38
|
-
end
|
42
|
+
end
|
39
43
|
|
40
44
|
def fingerprint_sha256
|
41
|
-
|
45
|
+
# We're translating this to hex because the SSHKEY default isn't as useful for comparing with SSHFP records
|
46
|
+
Base64.decode64(SSHKey.sha256_fingerprint(@key_string)).hexify(:delim => ":")
|
42
47
|
end
|
43
48
|
|
44
49
|
def to_hash
|
data/lib/ssh_scan/result.rb
CHANGED
@@ -157,12 +157,20 @@ module SSHScan
|
|
157
157
|
@auth_methods = auth_methods
|
158
158
|
end
|
159
159
|
|
160
|
+
def keys
|
161
|
+
@keys || {}
|
162
|
+
end
|
163
|
+
|
160
164
|
def keys=(keys)
|
161
165
|
@keys = keys
|
162
166
|
end
|
163
167
|
|
164
|
-
def
|
165
|
-
@
|
168
|
+
def dns_keys
|
169
|
+
@dns_keys
|
170
|
+
end
|
171
|
+
|
172
|
+
def dns_keys=(dns_keys)
|
173
|
+
@dns_keys = dns_keys
|
166
174
|
end
|
167
175
|
|
168
176
|
def duplicate_host_key_ips=(duplicate_host_key_ips)
|
@@ -250,6 +258,7 @@ module SSHScan
|
|
250
258
|
"languages_server_to_client" => self.languages_server_to_client,
|
251
259
|
"auth_methods" => self.auth_methods,
|
252
260
|
"keys" => self.keys,
|
261
|
+
"dns_keys" => self.dns_keys,
|
253
262
|
"duplicate_host_key_ips" => self.duplicate_host_key_ips.uniq,
|
254
263
|
"compliance" => @compliance,
|
255
264
|
"start_time" => self.start_time,
|
data/lib/ssh_scan/scan_engine.rb
CHANGED
@@ -3,6 +3,7 @@ require 'ssh_scan/client'
|
|
3
3
|
require 'ssh_scan/public_key'
|
4
4
|
require 'ssh_scan/fingerprint_database'
|
5
5
|
require 'ssh_scan/subprocess'
|
6
|
+
require 'ssh_scan/ssh_fp'
|
6
7
|
require 'net/ssh'
|
7
8
|
require 'logger'
|
8
9
|
require 'open3'
|
@@ -97,7 +98,7 @@ module SSHScan
|
|
97
98
|
target,
|
98
99
|
:port => port,
|
99
100
|
:timeout => timeout,
|
100
|
-
:
|
101
|
+
:verify_host_key => :never
|
101
102
|
)
|
102
103
|
raise SSHScan::Error::ClosedConnection.new if net_ssh_session.closed?
|
103
104
|
auth_session = Net::SSH::Authentication::Session.new(
|
@@ -123,7 +124,7 @@ module SSHScan
|
|
123
124
|
|
124
125
|
output = ""
|
125
126
|
|
126
|
-
cmd = ['ssh-keyscan', '-t', 'rsa,dsa', '-p', port.to_s, target].join(" ")
|
127
|
+
cmd = ['ssh-keyscan', '-t', 'rsa,dsa,ecdsa,ed25519', '-p', port.to_s, target].join(" ")
|
127
128
|
|
128
129
|
Utils::Subprocess.new(cmd) do |stdout, stderr, thread|
|
129
130
|
if stdout
|
@@ -144,6 +145,16 @@ module SSHScan
|
|
144
145
|
key = SSHScan::Crypto::PublicKey.new([host_keys[i], host_keys[i + 1]].join(" "))
|
145
146
|
keys.merge!(key.to_hash)
|
146
147
|
end
|
148
|
+
|
149
|
+
if host_keys[i].eql? "ecdsa-sha2-nistp256"
|
150
|
+
key = SSHScan::Crypto::PublicKey.new([host_keys[i], host_keys[i + 1]].join(" "))
|
151
|
+
keys.merge!(key.to_hash)
|
152
|
+
end
|
153
|
+
|
154
|
+
if host_keys[i].eql? "ssh-ed25519"
|
155
|
+
key = SSHScan::Crypto::PublicKey.new([host_keys[i], host_keys[i + 1]].join(" "))
|
156
|
+
keys.merge!(key.to_hash)
|
157
|
+
end
|
147
158
|
end
|
148
159
|
|
149
160
|
result.keys = keys
|
@@ -211,6 +222,15 @@ module SSHScan
|
|
211
222
|
end
|
212
223
|
end
|
213
224
|
|
225
|
+
# Decorate all the results with SSHFP records
|
226
|
+
sshfp = SSHScan::SshFp.new()
|
227
|
+
results.each do |result|
|
228
|
+
if !result.hostname.empty?
|
229
|
+
dns_keys = sshfp.query(result.hostname)
|
230
|
+
result.dns_keys = dns_keys
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
214
234
|
# Decorate all the results with compliance information
|
215
235
|
results.each do |result|
|
216
236
|
# Do this only when we have all the information we need
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'resolv'
|
2
|
+
|
3
|
+
module SSHScan
|
4
|
+
class SshFp
|
5
|
+
|
6
|
+
ALGO_MAP = {
|
7
|
+
0 => "reserved", # Reference: https://tools.ietf.org/html/rfc4255#section-2.4
|
8
|
+
1 => "rsa", # Reference: https://tools.ietf.org/html/rfc4255#section-2.4
|
9
|
+
2 => "dss", # Reference: https://tools.ietf.org/html/rfc4255#section-2.4
|
10
|
+
3 => "ecdsa", # Reference: https://tools.ietf.org/html/rfc6594#section-5.3.1
|
11
|
+
4 => "ed25519" # Reference: https://tools.ietf.org/html/rfc7479
|
12
|
+
}
|
13
|
+
|
14
|
+
|
15
|
+
FPTYPE_MAP = {
|
16
|
+
0 => "reserved", # Reference: https://tools.ietf.org/html/rfc4255#section-2.4
|
17
|
+
1 => "sha1", # Reference: https://tools.ietf.org/html/rfc4255#section-2.4
|
18
|
+
2 => "sha256" # Reference: https://tools.ietf.org/html/rfc6594#section-5.1.2
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
def query(fqdn)
|
23
|
+
sshfp_records = []
|
24
|
+
|
25
|
+
# try up to 5 times to resolve ssh_fp's
|
26
|
+
5.times do
|
27
|
+
|
28
|
+
# Reference: https://stackoverflow.com/questions/28867626/how-to-use-resolvdnsresourcegeneric
|
29
|
+
# Note: this includes some fixes too, I'll post a direct link back to the SO article.
|
30
|
+
Resolv::DNS.open do |dns|
|
31
|
+
all_records = dns.getresources(fqdn, Resolv::DNS::Resource::IN::ANY ) rescue nil
|
32
|
+
all_records.each do |rr|
|
33
|
+
if rr.is_a? Resolv::DNS::Resource::Generic then
|
34
|
+
classname = rr.class.name.split('::').last
|
35
|
+
if classname == "Type44_Class1"
|
36
|
+
data = rr.data.bytes
|
37
|
+
algo = data[0].to_s
|
38
|
+
fptype = data[1].to_s
|
39
|
+
fp = data[2..-1]
|
40
|
+
hex = fp.map{|b| b.to_s(16).rjust(2,'0') }.join(':')
|
41
|
+
sshfp_records << {"fptype" => FPTYPE_MAP[fptype.to_i], "algo" => ALGO_MAP[algo.to_i], "hex" => hex}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if sshfp_records.any?
|
48
|
+
return sshfp_records.sort_by { |k| k["hex"] }
|
49
|
+
end
|
50
|
+
|
51
|
+
sleep 0.5
|
52
|
+
end
|
53
|
+
|
54
|
+
return sshfp_records
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -8,7 +8,7 @@ module SSHScan
|
|
8
8
|
# @param ip [String] IP address
|
9
9
|
# @param port [Fixnum] port
|
10
10
|
# @return [Array] array of enumerated addresses
|
11
|
-
def enumerateIPRange(ip,port)
|
11
|
+
def enumerateIPRange(ip,port=nil)
|
12
12
|
if ip.fqdn?
|
13
13
|
if port.nil?
|
14
14
|
socket = ip
|
@@ -17,29 +17,22 @@ module SSHScan
|
|
17
17
|
end
|
18
18
|
return [socket]
|
19
19
|
else
|
20
|
-
if ip.include? "
|
21
|
-
octets = ip.split('.')
|
22
|
-
range = octets.pop.split('-')
|
23
|
-
lower = NetAddr::CIDR.create(octets.join('.') + "." + range[0])
|
24
|
-
upper = NetAddr::CIDR.create(octets.join('.') + "." + range[1])
|
25
|
-
ip_array = NetAddr.range(lower, upper,:Inclusive => true)
|
26
|
-
if !port.nil?
|
27
|
-
ip_array.map! { |i| i.concat(":").concat(port.to_s) }
|
28
|
-
end
|
29
|
-
return ip_array
|
30
|
-
elsif ip.include? "/"
|
20
|
+
if ip.include? "/"
|
31
21
|
begin
|
32
|
-
|
22
|
+
ip_net = NetAddr::IPv4Net.parse(ip)
|
33
23
|
rescue
|
34
24
|
raise ArgumentError, "Invalid target: #{ip}"
|
35
25
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
26
|
+
|
27
|
+
sock_array = []
|
28
|
+
1.upto(ip_net.len - 2) do |i|
|
29
|
+
sock_array << ip_net.nth(i).to_s
|
30
|
+
end
|
31
|
+
|
39
32
|
if !port.nil?
|
40
|
-
|
33
|
+
sock_array.map! { |i| i.concat(":").concat(port.to_s) }
|
41
34
|
end
|
42
|
-
return
|
35
|
+
return sock_array
|
43
36
|
else
|
44
37
|
if port.nil?
|
45
38
|
socket = ip
|
data/lib/ssh_scan/version.rb
CHANGED
data/lib/string_ext.rb
CHANGED
@@ -55,7 +55,11 @@ class String
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def resolve_fqdn
|
58
|
-
|
58
|
+
begin
|
59
|
+
IPSocket.getaddress(self)
|
60
|
+
rescue SocketError
|
61
|
+
nil # Can return anything you want here
|
62
|
+
end
|
59
63
|
end
|
60
64
|
|
61
65
|
def resolve_ptr(timeout = 3)
|
@@ -69,6 +73,31 @@ class String
|
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
76
|
+
# Stolen from: https://github.com/emonti/rbkb/blob/master/lib/rbkb/extends/string.rb
|
77
|
+
def hexify(opts={})
|
78
|
+
delim = opts[:delim]
|
79
|
+
pre = (opts[:prefix] || "")
|
80
|
+
suf = (opts[:suffix] || "")
|
81
|
+
|
82
|
+
if (rx=opts[:rx]) and not rx.kind_of? Regexp
|
83
|
+
raise "rx must be a regular expression for a character class"
|
84
|
+
end
|
85
|
+
|
86
|
+
hx = [("0".."9").to_a, ("a".."f").to_a].flatten
|
87
|
+
|
88
|
+
out=Array.new
|
89
|
+
|
90
|
+
self.each_byte do |c|
|
91
|
+
hc = if (rx and not rx.match c.chr)
|
92
|
+
c.chr
|
93
|
+
else
|
94
|
+
pre + (hx[(c >> 4)] + hx[(c & 0xf )]) + suf
|
95
|
+
end
|
96
|
+
out << (hc)
|
97
|
+
end
|
98
|
+
out.join(delim)
|
99
|
+
end
|
100
|
+
|
72
101
|
def fqdn?
|
73
102
|
begin
|
74
103
|
resolve_fqdn
|
data/ssh_scan.gemspec
CHANGED
@@ -31,12 +31,14 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.metadata["yard.run"] = "yri" # use "yard" to build full HTML docs
|
32
32
|
|
33
33
|
s.add_dependency('bindata', '2.4.3')
|
34
|
-
s.add_dependency('netaddr', '
|
35
|
-
s.add_dependency('net-ssh', '
|
34
|
+
s.add_dependency('netaddr', '2.0.4')
|
35
|
+
s.add_dependency('net-ssh', '6.0.2')
|
36
|
+
s.add_dependency('ed25519', '1.2.4')
|
37
|
+
s.add_dependency('bcrypt_pbkdf', '1.0.1')
|
36
38
|
s.add_dependency('sshkey')
|
37
39
|
s.add_development_dependency('pry', '0.11.3')
|
38
40
|
s.add_development_dependency('rspec', '3.7.0')
|
39
41
|
s.add_development_dependency('rspec-its', '1.2.0')
|
40
|
-
s.add_development_dependency
|
42
|
+
s.add_development_dependency "rake", ">= 12.3.3"
|
41
43
|
s.add_development_dependency('rubocop')
|
42
44
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssh_scan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.44
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Claudius
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
- Harsh Vardhan
|
10
10
|
- Rishabh Saxena
|
11
11
|
- Ashish Gaurav
|
12
|
-
autorequire:
|
12
|
+
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2021-05-20 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: bindata
|
@@ -34,28 +34,56 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - '='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 2.0.4
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
42
|
- - '='
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
44
|
+
version: 2.0.4
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: net-ssh
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
48
48
|
requirements:
|
49
49
|
- - '='
|
50
50
|
- !ruby/object:Gem::Version
|
51
|
-
version:
|
51
|
+
version: 6.0.2
|
52
52
|
type: :runtime
|
53
53
|
prerelease: false
|
54
54
|
version_requirements: !ruby/object:Gem::Requirement
|
55
55
|
requirements:
|
56
56
|
- - '='
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version:
|
58
|
+
version: 6.0.2
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: ed25519
|
61
|
+
requirement: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - '='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.2.4
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - '='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.2.4
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: bcrypt_pbkdf
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.0.1
|
80
|
+
type: :runtime
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - '='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 1.0.1
|
59
87
|
- !ruby/object:Gem::Dependency
|
60
88
|
name: sshkey
|
61
89
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,16 +144,16 @@ dependencies:
|
|
116
144
|
name: rake
|
117
145
|
requirement: !ruby/object:Gem::Requirement
|
118
146
|
requirements:
|
119
|
-
- -
|
147
|
+
- - ">="
|
120
148
|
- !ruby/object:Gem::Version
|
121
|
-
version: 12.3.
|
149
|
+
version: 12.3.3
|
122
150
|
type: :development
|
123
151
|
prerelease: false
|
124
152
|
version_requirements: !ruby/object:Gem::Requirement
|
125
153
|
requirements:
|
126
|
-
- -
|
154
|
+
- - ">="
|
127
155
|
- !ruby/object:Gem::Version
|
128
|
-
version: 12.3.
|
156
|
+
version: 12.3.3
|
129
157
|
- !ruby/object:Gem::Dependency
|
130
158
|
name: rubocop
|
131
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -155,6 +183,7 @@ files:
|
|
155
183
|
- README.md
|
156
184
|
- Rakefile
|
157
185
|
- bin/ssh_scan
|
186
|
+
- config/policies/just_etm_macs.yaml
|
158
187
|
- config/policies/mozilla_intermediate.yml
|
159
188
|
- config/policies/mozilla_modern.yml
|
160
189
|
- data/README
|
@@ -190,6 +219,7 @@ files:
|
|
190
219
|
- lib/ssh_scan/public_key.rb
|
191
220
|
- lib/ssh_scan/result.rb
|
192
221
|
- lib/ssh_scan/scan_engine.rb
|
222
|
+
- lib/ssh_scan/ssh_fp.rb
|
193
223
|
- lib/ssh_scan/ssh_lib.rb
|
194
224
|
- lib/ssh_scan/ssh_lib/ciscossh.rb
|
195
225
|
- lib/ssh_scan/ssh_lib/cryptlib.rb
|
@@ -217,7 +247,7 @@ licenses:
|
|
217
247
|
- ruby
|
218
248
|
metadata:
|
219
249
|
yard.run: yri
|
220
|
-
post_install_message:
|
250
|
+
post_install_message:
|
221
251
|
rdoc_options: []
|
222
252
|
require_paths:
|
223
253
|
- lib
|
@@ -232,8 +262,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
232
262
|
- !ruby/object:Gem::Version
|
233
263
|
version: '0'
|
234
264
|
requirements: []
|
235
|
-
rubygems_version: 3.
|
236
|
-
signing_key:
|
265
|
+
rubygems_version: 3.2.15
|
266
|
+
signing_key:
|
237
267
|
specification_version: 4
|
238
268
|
summary: Ruby-based SSH Scanner
|
239
269
|
test_files: []
|