Module: Msf::Auxiliary::Web::Analysis::Timing

Defined in:
lib/msf/core/auxiliary/web/analysis/timing.rb

Constant Summary collapse

TIMING_OPTIONS =
{
  # stub to be replaced by delay * multi
  :stub =>  '__TIME__',

  # stub = delay * multi
  :multi => 1,

  # delay in seconds to attempt to introduce
  :delay => 5
}

Instance Method Summary collapse

Instance Method Details

#if_responsive(timeout = 120, &callback) ⇒ Object


94
95
96
# File 'lib/msf/core/auxiliary/web/analysis/timing.rb', line 94

def if_responsive( timeout = 120, &callback )
  responsive_async?( timeout ) { |b| callback.call if b }
end

#if_unresponsive(timeout = 120, &callback) ⇒ Object


98
99
100
# File 'lib/msf/core/auxiliary/web/analysis/timing.rb', line 98

def if_unresponsive( timeout = 120, &callback )
  responsive_async?( timeout ) { |b| callback.call if !b }
end

#responsive?(timeout = 120) ⇒ Boolean


86
87
88
# File 'lib/msf/core/auxiliary/web/analysis/timing.rb', line 86

def responsive?( timeout = 120 )
  !submit( :timeout => timeout ).timed_out?
end

#responsive_async?(timeout = 120, &callback) ⇒ Boolean


90
91
92
# File 'lib/msf/core/auxiliary/web/analysis/timing.rb', line 90

def responsive_async?( timeout = 120, &callback )
  submit_async( :timeout => timeout ) { |r| callback.call !r.timed_out? }
end

#timeout_analysis(opts = {}) ⇒ Object

Performs timeout/time-delay analysis and logs an issue should there be one.

Fuzzer must provide:

- #seeds_for -- Array of Strings with server-side code which, when interpreted,
    will cause a delay in response. Must include 'stub'.

Here's how it goes:

  • Ensures that the server is responsive.

  • Injects the seed and makes sure that the expected delay has been successfully introduced.

  • Ensures that the server is responsive – blocks until the attack has worn off.

  • Increases the original delay and makes sure that the expected delay has been successfully introduced.

  • Ensures that the server is responsive– blocks until the attack has worn off.

  • Logs the vulnerability.

opts - Options Hash (default: {})

:timeout - Integer amount of seconds to wait for the request to complete (default: 5)
:stub - String stub to be replaced by delay * multi (default: __TIME__)
:multi - Integer multiplier (stub = timeout * multi) (default: 1)

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/msf/core/auxiliary/web/analysis/timing.rb', line 44

def timeout_analysis( opts = {} )
  opts = TIMING_OPTIONS.merge( opts )

  multi   = opts[:multi]
  stub    = opts[:stub]

  return if fuzzed? :type => :timing
  fuzzed :type => :timing

  permutations.each do |p|
    timeout = opts[:delay]

    seed    = p.altered_value.dup
    payload = fuzzer.payloads.select{ |pl| seed.include?( pl ) }.
      sort_by { |p2| p2.size }.last

    # 1st pass, make sure the webapp is responsive
    if_responsive do
      # 2nd pass, see if we can manipulate the response times
      timeout += 1
      p.altered_value = seed.gsub( stub, (timeout * multi).to_s )

      p.if_unresponsive( timeout - 1 ) do
        # 3rd pass, make sure that the previous step wasn't a fluke (like a dead web server)
        if_responsive do
          # 4th pass, increase the delay and timeout to make sure that we are the ones
          # manipulating the webapp and this isn't all a coincidence
          timeout *= 2
          timeout += 1
          p.altered_value = seed.gsub( stub, (timeout * multi).to_s )

          p.if_unresponsive( timeout - 1 ) do
            # log it!
            fuzzer.process_vulnerability( p, 'Manipulatable response times.',
              :payload => payload.gsub( stub, (timeout * multi).to_s ) )
          end
        end
      end
    end
  end
end