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.



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

def initialize()
  @cert = nil
  @ciphers = Set.new
  @supported_versions = [:SSLv2, :SSLv3, :TLSv1]
  @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'
  ]
end

Instance Attribute Details

#ciphersObject (readonly)

Returns the value of attribute ciphers.



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

def ciphers
  @ciphers
end

#openssl_sslv2Object

Returns the value of attribute openssl_sslv2.



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

def openssl_sslv2
  @openssl_sslv2
end

#supported_versionsObject (readonly)

Returns the value of attribute supported_versions.



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

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:



73
74
75
# File 'lib/rex/sslscan/result.rb', line 73

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 (Fixnum)

    the length of encryption key

  • status (Symbol)

    :accepted or :rejected



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rex/sslscan/result.rb', line 130

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? Fixnum
    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



38
39
40
# File 'lib/rex/sslscan/result.rb', line 38

def cert
  @cert
end

#cert=(input) ⇒ Object



42
43
44
45
46
47
# File 'lib/rex/sslscan/result.rb', line 42

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



85
86
87
88
89
# File 'lib/rex/sslscan/result.rb', line 85

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

#each_rejected(version = :all) ⇒ Object



91
92
93
94
95
# File 'lib/rex/sslscan/result.rb', line 91

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:



81
82
83
# File 'lib/rex/sslscan/result.rb', line 81

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

#sslv2Object



49
50
51
# File 'lib/rex/sslscan/result.rb', line 49

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

#sslv3Object



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

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

#standards_compliant?Boolean

Returns:

  • (Boolean)


117
118
119
120
121
122
123
# File 'lib/rex/sslscan/result.rb', line 117

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

#strong_ciphersObject



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

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

#supports_ssl?Boolean

Returns:

  • (Boolean)


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

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

#supports_sslv2?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/rex/sslscan/result.rb', line 97

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

#supports_sslv3?Boolean

Returns:

  • (Boolean)


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

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

#supports_tlsv1?Boolean

Returns:

  • (Boolean)


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

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

#supports_weak_ciphers?Boolean

Returns:

  • (Boolean)


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

def supports_weak_ciphers?
  !(weak_ciphers.empty?)
end

#tlsv1Object



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

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

#to_sObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/rex/sslscan/result.rb', line 160

def to_s
  unless supports_ssl?
    return "Server does not appear to support SSL on this port!"
  end
  table = Rex::Ui::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



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

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