ssh_scan 0.0.4 → 0.0.6
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 +14 -4
- data/bin/ssh_scan +54 -12
- data/lib/ssh_scan/client.rb +40 -0
- data/lib/ssh_scan/constants.rb +18 -15
- data/lib/ssh_scan/scan_engine.rb +11 -25
- data/lib/ssh_scan/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d2c9bf22bc6a5d8add93c53017b015ef4c93d34
|
4
|
+
data.tar.gz: 1e8b0e0240aa1bbec27895aab4df439ba393d99b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03dccca8b8627bced9051658a17614e37d01bbf7f9331be5938479347c671aaa2d0736ddb520916ce08d6fa7285c76201162f57d36998f6dd54fc4cbf60223f1
|
7
|
+
data.tar.gz: d1f61dd9ab0b18114817ca086ec0fe06930a36bd9ca14247dac43b829ef4119a2688adb1902673394acd9e8b4210a0a34d709ed7d92b4fbc869fc39923ab7044
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](http://travis-ci.org/claudijd/ssh_scan)
|
4
4
|
[](https://codeclimate.com/github/claudijd/ssh_scan)
|
5
5
|
|
6
|
-
A
|
6
|
+
A SSH configuration and policy scanner
|
7
7
|
|
8
8
|
## Key Benefits
|
9
9
|
|
@@ -34,14 +34,24 @@ gem install bindata
|
|
34
34
|
|
35
35
|
Run `ssh_scan -h` to get this
|
36
36
|
|
37
|
-
|
37
|
+
ssh_scan v0.0.5 (https://github.com/claudijd/ssh_scan)
|
38
|
+
|
39
|
+
Usage: ssh_scan [options]
|
40
|
+
-t, --target [IP] IP
|
41
|
+
-p, --port [PORT] Port (Default: 22)
|
42
|
+
-P, --policy [FILE] Policy file (Default: Mozilla Modern)
|
38
43
|
-h, --help Show this message
|
39
44
|
|
40
|
-
|
41
|
-
|
45
|
+
Examples:
|
46
|
+
|
47
|
+
ssh_scan -t 192.168.1.1
|
48
|
+
ssh_scan -t 192.168.1.1 -p 22222
|
49
|
+
ssh_scan -t 192.168.1.1 -P custom_policy.yml
|
42
50
|
|
43
51
|
See here for [example output](https://github.com/claudijd/ssh_scan/blob/master/examples/192.168.1.1.json)
|
44
52
|
|
53
|
+
See here for [example policies](https://github.com/claudijd/ssh_scan/blob/master/policies)
|
54
|
+
|
45
55
|
## Rubies Supported
|
46
56
|
|
47
57
|
This project is integrated with [travis-ci](http://about.travis-ci.org/) and is regularly tested to work with the following rubies:
|
data/bin/ssh_scan
CHANGED
@@ -4,25 +4,67 @@
|
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__), "../lib")
|
5
5
|
|
6
6
|
require 'ssh_scan'
|
7
|
+
require 'optparse'
|
7
8
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
#Default options
|
10
|
+
options = {
|
11
|
+
:target => nil,
|
12
|
+
:port => 22,
|
13
|
+
:policy => File.expand_path("../../policies/mozilla_modern.yml", __FILE__)
|
14
|
+
}
|
15
|
+
opt_parser = OptionParser.new do |opts|
|
16
|
+
opts.banner = "ssh_scan v#{SSHScan::VERSION} (https://github.com/claudijd/ssh_scan)\n\n" +
|
17
|
+
"Usage: ssh_scan [options]"
|
18
|
+
|
19
|
+
opts.on("-t", "--target [IP]",
|
20
|
+
"IP") do |ip|
|
21
|
+
options[:target] = ip
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on("-p", "--port [PORT]",
|
25
|
+
"Port (Default: 22)") do |port|
|
26
|
+
options[:port] = port.to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("-P", "--policy [FILE]",
|
30
|
+
"Policy file (Default: Mozilla Modern)") do |policy|
|
31
|
+
options[:policy] = policy
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
35
|
+
puts opts
|
36
|
+
puts "\nExamples:"
|
37
|
+
puts "\n ssh_scan -t 192.168.1.1"
|
38
|
+
puts " ssh_scan -t 192.168.1.1 -p 22222"
|
39
|
+
puts " ssh_scan -t 192.168.1.1 -P custom_policy.yml"
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
opt_parser.parse!
|
45
|
+
|
46
|
+
if options[:target].nil?
|
47
|
+
puts opt_parser.help
|
48
|
+
puts "\nReason: no target specified"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
unless (0..65535).include?(options[:port])
|
53
|
+
puts opt_parser.help
|
54
|
+
puts "\nReason: port supplied is not within acceptable range"
|
15
55
|
exit
|
16
56
|
end
|
17
57
|
|
18
|
-
|
19
|
-
|
20
|
-
|
58
|
+
unless File.exists?(options[:policy])
|
59
|
+
puts opt_parser.help
|
60
|
+
puts "\nReason: policy file supplied is not a file"
|
61
|
+
exit
|
62
|
+
end
|
21
63
|
|
22
|
-
policy = SSHScan::Policy.from_file(
|
64
|
+
policy = SSHScan::Policy.from_file(options[:policy])
|
23
65
|
|
24
66
|
# Perform scan and get results
|
25
67
|
scan_engine = SSHScan::ScanEngine.new()
|
26
|
-
result = scan_engine.scan(
|
68
|
+
result = scan_engine.scan(options[:target], options[:port], policy)
|
27
69
|
|
28
70
|
puts JSON.pretty_generate(result)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'ssh_scan/constants'
|
3
|
+
require 'ssh_scan/protocol'
|
4
|
+
|
5
|
+
module SSHScan
|
6
|
+
class Client
|
7
|
+
def initialize(ip, port)
|
8
|
+
@ip = ip
|
9
|
+
@port = port
|
10
|
+
@client_protocol = SSHScan::Constants::DEFAULT_CLIENT_PROTOCOL
|
11
|
+
@server_protocol = nil
|
12
|
+
@kex_init_raw = SSHScan::Constants::DEFAULT_KEY_INIT_RAW
|
13
|
+
end
|
14
|
+
|
15
|
+
def connect()
|
16
|
+
@sock = TCPSocket.new(@ip, @port)
|
17
|
+
@server_protocol = @sock.gets.chomp
|
18
|
+
@sock.puts(@client_protocol)
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_kex_result(kex_init_raw = @kex_init_raw)
|
22
|
+
@sock.write(kex_init_raw)
|
23
|
+
resp = @sock.read(4)
|
24
|
+
resp += @sock.read(resp.unpack("N").first)
|
25
|
+
@sock.close
|
26
|
+
|
27
|
+
kex_exchange_init = SSHScan::KeyExchangeInit.read(resp)
|
28
|
+
|
29
|
+
# Assemble and print results
|
30
|
+
result = {
|
31
|
+
:ip => @ip,
|
32
|
+
:port => @port,
|
33
|
+
:server_banner => @server_protocol
|
34
|
+
}
|
35
|
+
result.merge!(kex_exchange_init.to_hash)
|
36
|
+
|
37
|
+
return result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/ssh_scan/constants.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
+
require 'string_ext'
|
2
|
+
|
1
3
|
module SSHScan
|
2
4
|
module Constants
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
5
|
+
DEFAULT_CLIENT_PROTOCOL = "SSH-2.0-client"
|
6
|
+
DEFAULT_SERVER_PROTOCOL = "SSH-2.0-server"
|
7
|
+
DEFAULT_KEY_INIT_RAW = ("d8eb97b11b6cacbc3285473f08004500019ceccf40004006663fc0a80a7c3ff" +
|
8
|
+
"5db33cdfd0016982e6062988da97e801810154d2b00000101080a03a6399f3d" +
|
9
|
+
"f735d6000001640414e33f813f8cdcc6b00a3d852ec1aea4980000001a64696" +
|
10
|
+
"66669652d68656c6c6d616e2d67726f7570312d736861310000000f7373682d" +
|
11
|
+
"6473732c7373682d727361000000576165733132382d6362632c336465732d6" +
|
12
|
+
"362632c626c6f77666973682d6362632c6165733139322d6362632c61657332" +
|
13
|
+
"35362d6362632c6165733132382d6374722c6165733139322d6374722c61657" +
|
14
|
+
"33235362d637472000000576165733132382d6362632c336465732d6362632c" +
|
15
|
+
"626c6f77666973682d6362632c6165733139322d6362632c6165733235362d6" +
|
16
|
+
"362632c6165733132382d6374722c6165733139322d6374722c616573323536" +
|
17
|
+
"2d63747200000021686d61632d6d64352c686d61632d736861312c686d61632" +
|
18
|
+
"d726970656d6431363000000021686d61632d6d64352c686d61632d73686131" +
|
19
|
+
"2c686d61632d726970656d64313630000000046e6f6e65000000046e6f6e650" +
|
20
|
+
"00000000000000000000000006e05b3b4").unhexify
|
18
21
|
end
|
19
22
|
end
|
data/lib/ssh_scan/scan_engine.rb
CHANGED
@@ -1,34 +1,20 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'ssh_scan/client'
|
2
3
|
|
3
4
|
module SSHScan
|
4
5
|
class ScanEngine
|
5
6
|
|
6
|
-
|
7
|
+
def scan(ip, port, policy = nil)
|
8
|
+
# Connect and get results
|
9
|
+
client = SSHScan::Client.new(ip, port)
|
10
|
+
client.connect()
|
11
|
+
result = client.get_kex_result()
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# Perform Key Initialization Exchange
|
15
|
-
sock.write(SSHScan::Constants::DEFAULT_KEY_INIT_RAW)
|
16
|
-
resp = sock.read(4)
|
17
|
-
resp += sock.read(resp.unpack("N").first)
|
18
|
-
kex_init_response = SSHScan::KeyExchangeInit.read(resp)
|
19
|
-
sock.close
|
20
|
-
|
21
|
-
# Assemble and print results
|
22
|
-
result = {
|
23
|
-
:ip => ip,
|
24
|
-
:port => port,
|
25
|
-
:server_banner => server_protocol.chomp
|
26
|
-
}
|
27
|
-
result.merge!(kex_init_response.to_hash)
|
28
|
-
|
29
|
-
# Evaluate for Policy Compliance
|
30
|
-
policy_mgr = SSHScan::PolicyManager.new(result, policy)
|
31
|
-
result['compliance'] = policy_mgr.compliance_results
|
13
|
+
# If policy defined, then add compliance results
|
14
|
+
unless policy.nil?
|
15
|
+
policy_mgr = SSHScan::PolicyManager.new(result, policy)
|
16
|
+
result['compliance'] = policy_mgr.compliance_results
|
17
|
+
end
|
32
18
|
|
33
19
|
return result
|
34
20
|
end
|
data/lib/ssh_scan/version.rb
CHANGED
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.6
|
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-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- bin/ssh_scan
|
98
98
|
- lib/ssh_scan.rb
|
99
99
|
- lib/ssh_scan/basic_server.rb
|
100
|
+
- lib/ssh_scan/client.rb
|
100
101
|
- lib/ssh_scan/constants.rb
|
101
102
|
- lib/ssh_scan/policy.rb
|
102
103
|
- lib/ssh_scan/policy_manager.rb
|