ssh_scan 0.0.20 → 0.0.21
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 -0
 - data/lib/ssh_scan/banner.rb +17 -0
 - data/lib/ssh_scan/constants.rb +1 -0
 - data/lib/ssh_scan/crypto.rb +11 -0
 - data/lib/ssh_scan/error/closed_connection.rb +1 -0
 - data/lib/ssh_scan/error/connect_timeout.rb +1 -0
 - data/lib/ssh_scan/error/connection_refused.rb +1 -0
 - data/lib/ssh_scan/error/disconnected.rb +1 -0
 - data/lib/ssh_scan/error/no_banner.rb +1 -0
 - data/lib/ssh_scan/error/no_kex_response.rb +1 -0
 - data/lib/ssh_scan/fingerprint_database.rb +12 -0
 - data/lib/ssh_scan/os/raspbian.rb +5 -0
 - data/lib/ssh_scan/os/ubuntu.rb +4 -0
 - data/lib/ssh_scan/policy.rb +10 -0
 - data/lib/ssh_scan/policy_manager.rb +10 -9
 - data/lib/ssh_scan/protocol.rb +6 -0
 - data/lib/ssh_scan/scan_engine.rb +9 -0
 - data/lib/ssh_scan/target_parser.rb +5 -0
 - data/lib/ssh_scan/update.rb +9 -0
 - data/lib/ssh_scan/version.rb +1 -1
 - data/ssh_scan.gemspec +1 -0
 - metadata +4 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 504c40725362aee1beeb3795b3ea1fc7eb8af8a8
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: fcd896ac346c21474fab15b925562ec5a7c6c3e6
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ed59a66f3da720810d4834c4128c1e3b5effd68e572d46664a5d4151f89d5cc95f9a0094cdc69409d5413b1f643362fcf23289a1a9cfd4fc7f2857ffd31d199e
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: e7a761c9eb05247ec41d1fa8acb0b11d7265636934c7b5d76a940d7541212fe6a3675686ee4e8055d8f9fe3fe91d0e080ddd3e7c6cdc444ae7c589f987937879
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -99,6 +99,12 @@ Examples: 
     | 
|
| 
       99 
