module Arachni::Element::Form::Capabilities::Mutable

Extends {Arachni::Element::Capabilities::Mutable} with {Form}-specific functionality.

@author Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>

Public Instance Methods

each_mutation( payload, opts = {} ) { |elem| ... } click to toggle source

Overrides {Arachni::Element::Mutable#each_mutation} adding support for mutations with:

  • Sample values (filled by {Arachni::OptionGroups::Input.fill}).

  • Original values.

  • Password fields requiring identical values (in order to pass server-side validation)

@param [String] payload

Payload to inject.

@param [Hash] opts

Mutation options.

@option opts [Bool] :skip_original

Whether or not to skip adding a mutation holding original values and
sample values.

@param (see Arachni::Element::Capabilities::Mutable#each_mutation) @return (see Arachni::Element::Capabilities::Mutable#each_mutation) @yield (see Arachni::Element::Capabilities::Mutable#each_mutation) @yieldparam (see Arachni::Element::Capabilities::Mutable#each_mutation)

@see Arachni::Element::Capabilities::Mutable#each_mutation @see Arachni::OptionGroups::Input.fill

# File lib/arachni/element/form/capabilities/mutable.rb, line 66
def each_mutation( payload, opts = {} )
    opts = MUTATION_OPTIONS.merge( opts )

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

    # Completely remove fake inputs prior to mutation generation, they'll
    # be restored at the end of this method.
    pre_inputs = @inputs
    @inputs    = @inputs.reject{ |name, _| fake_field?( name ) }

    super( payload, opts ) do |elem|
        elem.mirror_password_fields
        yield elem if !generated.include?( elem )
        generated << elem
    end

    return if opts[:skip_original]

    elem = self.dup
    elem.mutation_with_original_values
    elem.affected_input_name = ORIGINAL_VALUES
    yield elem if !generated.include?( elem )
    generated << elem

    # Default select values, in case they reveal new resources.
    inputs.keys.each do |input|
        next if field_type_for( input ) != :select

        # We do the break inside the loop because #node is lazy parsed
        # and we don't want to parse it unless we have a select input.
        break if !node

        node.nodes_by_name( 'select' ).each do |select_node|
            next if select_node['name'] != input

            select_node.children.each do |child|
                next if !child.is_a?( Arachni::Parser::Nodes::Element ) ||
                    child.name != :option

                try_input do
                    elem = self.dup
                    elem.mutation_with_original_values
                    elem.affected_input_name  = input
                    elem.affected_input_value = child['value'] || child.text.strip
                    yield elem if !generated.include?( elem )
                    generated << elem
                end
            end
        end
    end

    try_input do
        # Sample values, in case they reveal new resources.
        elem = self.dup
        elem.inputs = Arachni::Options.input.fill( inputs.dup )
        elem.affected_input_name = SAMPLE_VALUES
        elem.mutation_with_sample_values
        yield elem if !generated.include?( elem )
        generated << elem
    end
ensure
    @inputs = pre_inputs
end
mutation_with_original_values() click to toggle source
# File lib/arachni/element/form/capabilities/mutable.rb, line 26
def mutation_with_original_values
    @mutation_with_original_values = true
end
mutation_with_original_values?() click to toggle source

@return [Bool]

`true` if the element has not been mutated, `false` otherwise.
# File lib/arachni/element/form/capabilities/mutable.rb, line 22
def mutation_with_original_values?
    !!@mutation_with_original_values
end
mutation_with_sample_values() click to toggle source
# File lib/arachni/element/form/capabilities/mutable.rb, line 39
def mutation_with_sample_values
    @mutation_with_sample_values = true
end
mutation_with_sample_values?() click to toggle source

@return [Bool]

`true` if the element has been populated with sample
({Arachni::OptionGroups::Input.fill}) values, `false` otherwise.

@see Arachni::OptionGroups::Input

# File lib/arachni/element/form/capabilities/mutable.rb, line 35
def mutation_with_sample_values?
    !!@mutation_with_sample_values
end