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

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

Defined Under Namespace

Modules: Format

Constant Summary collapse

MUTATION_OPTIONS =

Default formatting and permutation 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 ],


    # Skip mutation with default/original values
    # (for {Arachni::Element::Form} elements).
    skip_orig:  false,

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

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

    # `nil`:   Use system settings (!Options.fuzz_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

#alteredString

Returns Name of the altered/mutated parameter.

Returns:

  • (String)

    Name of the altered/mutated parameter.



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

def altered
  @altered
end

Instance Method Details

#altered_valueString

Returns Value of the altered input.

Returns:

  • (String)

    Value of the altered input.



75
76
77
# File 'lib/arachni/element/capabilities/mutable.rb', line 75

def altered_value
    self[altered].to_s
end

#altered_value=(value) ⇒ Object

Parameters:

  • value (String)

    Sets the value for the altered input.



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

def altered_value=( value )
    self[altered] = value
end

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

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

Vector names in #immutables will be excluded.

Parameters:

Yields:

  • (mutation)

    Each generated mutation.

Yield Parameters:

See Also:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
# File 'lib/arachni/element/capabilities/mutable.rb', line 111

def each_mutation( injection_str, opts = {} )
    return [] if self.auditable.empty?

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

    inputs  = auditable.dup
    cinputs = Support::KeyFiller.fill( inputs )

    generated = Support::LookUp::HashSet.new

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

        opts[:format].each do |format|

            str = format_str( injection_str, cinputs[k], format )

            elem           = self.dup
            elem.altered   = k.dup
            elem.auditable = cinputs.merge( k => str )

            yield elem if !generated.include?( elem )
            generated << elem

            next if opts[:respect_method]

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

    return if !opts[:param_flip]

    elem = self.dup

    # When under HPG mode element auditing is strictly regulated
    # and when we flip params we essentially create a new element
    # which won't be on the whitelist.
    elem.override_instance_scope

    elem.altered = 'Parameter flip'
    elem[injection_str] = seed

    yield elem if !generated.include?( elem )
    generated << elem

    return if opts[:respect_method]

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

    nil
end

#immutablesSet

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

Returns:

  • (Set)

    Names of input vectors to be excluded from #mutations.



95
96
97
# File 'lib/arachni/element/capabilities/mutable.rb', line 95

def immutables
    @immutables ||= Set.new
end

#mutated?Bool

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

Returns:

  • (Bool)

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



90
91
92
# File 'lib/arachni/element/capabilities/mutable.rb', line 90

def mutated?
    !original?
end

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

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

Vector names in #immutables will be excluded.

Parameters:

Returns:

See Also:



195
196
197
198
199
200
# File 'lib/arachni/element/capabilities/mutable.rb', line 195

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

#mutations_for(*args) ⇒ Object

Alias for #mutations.



203
204
205
# File 'lib/arachni/element/capabilities/mutable.rb', line 203

def mutations_for( *args )
    mutations( *args )
end

#original?Bool

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

Returns:

  • (Bool)

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



85
86
87
# File 'lib/arachni/element/capabilities/mutable.rb', line 85

def original?
    self.altered.nil?
end

#permutations(*args) ⇒ Object

Alias for #mutations.



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

def permutations( *args )
    mutations( *args )
end

#permutations_for(*args) ⇒ Object

Alias for #mutations.



211
212
213
# File 'lib/arachni/element/capabilities/mutable.rb', line 211

def permutations_for( *args )
    permutations( *args )
end

#switch_methodObject



169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/arachni/element/capabilities/mutable.rb', line 169

def switch_method
    c = self.dup
    if c.method.to_s.downcase.to_sym == :get
        # Strip the query from the action if we're fuzzing a link
        # otherwise the GET params might get precedence.
        c.action = c.action.split( '?' ).first if c.is_a? Link
        c.method = 'post'
    else
        c.method = 'get'
    end
    c
end