99 
     | 
    
         
             
            - See here for [example output](https://github.com/mozilla/ssh_scan/blob/master/examples/192.168.1.1.json)
         
     | 
| 
       100 
100 
     | 
    
         
             
            - See here for [example policies](https://github.com/mozilla/ssh_scan/blob/master/config/policies)
         
     | 
| 
       101 
101 
     | 
    
         | 
| 
      
 102 
     | 
    
         
            +
            ## ssh_scan as a service/api?
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            This project is soley for ssh_scan engine/command-line usage.
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            If you would like to run ssh_scan as a service, please refer to [the ssh_scan_api project](https://github.com/mozilla/ssh_scan_api)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
       102 
108 
     | 
    
         
             
            ## Rubies Supported
         
     | 
| 
       103 
109 
     | 
    
         | 
| 
       104 
110 
     | 
    
         
             
            This project is integrated with [travis-ci](http://about.travis-ci.org/) and is regularly tested to work with the following rubies:
         
     | 
    
        data/lib/ssh_scan/banner.rb
    CHANGED
    
    | 
         @@ -7,10 +7,19 @@ module SSHScan 
     | 
|
| 
       7 
7 
     | 
    
         
             
                  @string = string
         
     | 
| 
       8 
8 
     | 
    
         
             
                end
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
                # Create {SSHScan::Banner} object based on target's SSH banner.
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @param string [String] String from which the banner should be
         
     | 
| 
      
 12 
     | 
    
         
            +
                #   constructed.
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @return [SSHScan::Banner] {SSHScan::Banner} object
         
     | 
| 
      
 14 
     | 
    
         
            +
                #   constructed from string.
         
     | 
| 
       10 
15 
     | 
    
         
             
                def self.read(string)
         
     | 
| 
       11 
16 
     | 
    
         
             
                  return SSHScan::Banner.new(string)
         
     | 
| 
       12 
17 
     | 
    
         
             
                end
         
     | 
| 
       13 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
                # Guess target's SSH version.
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @return [String] If SSH version string looks like "SSH-1.81"
         
     | 
| 
      
 21 
     | 
    
         
            +
                #   or "SSH-number" then return the number, else return
         
     | 
| 
      
 22 
     | 
    
         
            +
                #   "unknown"
         
     | 
| 
       14 
23 
     | 
    
         
             
                def ssh_version()
         
     | 
| 
       15 
24 
     | 
    
         
             
                  if version = @string.match(/SSH-(\d+[\.\d+]+)/)[1]
         
     | 
| 
       16 
25 
     | 
    
         
             
                    return version.to_f
         
     | 
| 
         @@ -19,6 +28,10 @@ module SSHScan 
     | 
|
| 
       19 
28 
     | 
    
         
             
                  end
         
     | 
| 
       20 
29 
     | 
    
         
             
                end
         
     | 
| 
       21 
30 
     | 
    
         | 
| 
      
 31 
     | 
    
         
            +
                # Guess target's SSH Library (OpenSSH, LibSSH ...).
         
     | 
| 
      
 32 
     | 
    
         
            +
                # See {SSHScan::SSHLib} for a list of SSH libraries supported.
         
     | 
| 
      
 33 
     | 
    
         
            +
                # @return [SSHScan::SSHLib] Guessed {SSHScan::SSHLib} instance,
         
     | 
| 
      
 34 
     | 
    
         
            +
                #   otherwise {SSHScan::SSHLib::Unknown} instance.
         
     | 
| 
       22 
35 
     | 
    
         
             
                def ssh_lib_guess()
         
     | 
| 
       23 
36 
     | 
    
         
             
                  case @string
         
     | 
| 
       24 
37 
     | 
    
         
             
                  when /OpenSSH/i
         
     | 
| 
         @@ -54,6 +67,10 @@ module SSHScan 
     | 
|
| 
       54 
67 
     | 
    
         
             
                  end
         
     | 
| 
       55 
68 
     | 
    
         
             
                end
         
     | 
| 
       56 
69 
     | 
    
         | 
| 
      
 70 
     | 
    
         
            +
                # Guess target's OS (Ubuntu, CentOS ...).
         
     | 
| 
      
 71 
     | 
    
         
            +
                # See {SSHScan::OS} for a list of OS(s) supported.
         
     | 
| 
      
 72 
     | 
    
         
            +
                # @return [SSHScan::OS] Guessed {SSHScan::OS} instance,
         
     | 
| 
      
 73 
     | 
    
         
            +
                #   otherwise {SSHScan::OS::Unknown} instance. 
         
     | 
| 
       57 
74 
     | 
    
         
             
                def os_guess()
         
     | 
| 
       58 
75 
     | 
    
         
             
                  case @string
         
     | 
| 
       59 
76 
     | 
    
         
             
                  when /Ubuntu/i
         
     | 
    
        data/lib/ssh_scan/constants.rb
    CHANGED
    
    
    
        data/lib/ssh_scan/crypto.rb
    CHANGED
    
    | 
         @@ -3,13 +3,18 @@ require 'sshkey' 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require 'base64'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 6 
     | 
    
         
            +
              # All cryptography related methods.
         
     | 
| 
       6 
7 
     | 
    
         
             
              module Crypto
         
     | 
| 
      
 8 
     | 
    
         
            +
                # House methods helpful in analysing SSH public keys.
         
     | 
| 
       7 
9 
     | 
    
         
             
                class PublicKey
         
     | 
| 
       8 
10 
     | 
    
         
             
                  def initialize(key)
         
     | 
| 
       9 
11 
     | 
    
         
             
                    @key = key
         
     | 
| 
       10 
12 
     | 
    
         
             
                  end
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
       12 
14 
     | 
    
         
             
                  # Is the current key known to be in our known bad key list
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # @return [Boolean] true if this {SSHScan::Crypto::PublicKey}
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #   instance's key is also in {SSHScan::Crypto}'s
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #   bad_public_keys, otherwise false
         
     | 
| 
       13 
18 
     | 
    
         
             
                  def bad_key?
         
     | 
| 
       14 
19 
     | 
    
         
             
                    SSHScan::Crypto.bad_public_keys.each do |other_key|
         
     | 
| 
       15 
20 
     | 
    
         
             
                      if self.fingerprint_sha256 == other_key.fingerprint_sha256
         
     | 
| 
         @@ -20,14 +25,20 @@ module SSHScan 
     | 
|
| 
       20 
25 
     | 
    
         
             
                    return false
         
     | 
| 
       21 
26 
     | 
    
         
             
                  end
         
     | 
| 
       22 
27 
     | 
    
         | 
| 
      
 28 
     | 
    
         
            +
                  # Generate MD5 fingerprint for this {SSHScan::Crypto::PublicKey} instance.
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @return [String] formatted MD5 fingerprint
         
     | 
| 
       23 
30 
     | 
    
         
             
                  def fingerprint_md5
         
     | 
| 
       24 
31 
     | 
    
         
             
                    OpenSSL::Digest::MD5.hexdigest(::Base64.decode64(@key)).scan(/../).join(':')
         
     | 
| 
       25 
32 
     | 
    
         
             
                  end
         
     | 
| 
       26 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
                  # Generate SHA1 fingerprint for this {SSHScan::Crypto::PublicKey} instance.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @return [String] formatted SHA1 fingerprint
         
     | 
| 
       27 
36 
     | 
    
         
             
                  def fingerprint_sha1
         
     | 
| 
       28 
37 
     | 
    
         
             
                    OpenSSL::Digest::SHA1.hexdigest(::Base64.decode64(@key)).scan(/../).join(':')
         
     | 
| 
       29 
38 
     | 
    
         
             
                  end
         
     | 
| 
       30 
39 
     | 
    
         | 
| 
      
 40 
     | 
    
         
            +
                  # Generate SHA256 fingerprint for this {SSHScan::Crypto::PublicKey} instance.
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # @return [String] formatted SHA256 fingerprint
         
     | 
| 
       31 
42 
     | 
    
         
             
                  def fingerprint_sha256
         
     | 
| 
       32 
43 
     | 
    
         
             
                    OpenSSL::Digest::SHA256.hexdigest(::Base64.decode64(@key)).scan(/../).join(':')
         
     | 
| 
       33 
44 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1,17 +1,24 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'yaml/store'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Create and/or maintain a fingerprint database using YAML Store.
         
     | 
| 
       4 
5 
     | 
    
         
             
              class FingerprintDatabase
         
     | 
| 
       5 
6 
     | 
    
         
             
                def initialize(database_name)
         
     | 
| 
       6 
7 
     | 
    
         
             
                  @store = YAML::Store.new(database_name)
         
     | 
| 
       7 
8 
     | 
    
         
             
                end
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
                # Empty the fingerprints database for given IP.
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @param ip [String] IP for which fingerprints should be
         
     | 
| 
      
 12 
     | 
    
         
            +
                #   cleared.
         
     | 
| 
       9 
13 
     | 
    
         
             
                def clear_fingerprints(ip)
         
     | 
| 
       10 
14 
     | 
    
         
             
                  @store.transaction do
         
     | 
| 
       11 
15 
     | 
    
         
             
                    @store[ip] = []
         
     | 
| 
       12 
16 
     | 
    
         
             
                  end
         
     | 
| 
       13 
17 
     | 
    
         
             
                end
         
     | 
| 
       14 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
                # Insert a (fingerprint, IP) record.
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @param fingerprint [String] fingerprint to insert
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @param ip [String] IP for which fingerprint has to be added
         
     | 
| 
       15 
22 
     | 
    
         
             
                def add_fingerprint(fingerprint, ip)
         
     | 
| 
       16 
23 
     | 
    
         
             
                  @store.transaction do
         
     | 
| 
       17 
24 
     | 
    
         
             
                    @store[ip] = [] if @store[ip].nil?
         
     | 
| 
         @@ -19,6 +26,11 @@ module SSHScan 
     | 
|
| 
       19 
26 
     | 
    
         
             
                  end
         
     | 
| 
       20 
27 
     | 
    
         
             
                end
         
     | 
| 
       21 
28 
     | 
    
         | 
| 
      
 29 
     | 
    
         
            +
                # Find IPs that have the given fingerprint.
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @param fingerprint [String] fingerprint for which search
         
     | 
| 
      
 31 
     | 
    
         
            +
                #   should be performed
         
     | 
| 
      
 32 
     | 
    
         
            +
                # @return [Array<String>] return unique IPs for which the given
         
     | 
| 
      
 33 
     | 
    
         
            +
                #   fingerprint has an entry
         
     | 
| 
       22 
34 
     | 
    
         
             
                def find_fingerprints(fingerprint)
         
     | 
| 
       23 
35 
     | 
    
         
             
                  ip_matches = []
         
     | 
| 
       24 
36 
     | 
    
         | 
    
        data/lib/ssh_scan/os/raspbian.rb
    CHANGED
    
    | 
         @@ -18,6 +18,11 @@ module SSHScan 
     | 
|
| 
       18 
18 
     | 
    
         
             
                    @version = Raspbian::Version.new(raspbian_version_guess)
         
     | 
| 
       19 
19 
     | 
    
         
             
                  end
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                  # Guess Raspbian OS version. Typically, Raspbian banners 
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # are like "SSH-2.0-Raspbian-something", where something 
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # is the Raspbian version.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # @return [String] version string matched from banner, nil
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #   if not matched
         
     | 
| 
       21 
26 
     | 
    
         
             
                  def raspbian_version_guess
         
     | 
| 
       22 
27 
     | 
    
         
             
                    return nil if @banner.nil?
         
     | 
| 
       23 
28 
     | 
    
         
             
                    match = @banner.match(/SSH-2.0-Raspbian-(\d+)/)
         
     | 
    
        data/lib/ssh_scan/os/ubuntu.rb
    CHANGED
    
    | 
         @@ -217,6 +217,10 @@ module SSHScan 
     | 
|
| 
       217 
217 
     | 
    
         
             
                    "ubuntu"
         
     | 
| 
       218 
218 
     | 
    
         
             
                  end
         
     | 
| 
       219 
219 
     | 
    
         | 
| 
      
 220 
     | 
    
         
            +
                  # Get the FINGERPRINTS constant hash, generated from the
         
     | 
| 
      
 221 
     | 
    
         
            +
                  # scraping script.
         
     | 
| 
      
 222 
     | 
    
         
            +
                  # @return [Hash<String, Array<String>>] FINGERPRINTS constant
         
     | 
| 
      
 223 
     | 
    
         
            +
                  #   hash
         
     | 
| 
       220 
224 
     | 
    
         
             
                  def fingerprints
         
     | 
| 
       221 
225 
     | 
    
         
             
                    OS::Ubuntu::FINGERPRINTS
         
     | 
| 
       222 
226 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/ssh_scan/policy.rb
    CHANGED
    
    | 
         @@ -1,6 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'yaml'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Policy methods that deal with key exchange, macs, encryption methods,
         
     | 
| 
      
 5 
     | 
    
         
            +
              # compression methods and more.
         
     | 
| 
       4 
6 
     | 
    
         
             
              class Policy
         
     | 
| 
       5 
7 
     | 
    
         
             
                attr_reader :name, :kex, :macs, :encryption, :compression,
         
     | 
| 
       6 
8 
     | 
    
         
             
                            :references, :auth_methods, :ssh_version
         
     | 
| 
         @@ -16,11 +18,19 @@ module SSHScan 
     | 
|
| 
       16 
18 
     | 
    
         
             
                  @ssh_version = opts['ssh_version'] || false
         
     | 
| 
       17 
19 
     | 
    
         
             
                end
         
     | 
| 
       18 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
                # Generate a {SSHScan::Policy} object from YAML file.
         
     | 
| 
      
 22 
     | 
    
         
            +
                # @param file [String] filepath
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @return [SSHScan::Policy] new instance with parameters loaded
         
     | 
| 
      
 24 
     | 
    
         
            +
                #   from YAML file
         
     | 
| 
       19 
25 
     | 
    
         
             
                def self.from_file(file)
         
     | 
| 
       20 
26 
     | 
    
         
             
                  opts = YAML.load_file(file)
         
     | 
| 
       21 
27 
     | 
    
         
             
                  self.new(opts)
         
     | 
| 
       22 
28 
     | 
    
         
             
                end
         
     | 
| 
       23 
29 
     | 
    
         | 
| 
      
 30 
     | 
    
         
            +
                # Generate a {SSHScan::Policy} object from YAML string.
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @param string [String] YAML string
         
     | 
| 
      
 32 
     | 
    
         
            +
                # @return [SSHScan::Policy] new instance with parameters loaded
         
     | 
| 
      
 33 
     | 
    
         
            +
                #   from given string
         
     | 
| 
       24 
34 
     | 
    
         
             
                def self.from_string(string)
         
     | 
| 
       25 
35 
     | 
    
         
             
                  opts = YAML.load(string)
         
     | 
| 
       26 
36 
     | 
    
         
             
                  self.new(opts)
         
     | 
| 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Policy management methods, compliance checking and recommendations.
         
     | 
| 
       2 
3 
     | 
    
         
             
              class PolicyManager
         
     | 
| 
       3 
4 
     | 
    
         
             
                def initialize(result, policy)
         
     | 
| 
       4 
5 
     | 
    
         
             
                  @policy = policy
         
     | 
| 
         @@ -145,48 +146,48 @@ module SSHScan 
     | 
|
| 
       145 
146 
     | 
    
         | 
| 
       146 
147 
     | 
    
         
             
                  # Add these items to be compliant
         
     | 
| 
       147 
148 
     | 
    
         
             
                  if missing_policy_kex.any?
         
     | 
| 
       148 
     | 
    
         
            -
                    recommendations << "Add these  
     | 
| 
      
 149 
     | 
    
         
            +
                    recommendations << "Add these key exchange algorithms: \
         
     | 
| 
       149 
150 
     | 
    
         
             
            #{missing_policy_kex.join(",")}"
         
     | 
| 
       150 
151 
     | 
    
         
             
                  end
         
     | 
| 
       151 
152 
     | 
    
         | 
| 
       152 
153 
     | 
    
         
             
                  if missing_policy_macs.any?
         
     | 
| 
       153 
     | 
    
         
            -
                    recommendations << "Add these MAC  
     | 
| 
      
 154 
     | 
    
         
            +
                    recommendations << "Add these MAC algorithms: \
         
     | 
| 
       154 
155 
     | 
    
         
             
            #{missing_policy_macs.join(",")}"
         
     | 
| 
       155 
156 
     | 
    
         
             
                  end
         
     | 
| 
       156 
157 
     | 
    
         | 
| 
       157 
158 
     | 
    
         
             
                  if missing_policy_encryption.any?
         
     | 
| 
       158 
     | 
    
         
            -
                    recommendations << "Add these  
     | 
| 
      
 159 
     | 
    
         
            +
                    recommendations << "Add these encryption ciphers: \
         
     | 
| 
       159 
160 
     | 
    
         
             
            #{missing_policy_encryption.join(",")}"
         
     | 
| 
       160 
161 
     | 
    
         
             
                  end
         
     | 
| 
       161 
162 
     | 
    
         | 
| 
       162 
163 
     | 
    
         
             
                  if missing_policy_compression.any?
         
     | 
| 
       163 
     | 
    
         
            -
                    recommendations << "Add these  
     | 
| 
      
 164 
     | 
    
         
            +
                    recommendations << "Add these compression algorithms: \
         
     | 
| 
       164 
165 
     | 
    
         
             
            #{missing_policy_compression.join(",")}"
         
     | 
| 
       165 
166 
     | 
    
         
             
                  end
         
     | 
| 
       166 
167 
     | 
    
         | 
| 
       167 
168 
     | 
    
         
             
                  # Remove these items to be compliant
         
     | 
| 
       168 
169 
     | 
    
         
             
                  if out_of_policy_kex.any?
         
     | 
| 
       169 
     | 
    
         
            -
                    recommendations << "Remove these  
     | 
| 
      
 170 
     | 
    
         
            +
                    recommendations << "Remove these key exchange algorithms: \
         
     | 
| 
       170 
171 
     | 
    
         
             
            #{out_of_policy_kex.join(", ")}"
         
     | 
| 
       171 
172 
     | 
    
         
             
                  end
         
     | 
| 
       172 
173 
     | 
    
         | 
| 
       173 
174 
     | 
    
         
             
                  if out_of_policy_macs.any?
         
     | 
| 
       174 
     | 
    
         
            -
                    recommendations << "Remove these MAC  
     | 
| 
      
 175 
     | 
    
         
            +
                    recommendations << "Remove these MAC algorithms: \
         
     | 
| 
       175 
176 
     | 
    
         
             
            #{out_of_policy_macs.join(", ")}"
         
     | 
| 
       176 
177 
     | 
    
         
             
                  end
         
     | 
| 
       177 
178 
     | 
    
         | 
| 
       178 
179 
     | 
    
         
             
                  if out_of_policy_encryption.any?
         
     | 
| 
       179 
     | 
    
         
            -
                    recommendations << "Remove these  
     | 
| 
      
 180 
     | 
    
         
            +
                    recommendations << "Remove these encryption ciphers: \
         
     | 
| 
       180 
181 
     | 
    
         
             
            #{out_of_policy_encryption.join(", ")}"
         
     | 
| 
       181 
182 
     | 
    
         
             
                  end
         
     | 
| 
       182 
183 
     | 
    
         | 
| 
       183 
184 
     | 
    
         
             
                  if out_of_policy_compression.any?
         
     | 
| 
       184 
     | 
    
         
            -
                    recommendations << "Remove these  
     | 
| 
      
 185 
     | 
    
         
            +
                    recommendations << "Remove these compression algorithms: \
         
     | 
| 
       185 
186 
     | 
    
         
             
            #{out_of_policy_compression.join(", ")}"
         
     | 
| 
       186 
187 
     | 
    
         
             
                  end
         
     | 
| 
       187 
188 
     | 
    
         | 
| 
       188 
189 
     | 
    
         
             
                  if out_of_policy_auth_methods.any?
         
     | 
| 
       189 
     | 
    
         
            -
                    recommendations << "Remove these  
     | 
| 
      
 190 
     | 
    
         
            +
                    recommendations << "Remove these authentication methods: \
         
     | 
| 
       190 
191 
     | 
    
         
             
            #{out_of_policy_auth_methods.join(", ")}"
         
     | 
| 
       191 
192 
     | 
    
         
             
                  end
         
     | 
| 
       192 
193 
     | 
    
         | 
    
        data/lib/ssh_scan/protocol.rb
    CHANGED
    
    | 
         @@ -200,6 +200,7 @@ module SSHScan 
     | 
|
| 
       200 
200 
     | 
    
         
             
                end
         
     | 
| 
       201 
201 
     | 
    
         | 
| 
       202 
202 
     | 
    
         
             
                # Summarize as Hash
         
     | 
| 
      
 203 
     | 
    
         
            +
                # @return [Hash] summary
         
     | 
| 
       203 
204 
     | 
    
         
             
                def to_hash
         
     | 
| 
       204 
205 
     | 
    
         
             
                  {
         
     | 
| 
       205 
206 
     | 
    
         
             
                    :cookie => self.cookie.hexify,
         
     | 
| 
         @@ -220,6 +221,10 @@ module SSHScan 
     | 
|
| 
       220 
221 
     | 
    
         
             
                  }
         
     | 
| 
       221 
222 
     | 
    
         
             
                end
         
     | 
| 
       222 
223 
     | 
    
         | 
| 
      
 224 
     | 
    
         
            +
                # Generate a {SSHScan::KeyExchangeInit} object from given Ruby hash.
         
     | 
| 
      
 225 
     | 
    
         
            +
                # @param opts [Hash] options
         
     | 
| 
      
 226 
     | 
    
         
            +
                # @return [SSHScan::KeyExchangeInit] {SSHScan::KeyExchangeInit}
         
     | 
| 
      
 227 
     | 
    
         
            +
                #   instance initialized using passed opts
         
     | 
| 
       223 
228 
     | 
    
         
             
                def self.from_hash(opts)
         
     | 
| 
       224 
229 
     | 
    
         
             
                  kex_init = SSHScan::KeyExchangeInit.new()
         
     | 
| 
       225 
230 
     | 
    
         
             
                  kex_init.cookie = opts[:cookie]
         
     | 
| 
         @@ -244,6 +249,7 @@ module SSHScan 
     | 
|
| 
       244 
249 
     | 
    
         
             
                end
         
     | 
| 
       245 
250 
     | 
    
         | 
| 
       246 
251 
     | 
    
         
             
                # Summarize as JSON
         
     | 
| 
      
 252 
     | 
    
         
            +
                # @return [String] JSON representation for summary hash
         
     | 
| 
       247 
253 
     | 
    
         
             
                def to_json
         
     | 
| 
       248 
254 
     | 
    
         
             
                  self.to_hash.to_json
         
     | 
| 
       249 
255 
     | 
    
         
             
                end
         
     | 
    
        data/lib/ssh_scan/scan_engine.rb
    CHANGED
    
    | 
         @@ -6,8 +6,13 @@ require 'net/ssh' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            require 'logger'
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 9 
     | 
    
         
            +
              # Handle scanning of targets.
         
     | 
| 
       9 
10 
     | 
    
         
             
              class ScanEngine
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
      
 12 
     | 
    
         
            +
                # Scan a single target.
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @param socket [String] ip:port specification
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @param opts [Hash] options (timeout, ...)
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @return [Hash] result
         
     | 
| 
       11 
16 
     | 
    
         
             
                def scan_target(socket, opts)
         
     | 
| 
       12 
17 
     | 
    
         
             
                  target, port = socket.chomp.split(':')
         
     | 
| 
       13 
18 
     | 
    
         
             
                  if port.nil?
         
     | 
| 
         @@ -119,6 +124,10 @@ module SSHScan 
     | 
|
| 
       119 
124 
     | 
    
         
             
                  return result
         
     | 
| 
       120 
125 
     | 
    
         
             
                end
         
     | 
| 
       121 
126 
     | 
    
         | 
| 
      
 127 
     | 
    
         
            +
                # Utilize multiple threads to scan multiple targets, combine
         
     | 
| 
      
 128 
     | 
    
         
            +
                # results and check for compliance.
         
     | 
| 
      
 129 
     | 
    
         
            +
                # @param opts [Hash] options (sockets, threads ...)
         
     | 
| 
      
 130 
     | 
    
         
            +
                # @return [Hash] results
         
     | 
| 
       122 
131 
     | 
    
         
             
                def scan(opts)
         
     | 
| 
       123 
132 
     | 
    
         
             
                  sockets = opts["sockets"]
         
     | 
| 
       124 
133 
     | 
    
         
             
                  threads = opts["threads"] || 5
         
     | 
| 
         @@ -2,7 +2,12 @@ require 'netaddr' 
     | 
|
| 
       2 
2 
     | 
    
         
             
            require 'string_ext'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 5 
     | 
    
         
            +
              # Enumeration methods for IP notations.
         
     | 
| 
       5 
6 
     | 
    
         
             
              class TargetParser
         
     | 
| 
      
 7 
     | 
    
         
            +
                # Enumerate CIDR addresses, single IPs and IP ranges.
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @param ip [String] IP address
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @param port [Fixnum] port
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @return [Array] array of enumerated addresses
         
     | 
| 
       6 
11 
     | 
    
         
             
                def enumerateIPRange(ip,port)
         
     | 
| 
       7 
12 
     | 
    
         
             
                  if ip.fqdn?
         
     | 
| 
       8 
13 
     | 
    
         
             
                    if port.nil?
         
     | 
    
        data/lib/ssh_scan/update.rb
    CHANGED
    
    | 
         @@ -4,6 +4,7 @@ require 'ssh_scan/version' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'net/http'
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            module SSHScan
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Handle {SSHScan} updates.
         
     | 
| 
       7 
8 
     | 
    
         
             
              class Update
         
     | 
| 
       8 
9 
     | 
    
         
             
                def initialize
         
     | 
| 
       9 
10 
     | 
    
         
             
                  @errors = []
         
     | 
| 
         @@ -33,6 +34,9 @@ module SSHScan 
     | 
|
| 
       33 
34 
     | 
    
         
             
                  return [major_num.to_s, "0", "0"].join(".")
         
     | 
| 
       34 
35 
     | 
    
         
             
                end
         
     | 
| 
       35 
36 
     | 
    
         | 
| 
      
 37 
     | 
    
         
            +
                # Returns true if the given gem version exists.
         
     | 
| 
      
 38 
     | 
    
         
            +
                # @param version [String] version string
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @return [Boolean] true if given gem exists, else false
         
     | 
| 
       36 
40 
     | 
    
         
             
                def gem_exists?(version = SSHScan::VERSION)
         
     | 
| 
       37 
41 
     | 
    
         
             
                  uri = URI("https://rubygems.org/gems/ssh_scan/versions/#{version}")
         
     | 
| 
       38 
42 
     | 
    
         | 
| 
         @@ -54,6 +58,11 @@ module SSHScan 
     | 
|
| 
       54 
58 
     | 
    
         
             
                  @errors.uniq
         
     | 
| 
       55 
59 
     | 
    
         
             
                end
         
     | 
| 
       56 
60 
     | 
    
         | 
| 
      
 61 
     | 
    
         
            +
                # Tries to check if the next patch, minor or major version
         
     | 
| 
      
 62 
     | 
    
         
            +
                # is available or not. If so, returns true.
         
     | 
| 
      
 63 
     | 
    
         
            +
                # @param version [String] version string
         
     | 
| 
      
 64 
     | 
    
         
            +
                # @return [Boolean] true if next major/minor version available,
         
     | 
| 
      
 65 
     | 
    
         
            +
                #   else false
         
     | 
| 
       57 
66 
     | 
    
         
             
                def newer_gem_available?(version = SSHScan::VERSION)
         
     | 
| 
       58 
67 
     | 
    
         
             
                  if gem_exists?(next_patch_version(version))
         
     | 
| 
       59 
68 
     | 
    
         
             
                    return true
         
     | 
    
        data/lib/ssh_scan/version.rb
    CHANGED
    
    
    
        data/ssh_scan.gemspec
    CHANGED
    
    | 
         @@ -28,6 +28,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       28 
28 
     | 
    
         
             
              s.summary = 'Ruby-based SSH Scanner'
         
     | 
| 
       29 
29 
     | 
    
         
             
              s.description = 'A Ruby-based SSH scanner for configuration and policy scanning'
         
     | 
| 
       30 
30 
     | 
    
         
             
              s.homepage = 'http://rubygems.org/gems/ssh_scan'
         
     | 
| 
      
 31 
     | 
    
         
            +
              s.metadata["yard.run"] = "yri" # use "yard" to build full HTML docs
         
     | 
| 
       31 
32 
     | 
    
         | 
| 
       32 
33 
     | 
    
         
             
              s.add_dependency('bindata', '~> 2.0')
         
     | 
| 
       33 
34 
     | 
    
         
             
              s.add_dependency('netaddr')
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       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.21
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Jonathan Claudius
         
     | 
| 
         @@ -12,7 +12,7 @@ authors: 
     | 
|
| 
       12 
12 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       13 
13 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       14 
14 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       15 
     | 
    
         
            -
            date: 2017-05- 
     | 
| 
      
 15 
     | 
    
         
            +
            date: 2017-05-25 00:00:00.000000000 Z
         
     | 
| 
       16 
16 
     | 
    
         
             
            dependencies:
         
     | 
| 
       17 
17 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       18 
18 
     | 
    
         
             
              name: bindata
         
     | 
| 
         @@ -391,7 +391,8 @@ files: 
     | 
|
| 
       391 
391 
     | 
    
         
             
            homepage: http://rubygems.org/gems/ssh_scan
         
     | 
| 
       392 
392 
     | 
    
         
             
            licenses:
         
     | 
| 
       393 
393 
     | 
    
         
             
            - ruby
         
     | 
| 
       394 
     | 
    
         
            -
            metadata: 
     | 
| 
      
 394 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 395 
     | 
    
         
            +
              yard.run: yri
         
     | 
| 
       395 
396 
     | 
    
         
             
            post_install_message: 
         
     | 
| 
       396 
397 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       397 
398 
     | 
    
         
             
            require_paths:
         
     |