Class: Arachni::Element::Auditable

Inherits:
Object
  • Object
show all
Includes:
Module::Utilities
Defined in:
lib/parser/auditable.rb

Direct Known Subclasses

Parser::Element::Base

Defined Under Namespace

Modules: Format

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Module::Utilities

#exception_jail, #get_path, #normalize_url, #read_file, #seed

Instance Attribute Details

#alteredObject

Returns the value of attribute altered.



17
18
19
# File 'lib/parser/auditable.rb', line 17

def altered
  @altered
end

#optsObject (readonly)

Returns the value of attribute opts.



18
19
20
# File 'lib/parser/auditable.rb', line 18

def opts
  @opts
end

Class Method Details

.resetObject



13
14
15
# File 'lib/parser/auditable.rb', line 13

def self.reset
    @@audited = Set.new
end

Instance Method Details

#audit(injection_str, opts = { }, &block) ⇒ Object

Audits self

Parameters:

  • injection_str (String)

    the string to be injected

  • opts (Hash) (defaults to: { })

    options as described in Module::Auditor#OPTIONS

  • &block (Block)

    block to be passed the:

    • HTTP response

    • name of the input vector

    • updated opts

    The block will be called as soon as the
    HTTP response is received.
    


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
# File 'lib/parser/auditable.rb', line 116

def audit( injection_str, opts = { }, &block )

    # respect user audit options
    audit_opt = "@audit_#{self.type}s"
    return if !Arachni::Options.instance.instance_variable_get( audit_opt )

    @@audited ||= Set.new

    opts            = Arachni::Module::Auditor::OPTIONS.merge( opts )
    opts[:element]  = self.type

    opts[:injected_orig] = injection_str

    # if we don't have any auditable elements just return
    return if auditable.empty?

    audit_id = audit_id( injection_str, opts )
    return if !opts[:redundant] && audited?( audit_id )

    results = []
    # iterate through all variation and audit each one
    injection_sets( injection_str, opts ).each {
        |elem|

        opts[:altered] = elem.altered.dup

        return if skip?( elem )

        # inform the user about what we're auditing
        print_status( get_status_str( opts[:altered] ) )

        # submit the element with the injection values
        req = elem.submit( opts )
        return if !req

        on_complete( req, elem, &block )
        req.after_complete {
            |result|
            results << result.flatten[1] if result.flatten[1]
        }
    }

    audited( audit_id )
end

#auditor(auditor) ⇒ Object



48
49
50
# File 'lib/parser/auditable.rb', line 48

def auditor( auditor )
    @auditor = auditor
end

#debug?Boolean

Delegate output related methods to the auditor

Returns:

  • (Boolean)


56
57
58
# File 'lib/parser/auditable.rb', line 56

def debug?
    @auditor.debug? rescue false
end

#get_status_str(altered) ⇒ String

Returns a status string that explaining what’s happening.

The string contains the name of the input that is being audited the url and the type of the input (form, link, cookie…)

Parameters:

  • url (String)

    the url under audit

  • input (Hash)
  • opts (Hash)

Returns:



252
253
254
# File 'lib/parser/auditable.rb', line 252

def get_status_str( altered )
    return "Auditing #{self.type} variable '" + altered + "' of " + @action
end

#http_request(url, opts) ⇒ Object

Callback invoked by #audit to submit the object via Module::HTTP.

Must be implemented by the extending class.

Parameters:

See Also:



84
85
86
# File 'lib/parser/auditable.rb', line 84

def http_request( url, opts )

end

#infoObject

impersonate the auditor to the output methods



236
237
238
# File 'lib/parser/auditable.rb', line 236

def info
    @auditor ? @auditor.class.info : { :name => '' }
end

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

Injectes the injecton_str in self’s values according to formatting options and returns an array of hashes in the form of:

<altered_variable>   => <new element>

Parameters:

  • injection_str (String)

    the string to inject

Returns:

  • (Array)


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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/parser/auditable.rb', line 174

def injection_sets( injection_str, opts = { } )

    opts = Arachni::Module::Auditor::OPTIONS.merge( opts )
    hash = auditable( ).dup

    var_combo = []
    if( !hash || hash.size == 0 ) then return [] end

    if( self.is_a?( Arachni::Parser::Element::Form ) )

        if !audited?( audit_id( Arachni::Parser::Element::Form::FORM_VALUES_ORIGINAL ) )
            # this is the original hash, in case the default values
            # are valid and present us with new attack vectors
            elem = self.dup
            elem.altered = Arachni::Parser::Element::Form::FORM_VALUES_ORIGINAL
            var_combo << elem
        end

        if !audited?( audit_id( Arachni::Parser::Element::Form::FORM_VALUES_SAMPLE ) )
            duphash = hash.dup
            elem = self.dup
            elem.auditable = Arachni::Module::KeyFiller.fill( duphash )
            elem.altered = Arachni::Parser::Element::Form::FORM_VALUES_SAMPLE
            var_combo << elem
        end
    end

    chash = hash.dup
    hash.keys.each {
        |k|

        # don't audit parameter flips
        next if hash[k] == seed

        chash = Arachni::Module::KeyFiller.fill( chash )
        opts[:format].each {
            |format|

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

            elem = self.dup
            elem.altered = k.dup
            elem.auditable = chash.merge( { k => str } )
            var_combo << elem
        }

    }

    if opts[:param_flip]
        elem = self.dup
        elem.altered = 'Parameter flip'
        elem.auditable[injection_str] = seed
        var_combo << elem
    end

    print_debug_injection_set( var_combo, opts )

    return var_combo
end


68
69
70
# File 'lib/parser/auditable.rb', line 68

def print_debug( str = '' )
    @auditor.print_debug( str )
end


60
61
62
# File 'lib/parser/auditable.rb', line 60

def print_error( str = '' )
    @auditor.print_error( str )
end


64
65
66
# File 'lib/parser/auditable.rb', line 64

def print_status( str = '' )
    @auditor.print_status( str )
end

#skip?(elem) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/parser/auditable.rb', line 161

def skip?( elem )
    return @auditor.skip?( elem )
end

#submit(opts = {}) ⇒ Object

Submits self using #http_request.

Parameters:

  • opts (Hash) (defaults to: {})

See Also:



95
96
97
98
99
100
101
102
# File 'lib/parser/auditable.rb', line 95

def submit( opts = {} )

    opts = Arachni::Module::Auditor::OPTIONS.merge( opts )
    opts[:params]  = @auditable.dup
    @opts = opts

    return http_request( @action, opts )
end