Module: Msf::Auxiliary::Web::Analysis::Differential
- Defined in:
- lib/msf/core/auxiliary/web/analysis/differential.rb
Constant Summary collapse
- DIFFERENTIAL_OPTIONS =
{ # amount of refinement iterations :precision => 2 }
Instance Method Summary collapse
-
#differential_analysis(opts = {}, &block) ⇒ Object
Performs differential analysis and logs an issue should there be one.
Instance Method Details
#differential_analysis(opts = {}, &block) ⇒ Object
Performs differential analysis and logs an issue should there be one.
Fuzzer must provide:
- #boolean_seeds_for - array of boolean injection strings
(these are supposed to not alter the webapp behavior when interpreted)
- #fault_seeds_for - array of fault injection strings
(these are supposed to force erroneous conditions when interpreted)
Here’s how it goes:
-
let default be the default/original response
-
let fault be the response of the fault injection
-
let bool be the response of the boolean injection
A vulnerability is logged if:
default == bool AND bool.code == 200 AND fault != bool
The “bool” response is also checked in order to determine if it’s a custom 404, if it is it’ll be skipped.
42 43 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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/msf/core/auxiliary/web/analysis/differential.rb', line 42 def differential_analysis( opts = {}, &block ) opts = DIFFERENTIAL_OPTIONS.merge( opts ) return if fuzzed? :type => :differential fuzzed :type => :differential # don't continue if there's a missing value params.values.each { |val| return if !val || val.empty? } responses = { # will hold the original, default, response that results from submitting :orig => nil, # will hold responses of boolean injections :good => {}, # will hold responses of fault injections :bad => {} } # submit the element, as is, opts[:precision] amount of times and # rdiff the responses in order to arrive to a refined response without # any superfluous dynamic content opts[:precision].times do # get the default responses submit_async do |res| responses[:orig] ||= res.body.to_s # remove context-irrelevant dynamic content like banners and such responses[:orig] = Rex::Text.refine( responses[:orig], res.body.to_s ) end end # perform fault injection opts[:precision] amount of times and # rdiff the responses in order to arrive to a refined response without # any superfluous dynamic content opts[:precision].times do params.map do |name, value| fuzzer.fault_seeds_for( value ).map { |seed| permutation_for( name, seed ) } end.flatten.uniq.each do |elem| # submit the mutation and store the response elem.submit_async do |res| responses[:bad][elem.altered] ||= res.body.to_s.dup # remove context-irrelevant dynamic content like banners and such # from the error page responses[:bad][elem.altered] = Rex::Text.refine( responses[:bad][elem.altered], res.body.to_s.dup ) end end end # get injection variations that will not affect the outcome of the query params.map do |name, value| fuzzer.boolean_seeds_for( value ).map { |seed| permutation_for( name, seed ) } end.flatten.uniq.each do |elem| # submit the mutation and store the response elem.submit_async do |res| responses[:good][elem.altered] ||= [] # save the response and some data for analysis responses[:good][elem.altered] << { 'res' => res, 'elem' => elem.dup } end end http.after_run do responses[:good].keys.each do |key| responses[:good][key].each do |res| # if default_response_body == bool_response_body AND # fault_response_body != bool_response_body AND # bool_response_code == 200 if responses[:orig] == res['res'].body && responses[:bad][key] != res['res'].body && res['res'].code.to_i == 200 # check to see if the current boolean response we're analyzing # is a custom 404 page http.if_not_custom_404( action, res['res'].body ) do # if this isn't a custom 404 page then it means that # the element is vulnerable, so go ahead and log the issue fuzzer.process_vulnerability( res['elem'], 'Boolean manipulation.' ) end end end end end end |