improvements to tests and api

This commit is contained in:
A Galway 2021-04-19 15:13:42 +01:00
parent 88f17c5128
commit 5df0f0b164
No known key found for this signature in database
GPG Key ID: 5A35289C228D5BC0
5 changed files with 114 additions and 297 deletions

View File

@ -97,26 +97,6 @@ module Msf
@cookie.httponly = !!httponly
end
# def for_domain
# @cookie.for_domain
# end
#
# def for_domain= for_domain
# @cookie.for_domain= !!for_domain
# end
# def origin
# @cookie.origin
# end
#
# def origin= origin
# if origin.kind_of?(URI)
# @cookie.origin= origin
# else
# @cookie.origin= origin.to_s
# end
# end
def domain
@cookie.domain
end
@ -125,7 +105,7 @@ module Msf
if domain.nil? || domain.is_a?(DomainName)
@cookie.domain = domain
else
@cookie.domain = DomainName(domain.to_s)
@cookie.domain = domain.to_s
end
end

View File

@ -16,7 +16,7 @@ module Msf
end
def add(cookie)
raise TypeError, "Passed cookie is of class '#{cookie.class}' and not a subclass of '#{Msf::Exploit::Remote::HTTP::HttpCookie.class}" unless cookie.is_a?(HttpCookie)
raise TypeError, "Passed cookie is of class '#{cookie.class}' and not a subclass of '#{Msf::Exploit::Remote::HTTP::HttpCookie}" unless cookie.is_a?(Msf::Exploit::Remote::HTTP::HttpCookie)
@cookie_jar.add(cookie)
self
@ -24,7 +24,7 @@ module Msf
def delete(cookie)
return if @cookie_jar.cookies.empty?
raise TypeError, "Passed cookie is of class '#{cookie.class}' and not a subclass of '#{Msf::Exploit::Remote::HTTP::HttpCookie.class}" unless cookie.is_a?(HttpCookie)
raise TypeError, "Passed cookie is of class '#{cookie.class}' and not a subclass of '#{Msf::Exploit::Remote::HTTP::HttpCookie}" unless cookie.is_a?(Msf::Exploit::Remote::HTTP::HttpCookie)
@cookie_jar.delete(cookie)
self
@ -46,8 +46,8 @@ module Msf
@cookie_jar.cleanup(expire_all)
end
def empty?(url = nil)
@cookie_jar.empty?(url)
def empty?
@cookie_jar.empty?
end
def parse(set_cookie_header, origin_url, options = nil)

View File

@ -108,7 +108,6 @@ module Exploit::Remote::HttpClient
end
#
# This method is meant to be overriden in the exploit module to specify a set of regexps to
# attempt to match against. A failure to match any of them results in a RuntimeError exception
# being raised.
@ -383,16 +382,16 @@ module Exploit::Remote::HttpClient
# +expire_cookies+ will control if +cleanup+ is called on any passed +Msf::Exploit::Remote::HTTP::HttpCookieJar+ or the client cookiejar
#
# @return (see Rex::Proto::Http::Client#send_recv))
def send_request_cgi(opts = {}, timeout = 20, disconnect = true, expire_cookies = true)
def send_request_cgi(opts = {}, timeout = 20, disconnect = true)
if opts.has_key?('cookie')
if opts['cookie'].is_a?(Msf::Exploit::Remote::HTTP::HttpCookieJar)
cookie_jar.cleanup if expire_cookies
cookie_jar.cleanup unless opts['expire_cookies'] == false
opts.merge({ 'cookie' => opts['cookie'].cookies.join('; ') })
else
opts.merge({ 'cookie' => opts['cookie'].to_s })
end
elsif !cookie_jar.empty?
cookie_jar.cleanup if expire_cookies
cookie_jar.cleanup unless opts['expire_cookies'] == false
opts = opts.merge({ 'cookie' => cookie_jar.cookies.join('; ') })
end

View File

