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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d2c9bf22bc6a5d8add93c53017b015ef4c93d34
4
- data.tar.gz: 1e8b0e0240aa1bbec27895aab4df439ba393d99b
3
+ metadata.gz: 523f33ca35c02c11f2a59a1cab89e06cc6dbed10
4
+ data.tar.gz: e94e1d5cfb9df79e4e32e09e34d7e2670bafe223
5
5
  SHA512:
6
- metadata.gz: 03dccca8b8627bced9051658a17614e37d01bbf7f9331be5938479347c671aaa2d0736ddb520916ce08d6fa7285c76201162f57d36998f6dd54fc4cbf60223f1
7
- data.tar.gz: d1f61dd9ab0b18114817ca086ec0fe06930a36bd9ca14247dac43b829ef4119a2688adb1902673394acd9e8b4210a0a34d709ed7d92b4fbc869fc39923ab7044
6
+ metadata.gz: 499ca37ef4d13b353074a9ee3ea03484c87f1f633a8e4b02b93f4014f5b9be2cf4700ff0b28ab2b101e2ab491bdb7a85672379bb691b98b20d388be41ab38d33
7
+ data.tar.gz: a82121192d78b156c218bd53ecc27edf661f417c3deb028f999ae6dda7ee7b017db3af2113628e31d89c6446a4c0a4044b9cda309f2e73e9a1e59440a2e7b1a4
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
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
+ [![Gem Version](https://badge.fury.io/rb/ssh_scan.svg)](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.5 (https://github.com/claudijd/ssh_scan)
38
+ ssh_scan v0.0.6 (https://github.com/claudijd/ssh_scan)
38
39
 
39
40
  Usage: ssh_scan [options]
40
- -t, --target [IP] 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 192.168.1.1 -p 22222
49
- ssh_scan -t 192.168.1.1 -P custom_policy.yml
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
- policy = SSHScan::Policy.from_file(options[:policy])
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[:target], options[:port], policy)
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
@@ -4,8 +4,15 @@ require 'ssh_scan/protocol'
4
4
 
5
5
  module SSHScan
6
6
  class Client
7
- def initialize(ip, port)
8
- @ip = ip
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
- :ip => @ip,
32
- :port => @port,
33
- :server_banner => @server_protocol
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
@@ -96,7 +96,7 @@ module SSHScan
96
96
  missing_policy_encryption.empty? &&
97
97
  missing_policy_macs.empty? &&
98
98
  missing_policy_kex.empty? &&
99
- missing_policy_compression?
99
+ missing_policy_compression.empty?
100
100
  end
101
101
 
102
102
  def recommendations
@@ -4,9 +4,13 @@ require 'ssh_scan/client'
4
4
  module SSHScan
5
5
  class ScanEngine
6
6
 
7
- def scan(ip, port, policy = nil)
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(ip, port)
13
+ client = SSHScan::Client.new(target, port)
10
14
  client.connect()
11
15
  result = client.get_kex_result()
12
16
 
@@ -1,3 +1,3 @@
1
1
  module SSHScan
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
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.6
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-01 00:00:00.000000000 Z
11
+ date: 2016-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata