Class: Rex::SSLScan::Result

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/sslscan/result.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeResult

Returns a new instance of Result.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/rex/sslscan/result.rb', line 15

def initialize()
  @cert = nil
  @ciphers = Set.new
  @supported_versions = [:SSLv2, :SSLv3, :TLSv1, :TLSv1_1, :TLSv1_2]
  @deprecated_weak_ciphers = [
    'ECDHE-RSA-DES-CBC3-SHA',
    'ECDHE-ECDSA-DES-CBC3-SHA',
    'SRP-DSS-3DES-EDE-CBC-SHA',
    'SRP-RSA-3DES-EDE-CBC-SHA',
    'SRP-3DES-EDE-CBC-SHA',
    'EDH-RSA-DES-CBC3-SHA',
    'EDH-DSS-DES-CBC3-SHA',
    'ECDH-RSA-DES-CBC3-SHA',
    'ECDH-ECDSA-DES-CBC3-SHA',
    'DES-CBC3-SHA',
    'PSK-3DES-EDE-CBC-SHA',
    'EXP-EDH-RSA-DES-CBC-SHA',
    'EXP-EDH-DSS-DES-CBC-SHA',
    'EXP-DES-CBC-SHA',
    'EXP-RC2-CBC-MD5',
    'EXP-RC4-MD5',
    'EXP-RC4-MD5',
    'DES-CBC-SHA'
  ]
end

Instance Attribute Details

#ciphersObject (readonly)

Returns the value of attribute ciphers.



12
13
14
# File 'lib/rex/sslscan/result.rb', line 12

def ciphers
  @ciphers
end

#openssl_sslv2Object

Returns the value of attribute openssl_sslv2.



10
11
12
# File 'lib/rex/sslscan/result.rb', line 10

def openssl_sslv2
  @openssl_sslv2
end

#supported_versionsObject (readonly)

Returns the value of attribute supported_versions.



13
14
15
# File 'lib/rex/sslscan/result.rb', line 13

def supported_versions
  @supported_versions
end

Instance Method Details

#accepted(version = :all) ⇒ Array

Returns all accepted ciphers matching the supplied version

Parameters:

  • version (Symbol, Array) (defaults to: :all)

    The SSL Version to filter on

Returns:

  • (Array)

    An array of accepted cipher details matching the supplied versions

Raises:

  • (ArgumentError)

    if the version supplied is invalid



76
77
78
# File 'lib/rex/sslscan/result.rb', line 76

def accepted(version = :all)
  enum_ciphers(:accepted, version)
end

#add_cipher(version, cipher, key_length, status) ⇒ Object

Adds the details of a cipher test to the Result object.

Parameters:

  • version (Symbol)

    the SSL Version

  • cipher (String)

    the SSL cipher

  • key_length (Integer)

    the length of encryption key

  • status (Symbol)

    :accepted or :rejected



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/rex/sslscan/result.rb', line 143

def add_cipher(version, cipher, key_length, status)
  unless @supported_versions.include? version
    raise ArgumentError, "Must be a supported SSL Version"
  end
  unless OpenSSL::SSL::SSLContext.new(version).ciphers.flatten.include?(cipher) || @deprecated_weak_ciphers.include?(cipher)
    raise ArgumentError, "Must be a valid SSL Cipher for #{version}!"
  end
  unless key_length.kind_of? Integer
    raise ArgumentError, "Must supply a valid key length"
  end
  unless [:accepted, :rejected].include? status
    raise ArgumentError, "Status must be either :accepted or :rejected"
  end

  strong_cipher_ctx = OpenSSL::SSL::SSLContext.new(version)
  # OpenSSL Directive For Strong Ciphers
  # See: http://www.rapid7.com/vulndb/lookup/ssl-weak-ciphers
  strong_cipher_ctx.ciphers = "ALL:!aNULL:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM"

  if strong_cipher_ctx.ciphers.flatten.include? cipher
    weak = false
  else
    weak = true
  end

  cipher_details = {:version => version, :cipher => cipher, :key_length => key_length, :weak => weak, :status => status}
  @ciphers << cipher_details
end

#certObject



41
42
43
# File 'lib/rex/sslscan/result.rb', line 41

def cert
  @cert
end

#cert=(input) ⇒ Object



45
46
47
48
49
50
# File 'lib/rex/sslscan/result.rb', line 45

def cert=(input)
  unless input.kind_of? OpenSSL::X509::Certificate or input.nil?
    raise ArgumentError, "Must be an X509 Cert!"
  end
  @cert = input
end

#each_accepted(version = :all) ⇒ Object



88
89
90
91
92
# File 'lib/rex/sslscan/result.rb', line 88