@ -1,6 +1,4 @@
require 'spec_helper'
require 'msf/core/exploit/remote/http/http_cookie_jar'
require 'msf/core/exploit/remote/http/http_cookie'
RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
def random_string(min_len = 1, max_len = 12)
@ -8,22 +6,24 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
str[0, rand(min_len..max_len)]
end
def cookie
def random_cookie
Msf::Exploit::Remote::HTTP::HttpCookie.new(
random_string,
random_string,
max_age: rand(1..100),
max_age: Faker::Number.within(range: 1..100),
path: '/' + random_string,
secure: rand(0..1) == 1,
httponly: rand(0..1) == 1,
secure: Faker::Boolean.boolean,
httponly: Faker::Boolean.boolean,
domain: random_string
)
end
let(:cookie_jar) { described_class.new }
NOW = Time.local(2008, 9, 5, 10, 5, 30)
before(:each) do
Timecop.freeze(Time.local(2008, 9, 5, 10, 5, 30))
Timecop.freeze(NOW)
end
after(:each) do
@ -40,7 +40,7 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'will return false when a cookie has been added to a cookie_jar' do
c = cookie
c = random_cookie
cookie_jar.add(c)
e = cookie_jar.empty?
@ -58,8 +58,8 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
expect(cookie_jar.empty?).to eq(true)
end
it 'will return false when a cookie has been added to a cookie_jar' do
c = cookie
it 'will return true when populated cookie_jar has been cleared' do
c = random_cookie
cookie_jar.add(c)
cookie_jar.clear
@ -80,8 +80,8 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
it 'will return an array of all cookies added to the cookie_jar when called with no url param' do
c_array = []
rand(1..10).times do
c = cookie
Faker::Number.within(range: 1..10).times do
c = random_cookie
c_array.append(c)
cookie_jar.add(c)
@ -91,30 +91,10 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
expect(c_array.sort).to eq(jar_array.sort)
end
# it 'will return an array of all cookies that have parent paths to the url passed' do
# c_array = [cookie, cookie, cookie, cookie]
# c_array[0].secure = false
# c_array[1].secure = false
# c_array[1].domain = c_array[0].domain
# c_array[1].path = '/'
# c_array.map { |c| cookie_jar.add(c) }
#
# require 'pry'
# binding.pry
#
# filtered_cookies = cookie_jar.cookies("http://#{c_array[0].domain}#{c_array[0].path}")
#
# expect(filtered_cookies.length).to eq(2)
# expect(filtered_cookies.include?(c_array[0])).to eq(true)
# expect(filtered_cookies.include?(c_array[1])).to eq(true)
# expect(filtered_cookies.include?(c_array[2])).to eq(false)
# expect(filtered_cookies.include?(c_array[3])).to eq(false)
# end
end
describe 'add' do
it 'unacceptable cookie missing path throws ArgumentError' do
it 'unacceptable cookie without a domain will throw an ArgumentError' do
c = Msf::Exploit::Remote::HTTP::HttpCookie.new(
random_string,
random_string,
@ -126,7 +106,7 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end.to raise_error(ArgumentError)
end
it 'unacceptable cookie missing domain throws ArgumentError' do
it 'unacceptable cookie without a path will throw an ArgumentError' do
c = Msf::Exploit::Remote::HTTP::HttpCookie.new(
random_string,
random_string,
@ -139,7 +119,7 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'acceptable cookie added to cookie_jar successfully' do
c = cookie
c = random_cookie
cookie_jar.add(c)
@ -147,8 +127,8 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'acceptable cookie added to cookie_jar containing cookie with the same name, domain, and path will result in an overwrite' do
c = cookie
c_dup = cookie
c = random_cookie
c_dup = random_cookie
c_dup.name = c.name
c_dup.domain = c.domain
c_dup.path = c.path
@ -156,12 +136,11 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
cookie_jar.add(c)
cookie_jar.add(c_dup)
expect(cookie_jar.cookies[0]).to eq(c_dup)
expect(cookie_jar.cookies[0]).to_not eq(c)
expect(cookie_jar.cookies).to match_array([c_dup])
end
it 'variable not a subclass of ::HttpCookie will raise TypeError' do
int = rand(1..100)
int = 1
expect do
cookie_jar.add(int)
@ -173,14 +152,14 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
it 'used on an empty jar will return nil' do
# cookie_jar made in before
n = cookie_jar.delete(cookie)
n = cookie_jar.delete(random_cookie)
expect(n).to eq(nil)
end
it 'passed cookie with same name, domain, and path as cookie in jar, will delete cookie in jar' do
c = cookie
c_dup = cookie
c = random_cookie
c_dup = random_cookie
c_dup.name = c.name
c_dup.domain = c.domain
c_dup.path = c.path
@ -192,8 +171,8 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'passed a cookie different name, domain, and path as cookie in jar, will not delete cookie in jar' do
c = cookie
c_dup = cookie
c = random_cookie
c_dup = random_cookie
c_dup.name = c.name + random_string(1, 1)
c_dup.domain = c.domain + random_string(1, 1)
c_dup.path = c.path + random_string(1, 1)
@ -206,7 +185,7 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'variable not a subclass of ::HttpCookie will not raise TypeError when the cookie_jar is empty' do
int = rand(1..100)
int = Faker::Number.within(range: 1..100)
n = cookie_jar.delete(int)
@ -215,8 +194,8 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'variable not a subclass of ::HttpCookie will raise TypeError when the cookie_jar is not empty' do
cookie_jar.add(cookie)
int = rand(1..100)
cookie_jar.add(random_cookie)
int = Faker::Number.within(range: 1..100)
expect do
cookie_jar.delete(int)
@ -234,45 +213,37 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookieJar do
end
it 'will remove expired cookies with max_age value' do
expired_cookies = [cookie, cookie]
expired_cookies = [random_cookie, random_cookie]
expired_cookies[0].max_age = 1
expired_cookies[1].max_age = 1
expired_cookies[0].created_at = Time.local(2008, 9, 5, 10, 5, 1)
expired_cookies[1].created_at = Time.local(2008, 9, 5, 10, 5, 1)
cookies = [cookie, cookie]
cookies = [random_cookie, random_cookie]
cookies[0].max_age = 10000
cookies[1].max_age = 10000
cookies[0].created_at = Time.now
cookies[1].created_at = Time.now
cookies.map { |c| cookie_jar.add(c) }
expired_cookies.map { |c| cookie_jar.add(c) }
cookies.each { |c| cookie_jar.add(c) }
expired_cookies.each { |c| cookie_jar.add(c) }
cookie_jar.cleanup
expect(cookie_jar.cookies.length).to eq(2)
expect(cookie_jar.cookies.include?(expired_cookies[0])).to eq(false)
expect(cookie_jar.cookies.include?(expired_cookies[1])).to eq(false)
expect(cookie_jar.cookies.include?(cookies[0])).to eq(true)
expect(cookie_jar.cookies.include?(cookies[1])).to eq(true)
expect(cookie_jar.cookies).to match_array(cookies)
end
it 'will remove expired cookies with expires value' do
expired_cookies = [cookie, cookie]
expired_cookies = [random_cookie, random_cookie]
expired_cookies[0].expires = Time.local(2008, 9, 3, 10, 5, 0)
expired_cookies[1].expires = Time.local(2008, 9, 4, 10, 5, 0)
cookies = [cookie, cookie]
cookies = [random_cookie, random_cookie]
cookies[0].expires = Time.local(2008, 9, 6, 10, 5, 0)
cookies[1].expires = Time.local(2008, 9, 7, 10, 5, 0)
cookies.map { |c| cookie_jar.add(c) }
expired_cookies.map { |c| cookie_jar.add(c) }
cookies.each { |c| cookie_jar.add(c) }
expired_cookies.each { |c| cookie_jar.add(c) }
cookie_jar.cleanup
expect(cookie_jar.cookies.length).to eq(2)
expect(cookie_jar.cookies.include?(expired_cookies[0])).to eq(false)
expect(cookie_jar.cookies.include?(expired_cookies[1])).to eq(false)
expect(cookie_jar.cookies.include?(cookies[0])).to eq(true)
expect(cookie_jar.cookies.include?(cookies[1])).to eq(true)
expect(cookie_jar.cookies).to match_array(cookies)
end
end
end

View File

@ -9,6 +9,16 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
let(:cookie) { described_class.new(random_string, random_string) }
NOW = Time.local(2008, 9, 5, 10, 5, 30)
before(:each) do
Timecop.freeze(NOW)
end
after(:each) do
Timecop.return
end
describe 'name' do
describe 'String' do
it 'is assigned to name successfully' do
@ -225,10 +235,10 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
# then path is set to A
describe 'Complex Object' do
it 'which is a kind of String will be passed to path successfully' do
class MyString < String
clazz = Class.new(String) do
end
str = "/#{random_string(0)}"
my_str = MyString.new(str)
my_str = clazz.new(str)
cookie.path = my_str
@ -237,7 +247,7 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
end
describe 'nil' do
it 'assigned to path successfully' do
it 'assigned to expired successfully' do
n = nil
cookie.expires = n
@ -279,113 +289,6 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
end
end
# describe "origin" do
# before do
# cookie = Msf::Exploit::Remote::HTTP::HttpCookie.new('Name', 'Value')
# end
#
# describe 'Origin already set with value' do
# it "when being set with any value will throw an ArgumentError" do
# n = ''
#
# cookie.origin = n
#
# expect {
# cookie.origin = n
# }.to raise_error(ArgumentError)
# end
# end
#
# describe "String" do
# it "of URL without protocol is assigned to origin without altering domain OR path" do
# url_str = random_string
#
# cookie.origin = url_str
#
# expect(cookie.origin.kind_of?(URI)).to eql(true)
# expect(cookie.origin).to eql(URI(url_str))
# expect(cookie.domain).to eql(nil)
# expect(cookie.path).to eql(nil)
# end
#
# it "of HTTP URL with path is assigned to origin, broken out, and domain is populated correctly" do
# domain = "#{random_string}.#{random_string(2,2)}"
# url_str = "http://#{domain}"
#
# cookie.origin = url_str
#
# expect(cookie.origin.instance_of?(URI::HTTP)).to eql(true)
# expect(cookie.origin).to eql(URI(url_str))
# expect(cookie.domain).to eql(domain.downcase)
# expect(cookie.path).to eql('/')
# end
#
# it "of HTTP URL without path is assigned to origin, and domain & path are populated correctly" do
# path = "/#{random_string}/#{random_string}/"
# domain = "#{random_string}.#{random_string(2,2)}"
# url_str = "http://#{domain}#{path}#{random_string}"
#
# cookie.origin = url_str
#
# expect(cookie.origin.instance_of?(URI::HTTP)).to eql(true)
# expect(cookie.origin).to eql(URI(url_str))
# expect(cookie.domain).to eql(domain.downcase)
# expect(cookie.path).to eql(path)
# end
#
# it "of HTTPS URL with path is assigned to origin, broken out, and domain is populated correctly" do
# domain = "#{random_string}.#{random_string(2,2)}"
# url_str = "https://#{domain}"
#
# cookie.origin = url_str
#
# expect(cookie.origin.instance_of?(URI::HTTPS)).to eql(true)
# expect(cookie.origin).to eql(URI(url_str))
# expect(cookie.domain).to eql(domain.downcase)
# expect(cookie.path).to eql('/')
# end
#
# it "of HTTPS URL without path is assigned to origin, and domain & path are populated correctly" do
# path = "/#{random_string}/#{random_string}/"
# domain = "#{random_string}.#{random_string(2,2)}"
# url_str = "https://#{domain}#{path}#{random_string}"
#
# cookie.origin = url_str
#
# expect(cookie.origin.instance_of?(URI::HTTPS)).to eql(true)
# expect(cookie.origin).to eql(URI(url_str))
# expect(cookie.domain).to eql(domain.downcase)
# expect(cookie.path).to eql(path)
# end
# end
#
# describe 'URI' do
# it "instance of URI::Generic will be passed to origin successfully" do
# url = URI(random_string)
#
# cookie.origin = url
#
# expect(cookie.origin).to eql(url)
# end
#
# it "instance of URI::HTTP will be passed to origin successfully" do
# url = URI('http://' + random_string)
#
# cookie.origin = url
#
# expect(cookie.origin).to eql(url)
# end
#
# it "URI::HTTPS will be passed to origin successfully" do
# url = URI('https://' + random_string)
#
# cookie.origin = url
#
# expect(cookie.origin).to eql(url)
# end
# end
# end
describe 'httponly' do
describe 'Truthy' do
it 'empty string passed to httponly is set as true' do
@ -440,64 +343,6 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
end
end
# describe 'for_domain' do
# before do
# cookie = Msf::Exploit::Remote::HTTP::HttpCookie.new('Name', 'Value')
# end
#
# describe "Truthy" do
# it "empty string passed to for_domain is set as true" do
# str = ''
#
# cookie.for_domain = str
#
# expect(cookie.for_domain).to eql(true)
# end
#
# it "populated string passed to for_domain is set as true" do
# str = random_string
#
# cookie.for_domain = str
#
# expect(cookie.for_domain).to eql(true)
# end
#
# it "integer passed to for_domain is set as true" do
# int = rand(0..10)
#
# cookie.for_domain = int
#
# expect(cookie.for_domain).to eql(true)
# end
#
# it "true passed to for_domain is set as true" do
# t = true
#
# cookie.for_domain = t
#
# expect(cookie.for_domain).to eql(true)
# end
# end
#
# describe "Falsey" do
# it "nil passed to for_domain is set as false" do
# n = nil
#
# cookie.for_domain = n
#
# expect(cookie.for_domain).to eql(false)
# end
#
# it "false passed to for_domain is set as false" do
# f = false
#
# cookie.for_domain = f
#
# expect(cookie.for_domain).to eql(false)
# end
# end
# end
describe 'secure' do
describe 'Truthy' do
it 'empty string passed to secure is set as true' do
@ -645,30 +490,44 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
end
describe 'session' do
describe 'Session' do
it 'is set as True when initialized with no max_age or expires args and a nil value' do
# cookie created in before
it 'is set as True when initialized with no max_age or expires args and a nil value' do
# cookie created in before
s = cookie.session?
s = cookie.session?
expect(s).to eql(true)
end
expect(s).to eql(true)
end
it 'is set as the nil? value of max_age when a valid value is assigned to max_age' do
max_age = rand(0..1) == 1 ? 1 : nil
it 'is set to true when nil is assigned to max_age' do
max_age = nil
cookie.max_age = max_age
cookie.max_age = max_age
expect(cookie.session?).to eql(max_age.nil?)
end
expect(cookie.session?).to eq(true)
end
it 'is set as the nil? value of expires when a valid value is assigned to expires' do
expires = rand(0..1) == 1 ? Time.now : nil
it 'is set to false when an integer > 0 is assigned to max_age' do
max_age = Faker::Number.within(range: 1..100)
cookie.expires = expires
cookie.max_age = max_age
expect(cookie.session?).to eql(expires.nil?)
end
expect(cookie.session?).to eq(false)
end
it 'is set to true when nil is assigned to expires' do
expires = nil
cookie.expires = expires
expect(cookie.session?).to eq(true)
end
it 'is set to false when a valid Time is assigned to expires' do
expires = Time.now
cookie.expires = expires
expect(cookie.session?).to eq(false)
end
end
@ -692,23 +551,38 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
expect(cookie.expired?).to eql(false)
end
it 'call of expired? with a valid expires value will return True/False depending on if the value is before Time.now' do
expired = rand(0..1) == 1
t = expired ? Faker::Time.backward(days: 1) : Faker::Time.forward(days: 1)
it 'call of expired? will return true when expires is set to a Time in the past' do
t = Faker::Time.backward(days: 1)
cookie.expires = t
expect(cookie.expired?).to eql(expired)
expect(cookie.expired?).to eql(true)
end
it 'call of expired? with a valid max_age value will return True/False depending on if the value is before Time.now' do
expired = rand(0..1) == 1
m = expired ? 1 : 1000
it 'call of expired? will return false when expires is set to a Time in the future' do
t = Faker::Time.forward(days: 1)
cookie.max_age = m
sleep(1)
cookie.expires = t
expect(cookie.expired?).to eql(expired)
expect(cookie.expired?).to eql(false)
end
it 'call of expired? will return true when max_age in seconds plus cookie.created_at is before Time.now' do
max_age = 1
cookie.max_age = max_age
cookie.created_at = NOW - 5.seconds
expect(cookie.expired?).to eql(true)
end
it 'call of expired? will return false when max_age in seconds plus cookie.created_at is after Time.now' do
max_age = 10
cookie.max_age = max_age
cookie.created_at = NOW - 5.seconds
expect(cookie.expired?).to eql(false)
end
end
@ -742,13 +616,6 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
end
end
# if @domain.nil?
# raise "cannot tell if this cookie is valid because the domain is unknown"
# end
# uri = URI(uri)
# # RFC 6265 5.4
# return false if secure? && !(URI::HTTPS === uri)
# acceptable_from_uri?(uri) && HTTP::Cookie.path_match?(@path, uri.path)
describe 'valid_for_uri?' do
it "will return false when domain hasn't been set" do
# domain set as nil in before
@ -793,7 +660,7 @@ RSpec.describe Msf::Exploit::Remote::HTTP::HttpCookie do
expect(v).to eq(false)
end
it 'will return true if url with http(s) protocol is passed with a domain that watches the url domain' do
it 'will return true if url with http(s) protocol is passed with a domain that matches the url domain' do
host = random_string
uri = "http://#{host}/#{random_string}"
cookie.domain = host