Don’t use net-ssh to (not) ensure server compatibility

v1
Aeris 8 years ago
parent cf9a606a72
commit 2b19052c0c
  1. 1
      cryptcheck.gemspec
  2. 6
      lib/cryptcheck.rb
  3. 12
      lib/cryptcheck/ssh/grade.rb
  4. 45
      lib/cryptcheck/ssh/packet.rb
  5. 129
      lib/cryptcheck/ssh/server.rb

@ -35,5 +35,4 @@ Gem::Specification.new do |spec|
spec.add_dependency 'parallel', '~> 1.3', '>= 1.3.4'
spec.add_dependency 'ruby-progressbar', '~> 1.7', '>= 1.7.1'
spec.add_dependency 'colorize', '~> 0.7', '>= 0.7.7'
spec.add_dependency 'net-ssh', '~> 2.9', '>= 2.9.2'
end

@ -31,4 +31,10 @@ module CryptCheck
autoload :Grade, 'cryptcheck/tls/smtp/grade'
end
end
module Ssh
autoload :Packet, 'cryptcheck/ssh/packet'
autoload :Server, 'cryptcheck/ssh/server'
autoload :SshNotSupportedServer, 'cryptcheck/ssh/server'
end
end

@ -1,6 +1,6 @@
module CryptCheck
module Tls
class TlsNotSupportedGrade
module Ssh
class SshNotSupportedGrade
attr_reader :server, :score, :grade
def initialize(server)
@ -13,14 +13,6 @@ module CryptCheck
def initialize(server)
@server = server
calculate_protocol_score
calculate_key_exchange_score
calculate_cipher_strengths_score
@score = @protocol_score*0.3 + @key_exchange_score*0.3 + @cipher_strengths_score*0.4
calculate_error
calculate_warning
calculate_success
calculate_grade
end
def display

@ -0,0 +1,45 @@
module CryptCheck
module Ssh
class Packet
SSH_MSG_KEXINIT = 20
def self.uint32(raw)
raw.gets(4).unpack('N').first
end
def self.string(raw)
length = self.uint32 raw
raw.gets length
end
def self.strings(raw)
self.string(raw).split ','
end
def self.read(socket)
packet_length = socket.recv(4).unpack('N').first
padding_length = socket.recv(1).unpack('C').first
payload = socket.recv packet_length - padding_length - 1
socket.recv padding_length
StringIO.new payload
end
def self.read_kex_init(socket)
payload = self.read socket
msg_id = payload.gets(1).unpack('C').first
raise "Not expected message id #{msg_id}" unless msg_id == SSH_MSG_KEXINIT
payload.gets 16 # cookie
key_algorithms = self.strings payload
host_key_algorithms = self.strings payload
encryption_algorithms = (self.strings(payload) + self.strings(payload)).uniq
mac_algorithms = (self.strings(payload) + self.strings(payload)).uniq
compression_algorithms = (self.strings(payload) + self.strings(payload)).uniq
{ kex: key_algorithms, host_key: host_key_algorithms, encryption: encryption_algorithms,
mac: mac_algorithms, compression: compression_algorithms }
end
end
end
end

@ -1,4 +1,4 @@
require 'net/ssh'
require 'socket'
module CryptCheck
module Ssh
@ -11,91 +11,95 @@ module CryptCheck
end
class Server
TCP_TIMEOUT = 10
TCP_TIMEOUT = 10
class SshNotAvailableException < Exception
end
attr_reader :hostname, :port, :kex, :encryption, :hmac, :compression, :key
KEX = {
'curve25519-sha256@libssh.org' => :green,
'diffie-hellman-group1-sha1' => :yellow,
'diffie-hellman-group14-sha1' => :yellow,
'diffie-hellman-group-exchange-sha1' => :yellow,
'diffie-hellman-group-exchange-sha256' => :green,
'ecdh-sha2-nistp256' => :yellow,
'ecdh-sha2-nistp384' => :yellow,
'ecdh-sha2-nistp521' => :yellow
'curve25519-sha256@libssh.org' => :green,
'diffie-hellman-group1-sha1' => :yellow,
'diffie-hellman-group14-sha1' => :yellow,
'diffie-hellman-group-exchange-sha1' => :yellow,
'diffie-hellman-group-exchange-sha256' => :green,
'ecdh-sha2-nistp256' => :yellow,
'ecdh-sha2-nistp384' => :yellow,
'ecdh-sha2-nistp521' => :yellow
}
ENCRYPTION = {
'3des-cbc' => :red,
'aes128-cbc' => :yellow,
'aes192-cbc' => :yellow,
'aes256-cbc' => :yellow,
'aes128-ctr' => :yellow,
'aes192-ctr' => :yellow,
'aes256-ctr' => :yellow,
'aes128-gcm@openssh.com' => :green,
'aes256-gcm@openssh.com' => :green,
'arcfour' => :red,
'arcfour128' => :red,
'arcfour256' => :red,
'blowfish-cbc' => :yellow,
'cast128-cbc' => nil,
'chacha20-poly1305@openssh.com' => :green
'3des-cbc' => :red,
'aes128-cbc' => :yellow,
'aes192-cbc' => :yellow,
'aes256-cbc' => :yellow,
'aes128-ctr' => :yellow,
'aes192-ctr' => :yellow,
'aes256-ctr' => :yellow,
'aes128-gcm@openssh.com' => :green,
'aes256-gcm@openssh.com' => :green,
'arcfour' => :red,
'arcfour128' => :red,
'arcfour256' => :red,
'blowfish-cbc' => :yellow,
'cast128-cbc' => nil,
'chacha20-poly1305@openssh.com' => :green
}
HMAC = {
'hmac-md5' => :red,
'hmac-md5-96' => :red,
'hmac-ripemd160' => :green,
'hmac-sha1' => :yellow,
'hmac-sha1-96' => :red,
'hmac-sha2-256' => :green,
'hmac-sha2-512' => :green,
'umac-64@openssh.com' => :red,
'umac-128@openssh.com' => nil,
'hmac-md5-etm@openssh.com' => :red,
'hmac-md5-96-etm@openssh.com' => :red,
'hmac-ripemd160-etm@openssh.com' => :green,
'hmac-sha1-etm@openssh.com' => :yellow,
'hmac-sha1-96-etm@openssh.com' => :red,
'hmac-sha2-256-etm@openssh.com' => :green,
'hmac-sha2-512-etm@openssh.com' => :green,
'umac-64-etm@openssh.com' => :red,
'umac-128-etm@openssh.com' => nil
'hmac-md5' => :red,
'hmac-md5-96' => :red,
'hmac-ripemd160' => :green,
'hmac-sha1' => :yellow,
'hmac-sha1-96' => :red,
'hmac-sha2-256' => :green,
'hmac-sha2-512' => :green,
'umac-64@openssh.com' => :red,
'umac-128@openssh.com' => nil,
'hmac-md5-etm@openssh.com' => :red,
'hmac-md5-96-etm@openssh.com' => :red,
'hmac-ripemd160-etm@openssh.com' => :green,
'hmac-sha1-etm@openssh.com' => :yellow,
'hmac-sha1-96-etm@openssh.com' => :red,
'hmac-sha2-256-etm@openssh.com' => :green,
'hmac-sha2-512-etm@openssh.com' => :green,
'umac-64-etm@openssh.com' => :red,
'umac-128-etm@openssh.com' => nil
}
COMPRESSION = {
'none' => nil,
'zlib@openssh.com' => nil
'none' => nil,
'zlib@openssh.com' => nil
}
KEY = {
'ecdsa-sha2-nistp256-cert-v01@openssh.com' => :yellow,
'ecdsa-sha2-nistp384-cert-v01@openssh.com' => :yellow,
'ecdsa-sha2-nistp521-cert-v01@openssh.com' => :yellow,
'ssh-ed25519-cert-v01@openssh.com' => :green,
'ssh-rsa-cert-v01@openssh.com' => :yellow,
'ssh-dss-cert-v01@openssh.com' => :red,
'ssh-rsa-cert-v00@openssh.com' => :yellow,
'ssh-dss-cert-v00@openssh.com' => :red,
'ecdsa-sha2-nistp256' => :yellow,
'ecdsa-sha2-nistp384' => :yellow,
'ecdsa-sha2-nistp521' => :yellow,
'ssh-ed25519' => :green,
'ssh-rsa' => :yellow,
'ssh-dss' => :red
'ecdsa-sha2-nistp256-cert-v01@openssh.com' => :yellow,
'ecdsa-sha2-nistp384-cert-v01@openssh.com' => :yellow,
'ecdsa-sha2-nistp521-cert-v01@openssh.com' => :yellow,
'ssh-ed25519-cert-v01@openssh.com' => :green,
'ssh-rsa-cert-v01@openssh.com' => :yellow,
'ssh-dss-cert-v01@openssh.com' => :red,
'ssh-rsa-cert-v00@openssh.com' => :yellow,
'ssh-dss-cert-v00@openssh.com' => :red,
'ecdsa-sha2-nistp256' => :yellow,
'ecdsa-sha2-nistp384' => :yellow,
'ecdsa-sha2-nistp521' => :yellow,
'ssh-ed25519' => :green,
'ssh-rsa' => :yellow,
'ssh-dss' => :red
}
def initialize(hostname, port)
@hostname, @port = hostname, port
Logger.info { "#{hostname}:#{port}".colorize :blue }
session = ::Net::SSH::Transport::Session.new @hostname, port: @port, timeout: TCP_TIMEOUT
data = session.algorithms.instance_variable_get :@server_data
@kex, @encryption, @hmac, @compression, @key = data[:kex], data[:encryption_server], data[:hmac_server], data[:compression_server], data[:host_key]
kex = ::Socket.tcp hostname, port, connect_timeout: TCP_TIMEOUT do |socket|
socket.readline
socket.write "SSH-2.0-CryptCheck\r\n"
Packet.read_kex_init socket
end
@kex, @encryption, @hmac, @compression, @key = kex[:kex], kex[:encryption], kex[:mac], kex[:compression], kex[:host_key]
Logger.info { '' }
@kex.each { |k| Logger.info { "Key exchange : #{k.colorize KEX[k]}" } }
@ -107,7 +111,6 @@ module CryptCheck
@compression.each { |c| Logger.info { "Compression : #{c}" } }
Logger.info { '' }
@key.each { |k| Logger.info { "Key type : #{k.colorize KEY[k]}" } }
session.close
rescue => e
Logger.debug { "SSH not supported : #{e}" }
raise SshNotAvailableException, e

Loading…
Cancel
Save