def each_accepted(version = :all)
  accepted(version).each do |cipher_result|
    yield cipher_result
  end
end

#each_rejected(version = :all) ⇒ Object



94
95
96
97
98
# File 'lib/rex/sslscan/result.rb', line 94

def each_rejected(version = :all)
  rejected(version).each do |cipher_result|
    yield cipher_result
  end
end

#rejected(version = :all) ⇒ Array

Returns all rejected ciphers matching the supplied version

Parameters:

  • version (Symbol, Array) (defaults to: :all)

    The SSL Version to filter on

Returns:

  • (Array)

    An array of rejected cipher details matching the supplied versions

Raises:

  • (ArgumentError)

    if the version supplied is invalid



84
85
86
# File 'lib/rex/sslscan/result.rb', line 84

def rejected(version = :all)
  enum_ciphers(:rejected, version)
end

#sslv2Object



52
53
54
# File 'lib/rex/sslscan/result.rb', line 52

def sslv2
  @ciphers.reject{|cipher| cipher[:version] != :SSLv2 }
end

#sslv3Object



56
57
58
# File 'lib/rex/sslscan/result.rb', line 56

def sslv3
  @ciphers.reject{|cipher| cipher[:version] != :SSLv3 }
end

#standards_compliant?Boolean

Returns:

  • (Boolean)


128
129
130
131
132
133
134
135
136
# File 'lib/rex/sslscan/result.rb', line 128

def standards_compliant?
  if supports_ssl?
    return false if supports_sslv2?
    return false if supports_sslv3?
    return false if supports_weak_ciphers?
    return false if supports_tlsv1?
  end
  true
end

#strong_ciphersObject



68
69
70
# File 'lib/rex/sslscan/result.rb', line 68

def strong_ciphers
  accepted.reject{|cipher| cipher[:weak] }
end

#supports_ssl?Boolean

Returns:

  • (Boolean)


120
121
122
# File 'lib/rex/sslscan/result.rb', line 120

def supports_ssl?
  supports_sslv2? or supports_sslv3? or supports_tlsv1? or supports_tlsv1_1? or supports_tlsv1_2?
end

#supports_sslv2?Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/rex/sslscan/result.rb', line 100

def supports_sslv2?
  !(accepted(:SSLv2).empty?)
end

#supports_sslv3?Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/rex/sslscan/result.rb', line 104

def supports_sslv3?
  !(accepted(:SSLv3).empty?)
end

#supports_tlsv1?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'lib/rex/sslscan/result.rb', line 108

def supports_tlsv1?
  !(accepted(:TLSv1).empty?)
end

#supports_tlsv1_1?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'lib/rex/sslscan/result.rb', line 112

def supports_tlsv1_1?
  !(accepted(:TLSv1_1).empty?)
end

#supports_tlsv1_2?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/rex/sslscan/result.rb', line 116

def supports_tlsv1_2?
  !(accepted(:TLSv1_2).empty?)
end

#supports_weak_ciphers?Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/rex/sslscan/result.rb', line 124

def supports_weak_ciphers?
  !(weak_ciphers.empty?)
end

#tlsv1Object



60
61
62
# File 'lib/rex/sslscan/result.rb', line 60

def tlsv1
  @ciphers.reject{|cipher| cipher[:version] != :TLSv1 }
end

#to_sObject



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/rex/sslscan/result.rb', line 172

def to_s
  unless supports_ssl?
    return "Server does not appear to support SSL on this port!"
  end
  table = Rex::Text::Table.new(
    'Header'      => 'SSL Ciphers',
    'Indent'       => 1,
    'Columns'   => ['Status', 'Weak', 'SSL Version', 'Key Length', 'Cipher'],
    'SortIndex'  => -1
  )
  ciphers.each do |cipher|
    if cipher[:weak]
      weak = '*'
    else
      weak = ' '
    end
    table << [cipher[:status].to_s.capitalize, weak , cipher[:version], cipher[:key_length], cipher[:cipher]]
  end

  # Sort by SSL Version, then Key Length, and then Status
  table.rows.sort_by!{|row| [row[0],row[2],row[3]]}
  text = "#{table.to_s}"
  if @cert
    text << " \n\n #{@cert.to_text}"
  end
  if openssl_sslv2 == false
    text << "\n\n *** WARNING: Your OS hates freedom! Your OpenSSL libs are compiled without SSLv2 support!"
  end
  text
end

#weak_ciphersObject



64
65
66
# File 'lib/rex/sslscan/result.rb', line 64

def weak_ciphers
  accepted.reject{|cipher| cipher[:weak] == false }
end