ssh_scan 0.0.7 → 0.0.8
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/.travis.yml +0 -3
- data/README.md +17 -11
- data/bin/ssh_scan +3 -2
- data/lib/ssh_scan/banner.rb +56 -0
- data/lib/ssh_scan/client.rb +12 -5
- data/lib/ssh_scan/constants.rb +3 -2
- data/lib/ssh_scan/os/centos.rb +13 -0
- data/lib/ssh_scan/os/debian.rb +13 -0
- data/lib/ssh_scan/os/freebsd.rb +13 -0
- data/lib/ssh_scan/os/ubuntu.rb +13 -0
- data/lib/ssh_scan/os/unknown.rb +13 -0
- data/lib/ssh_scan/os.rb +5 -0
- data/lib/ssh_scan/scan_engine.rb +30 -1
- data/lib/ssh_scan/ssh_lib/libssh.rb +13 -0
- data/lib/ssh_scan/ssh_lib/openssh.rb +13 -0
- data/lib/ssh_scan/ssh_lib/unknown.rb +13 -0
- data/lib/ssh_scan/ssh_lib.rb +3 -0
- data/lib/ssh_scan/version.rb +1 -1
- data/ssh_scan.gemspec +1 -0
- metadata +28 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a02e7aa137511342eb655ddb1040cfbe8f39e47
|
4
|
+
data.tar.gz: 0db6be22ce2c16b3d389c742142f97b1288c422f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 298a42ca4f082a1c733e30189988506b3b99d0e08aeb406daee23047242a5e4e73dd44e0845fd36ae13b3a67b59c0db6fe35b41840a08e7931833beba90c9ed6
|
7
|
+
data.tar.gz: abb0db799fe454f328e7043f9479427e09fc76360992401f4cf90e0b9db5068589cd14569d2921c56930520497a02171945bbcc08940ef1e46a837c1717072c1
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ssh_scan
|
2
2
|
|
3
|
-
[](http://travis-ci.org/mozilla/ssh_scan)
|
4
|
+
[](https://codeclimate.com/github/mozilla/ssh_scan)
|
5
5
|
[](https://badge.fury.io/rb/ssh_scan)
|
6
6
|
|
7
7
|
A SSH configuration and policy scanner
|
@@ -25,7 +25,7 @@ ssh_scan
|
|
25
25
|
To install from source, type
|
26
26
|
|
27
27
|
```bash
|
28
|
-
git clone https://github.com/
|
28
|
+
git clone https://github.com/mozilla/ssh_scan.git
|
29
29
|
cd ssh_scan
|
30
30
|
gem install bindata
|
31
31
|
./bin/ssh_scan
|
@@ -35,24 +35,30 @@ gem install bindata
|
|
35
35
|
|
36
36
|
Run `ssh_scan -h` to get this
|
37
37
|
|
38
|
-
ssh_scan v0.0.
|
38
|
+
ssh_scan v0.0.8 (https://github.com/mozilla/ssh_scan)
|
39
39
|
|
40
40
|
Usage: ssh_scan [options]
|
41
|
-
-t, --target [IP/Hostname] IP/Hostname
|
41
|
+
-t, --target [IP/Hostname] IP/Hostname (IPv4/IPv6/FQDNs)
|
42
42
|
-p, --port [PORT] Port (Default: 22)
|
43
43
|
-P, --policy [FILE] Policy file (Default: Mozilla Modern)
|
44
|
+
-u, --unit-test [FILE] Throw appropriate exit codes based on compliance status
|
45
|
+
-v, --version Display just version info
|
44
46
|
-h, --help Show this message
|
45
47
|
|
46
48
|
Examples:
|
47
49
|
|
48
50
|
ssh_scan -t 192.168.1.1
|
49
51
|
ssh_scan -t server.example.com
|
50
|
-
ssh_scan -t
|
51
|
-
ssh_scan -t
|
52
|
+
ssh_scan -t ::1
|
53
|
+
ssh_scan -t 192.168.1.1 -p 22222
|
54
|
+
ssh_scan -t 192.168.1.1 -P custom_policy.yml
|
55
|
+
ssh_scan -t 192.168.1.1 --unit-test -P custom_policy.yml
|
52
56
|
|
53
|
-
See here for [example
|
57
|
+
See here for [example video](https://asciinema.org/a/7pliiw5zqhj7eqvz7q437u6vx)
|
54
58
|
|
55
|
-
See here for [example
|
59
|
+
See here for [example output](https://github.com/mozilla/ssh_scan/blob/master/examples/192.168.1.1.json)
|
60
|
+
|
61
|
+
See here for [example policies](https://github.com/mozilla/ssh_scan/blob/master/policies)
|
56
62
|
|
57
63
|
## Rubies Supported
|
58
64
|
|
@@ -66,11 +72,11 @@ This project is integrated with [travis-ci](http://about.travis-ci.org/) and is
|
|
66
72
|
* [jruby-head](http://jruby.org/)
|
67
73
|
* [jruby-19mode](http://jruby.org/)
|
68
74
|
|
69
|
-
To checkout the current build status for these rubies, click [here](https://travis-ci.org/#!/
|
75
|
+
To checkout the current build status for these rubies, click [here](https://travis-ci.org/#!/mozilla/ssh_scan).
|
70
76
|
|
71
77
|
## Contributing
|
72
78
|
|
73
|
-
If you are interested in contributing to this project, please see [CONTRIBUTING.md](https://github.com/
|
79
|
+
If you are interested in contributing to this project, please see [CONTRIBUTING.md](https://github.com/mozilla/ssh_scan/blob/master/CONTRIBUTING.md)
|
74
80
|
|
75
81
|
## Credits
|
76
82
|
|
data/bin/ssh_scan
CHANGED
@@ -14,11 +14,11 @@ options = {
|
|
14
14
|
:unit_test => false
|
15
15
|
}
|
16
16
|
opt_parser = OptionParser.new do |opts|
|
17
|
-
opts.banner = "ssh_scan v#{SSHScan::VERSION} (https://github.com/
|
17
|
+
opts.banner = "ssh_scan v#{SSHScan::VERSION} (https://github.com/mozilla/ssh_scan)\n\n" +
|
18
18
|
"Usage: ssh_scan [options]"
|
19
19
|
|
20
20
|
opts.on("-t", "--target [IP/Hostname]",
|
21
|
-
"IP/Hostname") do |ip|
|
21
|
+
"IP/Hostname (IPv4/IPv6/FQDNs)") do |ip|
|
22
22
|
options[:target] = ip
|
23
23
|
end
|
24
24
|
|
@@ -48,6 +48,7 @@ opt_parser = OptionParser.new do |opts|
|
|
48
48
|
puts "\nExamples:"
|
49
49
|
puts "\n ssh_scan -t 192.168.1.1"
|
50
50
|
puts " ssh_scan -t server.example.com"
|
51
|
+
puts " ssh_scan -t ::1"
|
51
52
|
puts " ssh_scan -t 192.168.1.1 -p 22222"
|
52
53
|
puts " ssh_scan -t 192.168.1.1 -P custom_policy.yml"
|
53
54
|
puts " ssh_scan -t 192.168.1.1 --unit-test -P custom_policy.yml"
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ssh_scan/os'
|
2
|
+
require 'ssh_scan/ssh_lib'
|
3
|
+
|
4
|
+
module SSHScan
|
5
|
+
class Banner
|
6
|
+
def initialize(string)
|
7
|
+
@string = string
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.read(string)
|
11
|
+
return SSHScan::Banner.new(string.chomp)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ssh_version()
|
15
|
+
if version = @string.match(/SSH-(\d+[\.\d+]+)/)[1]
|
16
|
+
return version.to_f
|
17
|
+
else
|
18
|
+
return "unknown"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def ssh_lib_guess()
|
23
|
+
case @string
|
24
|
+
when /OpenSSH/i
|
25
|
+
return SSHScan::SSHLib::OpenSSH.new()
|
26
|
+
when /LibSSH/i
|
27
|
+
return SSHScan::SSHLib::LibSSH.new()
|
28
|
+
else
|
29
|
+
return SSHScan::SSHLib::Unknown.new()
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def os_guess()
|
34
|
+
case @string
|
35
|
+
when /Ubuntu/i
|
36
|
+
return SSHScan::OS::Ubuntu.new
|
37
|
+
when /CentOS/i
|
38
|
+
return SSHScan::OS::CentOS.new
|
39
|
+
when /FreeBSD/i
|
40
|
+
return SSHScan::OS::FreeBSD.new
|
41
|
+
when /Debian/i
|
42
|
+
return SSHScan::OS::Debian.new
|
43
|
+
else
|
44
|
+
return SSHScan::OS::Unknown.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(other)
|
49
|
+
self.to_s == other.to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s
|
53
|
+
@string
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/ssh_scan/client.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'ssh_scan/constants'
|
3
3
|
require 'ssh_scan/protocol'
|
4
|
+
require 'ssh_scan/banner'
|
4
5
|
|
5
6
|
module SSHScan
|
6
7
|
class Client
|
@@ -14,15 +15,16 @@ module SSHScan
|
|
14
15
|
end
|
15
16
|
|
16
17
|
@port = port
|
17
|
-
@
|
18
|
-
@
|
18
|
+
@client_banner = SSHScan::Constants::DEFAULT_CLIENT_BANNER
|
19
|
+
@server_banner = nil
|
19
20
|
@kex_init_raw = SSHScan::Constants::DEFAULT_KEY_INIT_RAW
|
20
21
|
end
|
21
22
|
|
22
23
|
def connect()
|
23
24
|
@sock = TCPSocket.new(@ip, @port)
|
24
|
-
@
|
25
|
-
@
|
25
|
+
@raw_server_banner = @sock.gets.chomp
|
26
|
+
@server_banner = SSHScan::Banner.read(@raw_server_banner)
|
27
|
+
@sock.puts(@client_banner.to_s)
|
26
28
|
end
|
27
29
|
|
28
30
|
def get_kex_result(kex_init_raw = @kex_init_raw)
|
@@ -39,7 +41,12 @@ module SSHScan
|
|
39
41
|
result[:hostname] = @target.fqdn? ? @target : ""
|
40
42
|
result[:ip] = @ip
|
41
43
|
result[:port] = @port
|
42
|
-
result[:server_banner] = @
|
44
|
+
result[:server_banner] = @server_banner
|
45
|
+
result[:ssh_version] = @server_banner.ssh_version
|
46
|
+
result[:os] = @server_banner.os_guess.common
|
47
|
+
result[:os_cpe] = @server_banner.os_guess.cpe
|
48
|
+
result[:ssh_lib] = @server_banner.ssh_lib_guess.common
|
49
|
+
result[:ssh_lib_cpe] = @server_banner.ssh_lib_guess.cpe
|
43
50
|
result.merge!(kex_exchange_init.to_hash)
|
44
51
|
|
45
52
|
return result
|
data/lib/ssh_scan/constants.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'string_ext'
|
2
|
+
require 'ssh_scan/banner'
|
2
3
|
|
3
4
|
module SSHScan
|
4
5
|
module Constants
|
5
|
-
|
6
|
-
|
6
|
+
DEFAULT_CLIENT_BANNER = SSHScan::Banner.new("SSH-2.0-ssh_scan")
|
7
|
+
DEFAULT_SERVER_BANNER = SSHScan::Banner.new("SSH-2.0-server")
|
7
8
|
DEFAULT_KEY_INIT_RAW = ("d8eb97b11b6cacbc3285473f08004500019ceccf40004006663fc0a80a7c3ff" +
|
8
9
|
"5db33cdfd0016982e6062988da97e801810154d2b00000101080a03a6399f3d" +
|
9
10
|
"f735d6000001640414e33f813f8cdcc6b00a3d852ec1aea4980000001a64696" +
|
data/lib/ssh_scan/os.rb
ADDED
data/lib/ssh_scan/scan_engine.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'ssh_scan/client'
|
3
|
+
require 'net/ssh'
|
3
4
|
|
4
5
|
module SSHScan
|
5
6
|
class ScanEngine
|
@@ -9,11 +10,39 @@ module SSHScan
|
|
9
10
|
port = opts[:port]
|
10
11
|
policy = opts[:policy_file]
|
11
12
|
|
12
|
-
# Connect and get results
|
13
|
+
# Connect and get results (native)
|
13
14
|
client = SSHScan::Client.new(target, port)
|
14
15
|
client.connect()
|
15
16
|
result = client.get_kex_result()
|
16
17
|
|
18
|
+
# Connect and get results (Net-SSH)
|
19
|
+
net_ssh_session = Net::SSH::Transport::Session.new(target)
|
20
|
+
auth_session = Net::SSH::Authentication::Session.new(net_ssh_session, :auth_methods => ["none"])
|
21
|
+
auth_session.authenticate("none", "test", "test")
|
22
|
+
result['auth_methods'] = auth_session.allowed_auth_methods
|
23
|
+
host_key = net_ssh_session.host_keys.first
|
24
|
+
net_ssh_session.close
|
25
|
+
|
26
|
+
# only supporting RSA for the moment
|
27
|
+
unless OpenSSL::PKey::RSA
|
28
|
+
raise "Unknown host key type, need to add this host_key type"
|
29
|
+
end
|
30
|
+
|
31
|
+
data_string = OpenSSL::ASN1::Sequence([
|
32
|
+
OpenSSL::ASN1::Integer.new(host_key.public_key.n),
|
33
|
+
OpenSSL::ASN1::Integer.new(host_key.public_key.e)
|
34
|
+
])
|
35
|
+
|
36
|
+
fingerprint_md5 = OpenSSL::Digest::MD5.hexdigest(data_string.to_der).scan(/../).join(':')
|
37
|
+
fingerprint_sha1 = OpenSSL::Digest::SHA1.hexdigest(data_string.to_der).scan(/../).join(':')
|
38
|
+
fingerprint_sha256 = OpenSSL::Digest::SHA256.hexdigest(data_string.to_der).scan(/../).join(':')
|
39
|
+
|
40
|
+
result['fingerprints'] = {
|
41
|
+
"md5" => fingerprint_md5,
|
42
|
+
"sha1" => fingerprint_sha1,
|
43
|
+
"sha256" => fingerprint_sha256,
|
44
|
+
}
|
45
|
+
|
17
46
|
# If policy defined, then add compliance results
|
18
47
|
unless policy.nil?
|
19
48
|
policy_mgr = SSHScan::PolicyManager.new(result, policy)
|
data/lib/ssh_scan/version.rb
CHANGED
data/ssh_scan.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.homepage = 'http://rubygems.org/gems/ssh_scan'
|
28
28
|
|
29
29
|
s.add_dependency('bindata', '~> 2.0')
|
30
|
+
s.add_dependency('net-ssh')
|
30
31
|
s.add_development_dependency('pry')
|
31
32
|
s.add_development_dependency('rspec', '~> 3.0')
|
32
33
|
s.add_development_dependency('rspec-its', '~> 1.2')
|
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.8
|
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-
|
11
|
+
date: 2016-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: net-ssh
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: pry
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,13 +110,24 @@ files:
|
|
96
110
|
- Rakefile
|
97
111
|
- bin/ssh_scan
|
98
112
|
- lib/ssh_scan.rb
|
113
|
+
- lib/ssh_scan/banner.rb
|
99
114
|
- lib/ssh_scan/basic_server.rb
|
100
115
|
- lib/ssh_scan/client.rb
|
101
116
|
- lib/ssh_scan/constants.rb
|
117
|
+
- lib/ssh_scan/os.rb
|
118
|
+
- lib/ssh_scan/os/centos.rb
|
119
|
+
- lib/ssh_scan/os/debian.rb
|
120
|
+
- lib/ssh_scan/os/freebsd.rb
|
121
|
+
- lib/ssh_scan/os/ubuntu.rb
|
122
|
+
- lib/ssh_scan/os/unknown.rb
|
102
123
|
- lib/ssh_scan/policy.rb
|
103
124
|
- lib/ssh_scan/policy_manager.rb
|
104
125
|
- lib/ssh_scan/protocol.rb
|
105
126
|
- lib/ssh_scan/scan_engine.rb
|
127
|
+
- lib/ssh_scan/ssh_lib.rb
|
128
|
+
- lib/ssh_scan/ssh_lib/libssh.rb
|
129
|
+
- lib/ssh_scan/ssh_lib/openssh.rb
|
130
|
+
- lib/ssh_scan/ssh_lib/unknown.rb
|
106
131
|
- lib/ssh_scan/version.rb
|
107
132
|
- lib/string_ext.rb
|
108
133
|
- policies/mozilla_intermediate.yml
|
@@ -128,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
153
|
version: '0'
|
129
154
|
requirements: []
|
130
155
|
rubyforge_project:
|
131
|
-
rubygems_version: 2.
|
156
|
+
rubygems_version: 2.6.2
|
132
157
|
signing_key:
|
133
158
|
specification_version: 4
|
134
159
|
summary: Ruby-based SSH Scanner
|