Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions lib/msf/core/exploit/remote/kerberos/client.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: binary -*-

require 'msf/core/exploit/remote/kerberos/clock_skew'
require 'msf/core/opt_timedelta'

module Msf
class Exploit
Expand Down Expand Up @@ -45,8 +45,7 @@ def initialize(info = {})

register_advanced_options(
[
OptString.new('KrbClockSkew', [true, 'Adjust Kerberos client clock by this offset (e.g. 90s, -5m, 1h)', '0s'],
regex: Msf::Exploit::Remote::Kerberos::ClockSkew::CLOCK_SKEW_REGEX)
OptTimedelta.new('KrbClockSkew', [true, 'Adjust Kerberos client clock by this offset (e.g. 90s, -5m, 1h)', '0s'])
], self.class
)
end
Expand Down Expand Up @@ -90,7 +89,7 @@ def kerberos_clock_skew
#
# @param value [String, Numeric, nil]
def kerberos_clock_skew=(value)
@kerberos_clock_skew = Msf::Exploit::Remote::Kerberos::ClockSkew.parse(value)
@kerberos_clock_skew = Msf::OptTimedelta.parse(value)
end

# Returns the current time adjusted for Kerberos clock skew in UTC.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# This class stores Metasploit option configuration used across service authentication
#
require 'msf/core/exploit/remote/kerberos/clock_skew'
require 'msf/core/opt_timedelta'

module Msf::Exploit::Remote::Kerberos::ServiceAuthenticator::Options
# Create the list of options that a module must provide for Kerberos authentication via the given protocol
Expand Down Expand Up @@ -38,10 +38,9 @@ def kerberos_auth_options(protocol:, auth_methods:)
fallbacks: ['Rhostname'],
conditions: option_conditions
),
Msf::OptString.new(
Msf::OptTimedelta.new(
'KrbClockSkew',
[true, 'Adjust Kerberos client clock by this offset (e.g. 90s, -5m, 1h)', '0s'],
regex: Msf::Exploit::Remote::Kerberos::ClockSkew::CLOCK_SKEW_REGEX,
conditions: option_conditions
),
Msf::OptAddress.new(
Expand All @@ -66,6 +65,6 @@ def kerberos_auth_options(protocol:, auth_methods:)
#
# @return [Float]
def kerberos_clock_skew_seconds
Msf::Exploit::Remote::Kerberos::ClockSkew.parse(datastore['KrbClockSkew'])
Msf::OptTimedelta.parse(datastore['KrbClockSkew'])
end
end
64 changes: 64 additions & 0 deletions lib/msf/core/opt_timedelta.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

# -*- coding: binary -*-

module Msf
class OptTimedelta < OptBase
TIMEDELTA_REGEX = /\A([+-]?\d+(?:\.\d+)?(?:[smhd])?)+\z/i.freeze

UNIT_IN_SECONDS = {
's' => 1,
'm' => 60,
'h' => 3_600,
'd' => 86_400
}.freeze

attr_reader :allow_negative

def initialize(in_name, attrs = [], allow_negative: true, **kwargs)
super(in_name, attrs, **kwargs)
@allow_negative = allow_negative
end

def type
'timedelta'
end

def normalize(value)
self.class.parse(value)
end

def valid?(value, check_empty: true, datastore: nil)
return false if check_empty && empty_required_value?(value)

begin
parsed_value = self.class.parse(value)
rescue Msf::OptionValidateError
return false
end

return false if !allow_negative && parsed_value.negative?

super
end

def self.parse(value)
return 0 if value.nil?
return value.to_f if value.is_a?(Numeric)

trimmed_value = value.to_s.strip
return 0 if trimmed_value.empty?
return trimmed_value.to_f if trimmed_value.match?(/\A[+-]?\d+(?:\.\d+)?\z/)
raise Msf::OptionValidateError.new([], message: 'Invalid timedelta format') unless trimmed_value.match?(TIMEDELTA_REGEX)


total = 0
trimmed_value.scan(/([+-]?\d+(?:\.\d+)?)([smhd]?)/i) do |amount, unit|
unit = 's' if unit.blank?
multiplier = UNIT_IN_SECONDS[unit.downcase]
total += amount.to_f * multiplier
end
total
end
end
end
4 changes: 2 additions & 2 deletions lib/rex/proto/mssql/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require 'rex/text'
require 'msf/core/exploit'
require 'msf/core/exploit/remote'
require 'msf/core/exploit/remote/kerberos/clock_skew'
require 'msf/core/opt_timedelta'

module Rex
module Proto
Expand Down Expand Up @@ -389,7 +389,7 @@ def login_kerberos(user, pass, db, domain_name)
framework: framework,
framework_module: framework_module,
ticket_storage: Msf::Exploit::Remote::Kerberos::Ticket::Storage::WriteOnly.new(framework: framework, framework_module: framework_module),
clock_skew: Msf::Exploit::Remote::Kerberos::ClockSkew.parse(framework_module.datastore['KrbClockSkew'])
clock_skew: Msf::OptTimedelta.parse(framework_module.datastore['KrbClockSkew'])
)

kerberos_result = kerberos_authenticator.authenticate
Expand Down
7 changes: 7 additions & 0 deletions spec/lib/msf/core/exploit/remote/kerberos/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
mod
end


describe 'KrbClockSkew option' do
it 'is registered as an OptTimedelta datastore option' do
expect(subject.options['KrbClockSkew']).to be_a(Msf::OptTimedelta)
end
end

describe '#kerberos_clock_skew' do
it 'defaults to zero' do
expect(subject.kerberos_clock_skew).to eq(0)
Expand Down
30 changes: 30 additions & 0 deletions spec/lib/msf/core/opt_timedelta_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding:binary -*-

require 'spec_helper'

RSpec.describe Msf::OptTimedelta do
valid_values = [
{ value: '120', normalized: 120.0 },
{ value: '-5m', normalized: -300.0 },
{ value: '1h30m', normalized: 5_400.0 },
{ value: '2d', normalized: 172_800.0 },
{ value: '+1.5h', normalized: 5_400.0 }
]

invalid_values = [
{ value: 'yolo' },
{ value: '1w' },
{ value: '5mfoo' }
]

it_behaves_like 'an option', valid_values, invalid_values, 'timedelta'

describe '#valid?' do
it 'can enforce positive-only values' do
subject = described_class.new('Duration', [true, 'Duration'], allow_negative: false)

expect(subject.valid?('5m')).to be(true)
expect(subject.valid?('-5m')).to be(false)
end
end
end
Loading