fix stupid datat structure

also supports a boolean value for whether the cipher is weak or not
bug/bundler_fix
David Maloney 2013-02-08 11:33:36 -06:00
parent 5c9f946927
commit dfc7ce9381
2 changed files with 137 additions and 91 deletions

View File

@ -4,16 +4,12 @@ require 'rex/socket'
module Rex::SSLScan module Rex::SSLScan
class Result class Result
attr_reader :sslv2 attr_reader :ciphers
attr_reader :sslv3
attr_reader :tlsv1
attr_reader :supported_versions attr_reader :supported_versions
def initialize() def initialize()
@cert = nil @cert = nil
@sslv2 = {:accepted => [], :rejected => []} @ciphers = []
@sslv3 = {:accepted => [], :rejected => []}
@tlsv1 = {:accepted => [], :rejected => []}
@supported_versions = [:SSLv2, :SSLv3, :TLSv1] @supported_versions = [:SSLv2, :SSLv3, :TLSv1]
end end
@ -28,6 +24,10 @@ class Result
@cert = input @cert = input
end end
def sslv2
@ciphers.reject{|cipher| cipher[:version] != :SSLv2 }
end
def add_cipher(version, cipher, key_length, status) def add_cipher(version, cipher, key_length, status)
unless @supported_versions.include? version unless @supported_versions.include? version
raise ArgumentError, "Must be a supported SSL Version" raise ArgumentError, "Must be a supported SSL Version"
@ -42,74 +42,86 @@ class Result
raise ArgumentError, "status Must be either :accepted or :rejected" raise ArgumentError, "status Must be either :accepted or :rejected"
end end
cipher_details = {:cipher => cipher, :key_length => key_length} strong_cipher_ctx = OpenSSL::SSL::SSLContext.new(version)
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
@ciphers.uniq!
end
def accepted(version = :all)
if version.kind_of? Symbol
case version case version
when :SSLv2 when :all
@sslv2[status] << cipher_details return @ciphers.reject{|cipher| cipher[:status] == :rejected}
@sslv2[status].uniq! when :SSLv2, :SSLv3, :TLSv1
when :SSLv3 return @ciphers.reject{|cipher| cipher[:status] == :rejected or cipher[:version] != version}
@sslv3[status] << cipher_details else
@sslv3[status].uniq! raise ArgumentError, "Invalid SSL Version Supplied: #{version}"
when :TLSv1 end
@tlsv1[status] << cipher_details elsif version.kind_of? Array
@tlsv1[status].uniq! version.reject!{|version| @supported_versions.include? version}
if version.empty?
return @ciphers.reject{|cipher| cipher[:status] == :rejected}
else
return @ciphers.reject{|cipher| cipher[:status] == :rejected or !(version.include? cipher[:version])}
end
else
raise ArgumentError, "Was expecting Symbol or Array and got #{version.class}"
end end
end end
def accepted def rejected(version = :all)
{ if version.kind_of? Symbol
:SSLv2 => @sslv2[:accepted], case version
:SSLv3 => @sslv3[:accepted], when :all
:TLSv1 => @tlsv1[:accepted] return @ciphers.reject{|cipher| cipher[:status] == :accepted}
} when :SSLv2, :SSLv3, :TLSv1
return @ciphers.reject{|cipher| cipher[:status] == :accepted or cipher[:version] != version}
else
raise ArgumentError, "Invalid SSL Version Supplied: #{version}"
end
elsif version.kind_of? Array
version.reject!{|version| @supported_versions.include? version}
if version.empty?
return @ciphers.reject{|cipher| cipher[:status] == :accepted}
else
return @ciphers.reject{|cipher| cipher[:status] == :accepted or !(version.include? cipher[:version])}
end
else
raise ArgumentError, "Was expecting Symbol or Array and got #{version.class}"
end
end end
def rejected def each_accepted(version = :all)
{ accepted(version).each do |cipher_result|
:SSLv2 => @sslv2[:rejected],
:SSLv3 => @sslv3[:rejected],
:TLSv1 => @tlsv1[:rejected]
}
end
def each_accepted
all_accepted = []
accepted.each_pair do |version, cipher_list|
cipher_list.each do |cipher_details|
cipher_details[:version] = version
all_accepted << cipher_details
end
end
all_accepted.each do |cipher_result|
yield cipher_result yield cipher_result
end end
end end
def each_rejected def each_rejected(version = :all)
all_rejected = [] rejected(version).each do |cipher_result|
rejected.each_pair do |version, cipher_list|
cipher_list.each do |cipher_details|
cipher_details[:version] = version
all_rejected << cipher_details
end
end
all_rejected.each do |cipher_result|
yield cipher_result yield cipher_result
end end
end end
def supports_sslv2? def supports_sslv2?
!(accepted[:SSLv2].empty?) !(accepted(:SSLv2).empty?)
end end
def supports_sslv3? def supports_sslv3?
!(accepted[:SSLv3].empty?) !(accepted(:SSLv3).empty?)
end end
def supports_tlsv1? def supports_tlsv1?
!(accepted[:TLSv1].empty?) !(accepted(:TLSv1).empty?)
end end
def supports_ssl? def supports_ssl?

