ssh_scan 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://secure.travis-ci.org/claudijd/ssh_scan.png)](http://travis-ci.org/claudijd/ssh_scan)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/claudijd/ssh_scan.png)](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
|