Module: Arachni::Element::Capabilities::Mutable

Included in:
Auditable
Defined in:
lib/arachni/element/capabilities/mutable.rb

Overview

Author:

Defined Under Namespace

Modules: Format

Constant Summary collapse

MUTATION_OPTIONS =

Default formatting and mutation options.

{
    #
    # Formatting of the injection strings.
    #
    # A new set of audit inputs will be generated for each value in the array.
    #
    # Values can be OR'ed bitfields of all available constants of {Format}.
    #
    format:         [ Format::STRAIGHT, Format::APPEND,
                        Format::NULL, Format::APPEND | Format::NULL ],

    # Flip injection value and input name.
    param_flip:     false,

    # Array of parameter names remain untouched.
    skip:           [],

    # `nil`:   Use system settings (!Options.audit.with_both_http_methods).
    # `true`:  Don't create mutations with other methods (GET/POST).
    # `false`: Create mutations with other methods (GET/POST).
    respect_method: nil
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#affected_input_nameString

Returns Name of the mutated parameter.

Returns:

  • (String)

    Name of the mutated parameter.



17
18
19
# File 'lib/arachni/element/capabilities/mutable.rb', line 17

def affected_input_name
  @affected_input_name
end

#formatObject

Returns the value of attribute format.



23
24
25
# File 'lib/arachni/element/capabilities/mutable.rb', line 23

def format
  @format
end

#seedString

Returns Original seed used for the #mutations.

Returns:



21
22
23
# File 'lib/arachni/element/capabilities/mutable.rb', line 21

def seed
  @seed
end

Instance Method Details

#affected_input_valueni, String

Returns ‘nil` if no input has been fuzzed, the `String` value of the fuzzed input.

Returns:

  • (ni, String)

    ‘nil` if no input has been fuzzed, the `String` value of the fuzzed input.



80
81
82
83
# File 'lib/arachni/element/capabilities/mutable.rb', line 80

def affected_input_value
    return if !affected_input_name
    self[affected_input_name].to_s
end

#affected_input_value=(value) ⇒ Object

Parameters:

  • value (String)

    Sets the value for the fuzzed input.



87
88
89
# File 'lib/arachni/element/capabilities/mutable.rb', line 87

def affected_input_value=( value )
    self[affected_input_name] = value
end

#dupObject



243
244
245
# File 'lib/arachni/element/capabilities/mutable.rb', line 243

def dup
    copy_mutable( super )
end

#each_mutation(payload, opts = {}) {|mutation| ... } ⇒ Object

Note:

Vector names in #immutables will be excluded.

Injects the ‘payload` in self’s values according to formatting options and returns an array of mutations of self.

Parameters:

Yields:

  • (mutation)

    Each generated mutation.

Yield Parameters:

See Also:



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/arachni/element/capabilities/mutable.rb', line 130

def each_mutation( payload, opts = {} )
    return if self.inputs.empty?

    if !valid_input_data?( payload )
        print_debug_level_2 "Payload not supported by #{self}: #{payload.inspect}"
        return
    end

    print_debug_trainer( opts )
    print_debug_formatting( opts )

    opts = MUTATION_OPTIONS.merge( opts )
    opts[:respect_method] = !Options.audit.with_both_http_methods? if opts[:respect_method].nil?

    dinputs = inputs.dup
    cinputs = Options.input.fill( inputs )

    generated = Support::LookUp::HashSet.new( hasher: :mutable_id )

    dinputs.keys.each do |k|
        # Don't audit parameter flips.
        next if dinputs[k] == seed || immutables.include?( k )

        opts[:format].each do |format|
            str = format_str( payload, cinputs[k], format )

            if !valid_input_value_data?( str )
                print_debug_level_2 'Payload not supported as input value by' <<
                                        " #{audit_id}: #{str.inspect}"
                next
            end

            elem                     = self.dup
            elem.seed                = payload
            elem.affected_input_name = k.dup
            elem.inputs              = cinputs.merge( k => str )
            elem.format              = format

            if !generated.include?( elem )
                print_debug_mutation elem
                yield elem
            end

            generated << elem

            next if opts[:respect_method]

            celem = elem.switch_method
            if !generated.include?( celem )
                print_debug_mutation elem
                yield celem
            end
            generated << celem
        end
    end

    if opts[:param_flip]
        if valid_input_name_data?( payload )
            elem                     = self.dup
            elem.affected_input_name = 'Parameter flip'
            elem[payload]            = seed
            elem.seed                = payload

            if !generated.include?( elem )
                print_debug_mutation elem
                yield elem
            end
            generated << elem
        else
            print_debug_level_2 'Payload not supported as input name by' <<
                                    " #{audit_id}: #{payload.inspect}"
            return
        end
    end

    nil
end

#immutablesSet

Returns Names of input vectors to be excluded from #mutations.

Returns:

  • (Set)

    Names of input vectors to be excluded from #mutations.



111
112
113
# File 'lib/arachni/element/capabilities/mutable.rb', line 111

def immutables
    @immutables ||= Set.new
end

#mutation?Bool

Returns ‘true` if the element has been mutated, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the element has been mutated, `false` otherwise.



105
106
107
# File 'lib/arachni/element/capabilities/mutable.rb', line 105

def mutation?
    !!self.affected_input_name
end

#mutations(payload, opts = {}) ⇒ Array

Injects the ‘payload` in self’s values according to formatting options and returns an array of mutations of self.

Vector names in #immutables will be excluded.

Parameters:

Returns:

See Also:



225
226
227
228
229
# File 'lib/arachni/element/capabilities/mutable.rb', line 225

def mutations( payload, opts = {} )
    combo = []
    each_mutation( payload, opts ) { |m| combo << m }
    combo
end

#resetObject

Resets the inputs to their original format/values.



70
71
72
73
74
75
# File 'lib/arachni/element/capabilities/mutable.rb', line 70

def reset
    super
    @affected_input_name = nil
    @seed                = nil
    self
end

#switch_methodObject



208
209
210
# File 'lib/arachni/element/capabilities/mutable.rb', line 208

def switch_method
    self.dup.tap { |c| c.method = (c.method == :get ? :post : :get) }
end

#to_hObject



231
232
233
234
235
236
237
238
239
240
241
# File 'lib/arachni/element/capabilities/mutable.rb', line 231

def to_h
    h = super

    if mutation?
        h[:affected_input_name]  = self.affected_input_name
        h[:affected_input_value] = self.affected_input_value
        h[:seed]                 = self.seed
    end

    h
end