View File

@ -5,33 +5,23 @@ describe Rex::SSLScan::Result do
subject{Rex::SSLScan::Result.new} subject{Rex::SSLScan::Result.new}
it { should respond_to :cert } it { should respond_to :cert }
it { should respond_to :sslv2 } it { should respond_to :ciphers }
it { should respond_to :sslv3 }
it { should respond_to :tlsv1 }
context "with no values set" do context "with no values set" do
it "should return nil for the cert" do it "should return nil for the cert" do
subject.cert.should == nil subject.cert.should == nil
end end
it "should return an empty structure for sslv2" do it "should return an empty array for ciphers" do
subject.sslv2.should == {:accepted => [], :rejected => []} subject.ciphers.should == []
end end
it "should return an empty structure for sslv3" do it "should return an empty array for accepted" do
subject.sslv3.should == {:accepted => [], :rejected => []} subject.accepted.should == []
end end
it "should return an empty structure for tlsv1" do it "should return an empty array for rejected" do
subject.tlsv1.should == {:accepted => [], :rejected => []} subject.rejected.should == []
end
it "should return an empty structure for #accepted" do
subject.accepted.should == {:SSLv2=>[], :SSLv3=>[], :TLSv1=>[]}
end
it "should return an emtpy structure for #rejected" do
subject.rejected.should == {:SSLv2=>[], :SSLv3=>[], :TLSv1=>[]}
end end
end end
@ -89,65 +79,109 @@ describe Rex::SSLScan::Result do
context "that was accepted" do context "that was accepted" do
it "should add an SSLv2 cipher result to the SSLv2 Accepted array" do it "should add an SSLv2 cipher result to the SSLv2 Accepted array" do
subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :accepted) subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :accepted)
subject.sslv2[:accepted].should include({:cipher=>"DES-CBC3-MD5", :key_length=>168}) subject.accepted(:SSLv2).should include({
subject.accepted[:SSLv2].should include({:cipher=>"DES-CBC3-MD5", :key_length=>168}) :version => :SSLv2,
:cipher=>"DES-CBC3-MD5",
:key_length=>168,
:weak=> false,
:status => :accepted})
end end
it "should add an SSLv3 cipher result to the SSLv3 Accepted array" do it "should add an SSLv3 cipher result to the SSLv3 Accepted array" do
subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted)
subject.sslv3[:accepted].should include({:cipher=>"AES256-SHA", :key_length=>256}) subject.accepted(:SSLv3).should include({
subject.accepted[:SSLv3].should include({:cipher=>"AES256-SHA", :key_length=>256}) :version => :SSLv3,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :accepted})
end end
it "should add an TLSv1 cipher result to the TLSv1 Accepted array" do it "should add an TLSv1 cipher result to the TLSv1 Accepted array" do
subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted) subject.add_cipher(:TLSv1, "AES256-SHA", 256, :accepted)
subject.tlsv1[:accepted].should include({:cipher=>"AES256-SHA", :key_length=>256}) subject.accepted(:TLSv1).should include({
subject.accepted[:TLSv1].should include({:cipher=>"AES256-SHA", :key_length=>256}) :version => :TLSv1,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :accepted})
end end
it "should successfully add multiple entries in a row" do it "should successfully add multiple entries in a row" do
subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted)
subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted) subject.add_cipher(:SSLv3, "AES256-SHA", 256, :accepted)
subject.sslv3[:accepted].should include({:cipher=>"AES256-SHA", :key_length=>256}) subject.accepted(:SSLv3).should include({
subject.sslv3[:accepted].should include({:cipher=>"AES128-SHA", :key_length=>128}) :version => :SSLv3,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :accepted})
subject.accepted(:SSLv3).should include({
:version => :SSLv3,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :accepted})
end end
it "should not add duplicate entries" do it "should not add duplicate entries" do
subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted)
subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted) subject.add_cipher(:SSLv3, "AES128-SHA", 128, :accepted)
subject.sslv3[:accepted].count.should == 1 subject.accepted(:SSLv3).count.should == 1
end end
end end
context "that was rejected" do context "that was rejected" do
it "should add an SSLv2 cipher result to the SSLv2 Rejected array" do it "should add an SSLv2 cipher result to the SSLv2 Rejected array" do
subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :rejected) subject.add_cipher(:SSLv2, "DES-CBC3-MD5", 168, :rejected)
subject.sslv2[:rejected].should include({:cipher=>"DES-CBC3-MD5", :key_length=>168}) subject.rejected(:SSLv2).should include({
subject.rejected[:SSLv2].should include({:cipher=>"DES-CBC3-MD5", :key_length=>168}) :version => :SSLv2,
:cipher=>"DES-CBC3-MD5",
:key_length=>168,
:weak=> false,
:status => :rejected})
end end
it "should add an SSLv3 cipher result to the SSLv3 Rejected array" do it "should add an SSLv3 cipher result to the SSLv3 Rejected array" do
subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected) subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected)
subject.sslv3[:rejected].should include({:cipher=>"AES256-SHA", :key_length=>256}) subject.rejected(:SSLv3).should include({
subject.rejected[:SSLv3].should include({:cipher=>"AES256-SHA", :key_length=>256}) :version => :SSLv3,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :rejected})
end end
it "should add an TLSv1 cipher result to the TLSv1 Rejected array" do it "should add an TLSv1 cipher result to the TLSv1 Rejected array" do
subject.add_cipher(:TLSv1, "AES256-SHA", 256, :rejected) subject.add_cipher(:TLSv1, "AES256-SHA", 256, :rejected)
subject.tlsv1[:rejected].should include({:cipher=>"AES256-SHA", :key_length=>256}) subject.rejected(:TLSv1).should include({
subject.rejected[:TLSv1].should include({:cipher=>"AES256-SHA", :key_length=>256}) :version => :TLSv1,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :rejected})
end end
it "should successfully add multiple entries in a row" do it "should successfully add multiple entries in a row" do
subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected)
subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected) subject.add_cipher(:SSLv3, "AES256-SHA", 256, :rejected)
subject.sslv3[:rejected].should include({:cipher=>"AES256-SHA", :key_length=>256}) subject.rejected(:SSLv3).should include({
subject.sslv3[:rejected].should include({:cipher=>"AES128-SHA", :key_length=>128}) :version => :SSLv3,
:cipher=>"AES256-SHA",
:key_length=>256,
:weak=> false,
:status => :rejected})
subject.rejected(:SSLv3).should include({
:version => :SSLv3,
:cipher=>"AES128-SHA",
:key_length=>128,
:weak=> false,
:status => :rejected})
end end
it "should not add duplicate entries" do it "should not add duplicate entries" do
subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected)
subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected) subject.add_cipher(:SSLv3, "AES128-SHA", 128, :rejected)
subject.sslv3[:rejected].count.should == 1 subject.rejected(:SSLv3).count.should == 1
end end
end end
end end
@ -162,7 +196,7 @@ describe Rex::SSLScan::Result do
it "should return an array of cipher detail hashes" do it "should return an array of cipher detail hashes" do
subject.each_accepted do |cipher_details| subject.each_accepted do |cipher_details|
cipher_details.should include(:version, :cipher, :key_length) cipher_details.should include(:version, :cipher, :key_length, :status, :weak)
end end
end end
@ -185,7 +219,7 @@ describe Rex::SSLScan::Result do
it "should return an array of cipher detail hashes" do it "should return an array of cipher detail hashes" do
subject.each_rejected do |cipher_details| subject.each_rejected do |cipher_details|
cipher_details.should include(:version, :cipher, :key_length) cipher_details.should include(:version, :cipher, :key_length, :status, :weak)
end end
end end