ssh_scan 0.0.6 → 0.0.7
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/README.md +6 -4
- data/bin/ssh_scan +32 -5
- data/lib/ssh_scan/client.rb +15 -7
- data/lib/ssh_scan/policy_manager.rb +1 -1
- data/lib/ssh_scan/scan_engine.rb +6 -2
- data/lib/ssh_scan/version.rb +1 -1
- data/lib/string_ext.rb +33 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 523f33ca35c02c11f2a59a1cab89e06cc6dbed10
|
4
|
+
data.tar.gz: e94e1d5cfb9df79e4e32e09e34d7e2670bafe223
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 499ca37ef4d13b353074a9ee3ea03484c87f1f633a8e4b02b93f4014f5b9be2cf4700ff0b28ab2b101e2ab491bdb7a85672379bb691b98b20d388be41ab38d33
|
7
|
+
data.tar.gz: a82121192d78b156c218bd53ecc27edf661f417c3deb028f999ae6dda7ee7b017db3af2113628e31d89c6446a4c0a4044b9cda309f2e73e9a1e59440a2e7b1a4
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[](http://travis-ci.org/claudijd/ssh_scan)
|
4
4
|
[](https://codeclimate.com/github/claudijd/ssh_scan)
|
5
|
+
[](https://badge.fury.io/rb/ssh_scan)
|
5
6
|
|
6
7
|
A SSH configuration and policy scanner
|
7
8
|
|
@@ -34,10 +35,10 @@ gem install bindata
|
|
34
35
|
|
35
36
|
Run `ssh_scan -h` to get this
|
36
37
|
|
37
|
-
ssh_scan v0.0.
|
38
|
+
ssh_scan v0.0.6 (https://github.com/claudijd/ssh_scan)
|
38
39
|
|
39
40
|
Usage: ssh_scan [options]
|
40
|
-
-t, --target [IP]
|
41
|
+
-t, --target [IP/Hostname] IP/Hostname
|
41
42
|
-p, --port [PORT] Port (Default: 22)
|
42
43
|
-P, --policy [FILE] Policy file (Default: Mozilla Modern)
|
43
44
|
-h, --help Show this message
|
@@ -45,8 +46,9 @@ Run `ssh_scan -h` to get this
|
|
45
46
|
Examples:
|
46
47
|
|
47
48
|
ssh_scan -t 192.168.1.1
|
48
|
-
ssh_scan -t
|
49
|
-
ssh_scan -t
|
49
|
+
ssh_scan -t server.example.com
|
50
|
+
ssh_scan -t server.example.com -p 22222
|
51
|
+
ssh_scan -t server.example.com -P custom_policy.yml
|
50
52
|
|
51
53
|
See here for [example output](https://github.com/claudijd/ssh_scan/blob/master/examples/192.168.1.1.json)
|
52
54
|
|
data/bin/ssh_scan
CHANGED
@@ -10,14 +10,15 @@ require 'optparse'
|
|
10
10
|
options = {
|
11
11
|
:target => nil,
|
12
12
|
:port => 22,
|
13
|
-
:policy => File.expand_path("../../policies/mozilla_modern.yml", __FILE__)
|
13
|
+
:policy => File.expand_path("../../policies/mozilla_modern.yml", __FILE__),
|
14
|
+
:unit_test => false
|
14
15
|
}
|
15
16
|
opt_parser = OptionParser.new do |opts|
|
16
17
|
opts.banner = "ssh_scan v#{SSHScan::VERSION} (https://github.com/claudijd/ssh_scan)\n\n" +
|
17
18
|
"Usage: ssh_scan [options]"
|
18
19
|
|
19
|
-
opts.on("-t", "--target [IP]",
|
20
|
-
"IP") do |ip|
|
20
|
+
opts.on("-t", "--target [IP/Hostname]",
|
21
|
+
"IP/Hostname") do |ip|
|
21
22
|
options[:target] = ip
|
22
23
|
end
|
23
24
|
|
@@ -31,12 +32,26 @@ opt_parser = OptionParser.new do |opts|
|
|
31
32
|
options[:policy] = policy
|
32
33
|
end
|
33
34
|
|
35
|
+
opts.on("-u", "--unit-test [FILE]",
|
36
|
+
"Throw appropriate exit codes based on compliance status") do
|
37
|
+
options[:unit_test] = true
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-v", "--version",
|
41
|
+
"Display just version info") do
|
42
|
+
puts SSHScan::VERSION
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
34
46
|
opts.on_tail("-h", "--help", "Show this message") do
|
35
47
|
puts opts
|
36
48
|
puts "\nExamples:"
|
37
49
|
puts "\n ssh_scan -t 192.168.1.1"
|
50
|
+
puts " ssh_scan -t server.example.com"
|
38
51
|
puts " ssh_scan -t 192.168.1.1 -p 22222"
|
39
52
|
puts " ssh_scan -t 192.168.1.1 -P custom_policy.yml"
|
53
|
+
puts " ssh_scan -t 192.168.1.1 --unit-test -P custom_policy.yml"
|
54
|
+
puts ""
|
40
55
|
exit
|
41
56
|
end
|
42
57
|
end
|
@@ -49,6 +64,12 @@ if options[:target].nil?
|
|
49
64
|
exit
|
50
65
|
end
|
51
66
|
|
67
|
+
unless options[:target].ip_addr? || options[:target].fqdn?
|
68
|
+
puts opt_parser.help
|
69
|
+
puts "\nReason: #{options[:target]} is not a valid target"
|
70
|
+
exit
|
71
|
+
end
|
72
|
+
|
52
73
|
unless (0..65535).include?(options[:port])
|
53
74
|
puts opt_parser.help
|
54
75
|
puts "\nReason: port supplied is not within acceptable range"
|
@@ -61,10 +82,16 @@ unless File.exists?(options[:policy])
|
|
61
82
|
exit
|
62
83
|
end
|
63
84
|
|
64
|
-
|
85
|
+
options[:policy_file] = SSHScan::Policy.from_file(options[:policy])
|
65
86
|
|
66
87
|
# Perform scan and get results
|
67
88
|
scan_engine = SSHScan::ScanEngine.new()
|
68
|
-
result = scan_engine.scan(options
|
89
|
+
result = scan_engine.scan(options)
|
69
90
|
|
70
91
|
puts JSON.pretty_generate(result)
|
92
|
+
|
93
|
+
if result["compliance"] && result["compliance"][:compliant] == false
|
94
|
+
exit 1 #non-zero means a false
|
95
|
+
else
|
96
|
+
exit 0 #non-zero means pass
|
97
|
+
end
|
data/lib/ssh_scan/client.rb
CHANGED
@@ -4,8 +4,15 @@ require 'ssh_scan/protocol'
|
|
4
4
|
|
5
5
|
module SSHScan
|
6
6
|
class Client
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(target, port)
|
8
|
+
@target = target
|
9
|
+
|
10
|
+
if @target.ip_addr?
|
11
|
+
@ip = @target
|
12
|
+
else
|
13
|
+
@ip = @target.resolve_fqdn()
|
14
|
+
end
|
15
|
+
|
9
16
|
@port = port
|
10
17
|
@client_protocol = SSHScan::Constants::DEFAULT_CLIENT_PROTOCOL
|
11
18
|
@server_protocol = nil
|
@@ -27,11 +34,12 @@ module SSHScan
|
|
27
34
|
kex_exchange_init = SSHScan::KeyExchangeInit.read(resp)
|
28
35
|
|
29
36
|
# Assemble and print results
|
30
|
-
result = {
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
result = {}
|
38
|
+
result[:ssh_scan_version] = SSHScan::VERSION
|
39
|
+
result[:hostname] = @target.fqdn? ? @target : ""
|
40
|
+
result[:ip] = @ip
|
41
|
+
result[:port] = @port
|
42
|
+
result[:server_banner] = @server_protocol
|
35
43
|
result.merge!(kex_exchange_init.to_hash)
|
36
44
|
|
37
45
|
return result
|
data/lib/ssh_scan/scan_engine.rb
CHANGED
@@ -4,9 +4,13 @@ require 'ssh_scan/client'
|
|
4
4
|
module SSHScan
|
5
5
|
class ScanEngine
|
6
6
|
|
7
|
-
def scan(
|
7
|
+
def scan(opts)
|
8
|
+
target = opts[:target]
|
9
|
+
port = opts[:port]
|
10
|
+
policy = opts[:policy_file]
|
11
|
+
|
8
12
|
# Connect and get results
|
9
|
-
client = SSHScan::Client.new(
|
13
|
+
client = SSHScan::Client.new(target, port)
|
10
14
|
client.connect()
|
11
15
|
result = client.get_kex_result()
|
12
16
|
|
data/lib/ssh_scan/version.rb
CHANGED
data/lib/string_ext.rb
CHANGED
@@ -1,6 +1,39 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
|
1
3
|
# Extend string to include some helpful stuff
|
2
4
|
class String
|
3
5
|
def unhexify
|
4
6
|
[self].pack("H*")
|
5
7
|
end
|
8
|
+
|
9
|
+
def ip_addr?
|
10
|
+
begin
|
11
|
+
IPAddr.new(self)
|
12
|
+
|
13
|
+
# Using ArgumentError instead of IPAddr::InvalidAddressError for 1.9.3 backward compatability
|
14
|
+
rescue ArgumentError
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
return true
|
19
|
+
end
|
20
|
+
|
21
|
+
def resolve_fqdn
|
22
|
+
@fqdn ||= TCPSocket.gethostbyname(self)[3]
|
23
|
+
end
|
24
|
+
|
25
|
+
def fqdn?
|
26
|
+
begin
|
27
|
+
resolve_fqdn
|
28
|
+
rescue SocketError
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
|
32
|
+
if ip_addr?
|
33
|
+
return false
|
34
|
+
else
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
6
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Claudius
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata
|