fix stupid datat structure
also supports a boolean value for whether the cipher is weak or notbug/bundler_fix
parent
5c9f946927
commit
dfc7ce9381
|
@ -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?
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue