Class: Arachni::Session

Inherits:
Object show all
Includes:
UI::Output, Utilities
Defined in:
lib/arachni/session.rb

Overview

Session management class.

Handles logins, provided log-out detection, stores and executes login sequences and provided general webapp session related helpers.

Author:

Defined Under Namespace

Classes: Error

Constant Summary collapse

LOGIN_TRIES =
5
LOGIN_RETRY_WAIT =
5

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utilities

#available_port, #cookie_encode, #cookies_from_document, #cookies_from_file, #cookies_from_response, #exception_jail, #exclude_path?, #extract_domain, #follow_protocol?, #form_decode, #form_encode, #form_parse_request_body, #forms_from_document, #forms_from_response, #generate_token, #get_path, #html_decode, #html_encode, #include_path?, #links_from_document, #links_from_response, #normalize_url, #page_from_response, #page_from_url, #parse_query, #parse_set_cookie, #parse_url_vars, #path_in_domain?, #path_too_deep?, #port_available?, #rand_port, #redundant_path?, #remove_constants, #seed, #skip_page?, #skip_path?, #skip_resource?, #to_absolute, #uri_decode, #uri_encode, #uri_parse, #uri_parser, #url_sanitize

Methods included from UI::Output

#debug?, #debug_off, #debug_on, #disable_only_positives, #error_logfile, #flush_buffer, #log_error, #mute, #muted?, old_reset_output_options, #only_positives, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_pp, #print_error, #print_error_backtrace, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, reset_output_options, #set_buffer_cap, #set_error_logfile, #uncap_buffer, #unmute, #verbose, #verbose?

Constructor Details

#initialize(opts = Arachni::Options.instance) ⇒ Session

Returns a new instance of Session.



101
102
103
# File 'lib/arachni/session.rb', line 101

def initialize( opts = Arachni::Options.instance )
    @opts = opts
end

Instance Attribute Details

#login_check(&block) ⇒ Block

A block used to check whether or not we’re logged in to the webapp.

It should:

* return `true` on success, `false` on failure.
* expect 2 parameters, the first one being a hash of HTTP options and
    the second one an optional block.

If a block has been set, the check should work async and pass the result to the block, otherwise it should simply return the result.

The result of the check should be ‘true` or `false`.

A good example of this can be found in #set_login_check.

Returns:

  • (Block)

See Also:



86
87
88
# File 'lib/arachni/session.rb', line 86

def 
  @login_check
end

#login_formElement::Form

Sets a login form and generates a login sequence from it.

The form must be kosher, best be generated by one of the Element::Form helpers, Parser or #find_login_form.

Once you get the right form you need to update it with the appropriate values before passing it to this accessor.

Returns:



99
100
101
# File 'lib/arachni/session.rb', line 99

def 
  @login_form
end

#login_sequence(&block) ⇒ Block

A block used to login to the webapp.

The block should log the framework into the webapp and return ‘true` on success, `false` on failure.

Parameters:

  • block (Block)

    if a block has been given it will be set as the login sequence.

Returns:

  • (Block)


64
65
66
# File 'lib/arachni/session.rb', line 64

def 
  @login_sequence
end

#optsOptions (readonly)

Returns options.

Returns:



54
55
56
# File 'lib/arachni/session.rb', line 54

def opts
  @opts
end

Instance Method Details

#can_login?Bool

Returns ‘true` if there is log-in capability, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if there is log-in capability, `false` otherwise.



185
186
187
# File 'lib/arachni/session.rb', line 185

def can_login?
     && @login_check
end

Tries to find the main session (login/ID) cookie.

Parameters:

  • block (Block)

    block to be passed the cookie

Raises:



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/arachni/session.rb', line 117

def cookie( &block )
    return block.call( @session_cookie ) if @session_cookie
    fail Error::NoLoginCheck, 'No login-check has been configured.' if !

    cookies.each do |cookie|
        logged_in?( cookies: { cookie.name => '' } ) do |bool|
            next if bool
            block.call( @session_cookie = cookie )
        end
    end
end

#cookiesArray<Element::Cookie>

Returns session cookies.

Returns:



106
107
108
# File 'lib/arachni/session.rb', line 106

def cookies
    http.cookies.select{ |c| c.session? }
end

#ensure_logged_inBool?

Returns ‘true` if logged-in, `false` otherwise, `nil` if there’s no log-in capability.

Returns:

  • (Bool, nil)

    ‘true` if logged-in, `false` otherwise, `nil` if there’s no log-in capability.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/arachni/session.rb', line 192

def ensure_logged_in
    return if !can_login?
    return true if logged_in?

    print_bad 'The scanner has been logged out.'
    print_info 'Trying to re-login...'

    LOGIN_TRIES.times do |i|
        break if 
        print_bad "Login attempt #{i+1} failed, retrying after " <<
                      "#{LOGIN_RETRY_WAIT} seconds..."
        sleep LOGIN_RETRY_WAIT
    end

    if !logged_in?
        print_bad 'Could not re-login.'
        false
    else
        print_ok 'Logged-in successfully.'
        true
    end
end

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

Finds a login forms based on supplied location, collection and criteria.

Parameters:

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

    if a block and a :url are given, the request will run async and the block will be called with the result of this method.

Options Hash (opts):

  • :requires_password (Bool)

    Does the login form include a password field? (Defaults to ‘true`)

  • :action (Array, Regexp)

    Regexp to match or String to compare against the form action.

  • :inputs (String, Array, Hash, Symbol)

    Inputs that the form must contain.

  • :forms (Array<Element::Form>)

    Collection of forms to look through.

  • :pages (Page, Array<Page>)

    Pages to look through.

  • :url (String)

    URL to fetch and look for forms.



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
# File 'lib/arachni/session.rb', line 144

def ( opts = {}, &block )
    async = block_given?

    requires_password = (opts[:requires_password].nil? ? true : opts[:requires_password])

    find = proc do |cforms|
        cforms.select do |f|
            next if requires_password && !f.requires_password?

            oks   = []

            if action = opts[:action]
                oks << !!(action.is_a?( Regexp ) ? f.action =~ action : f.action == action)
            end

            if inputs = opts[:inputs]
                oks << f.has_inputs?( inputs )
            end

            oks.count( true ) == oks.size
        end.first
    end

    forms = if opts[:pages]
                [opts[:pages]].flatten.map { |p| p.forms }.flatten
            elsif opts[:forms]
                opts[:forms]
            elsif url = opts[:url]
                http_opts = { http: { update_cookies: true } }

                if async
                    page_from_url( url, http_opts ) { |p| block.call find.call( p.forms ) }
                else
                    page_from_url( url, http_opts ).forms
                end
            end

    find.call( forms || [] ) if !async
end

#has_login_check?Bool

Returns ‘true` if a login check exists, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if a login check exists, `false` otherwise.



249
250
251
# File 'lib/arachni/session.rb', line 249

def 
    !!
end

#has_login_sequence?Bool

Returns ‘true` if a login sequence exists, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if a login sequence exists, `false` otherwise.



227
228
229
# File 'lib/arachni/session.rb', line 227

def 
    !!
end

#httpHTTP

Returns http interface.

Returns:

  • (HTTP)

    http interface



314
315
316
# File 'lib/arachni/session.rb', line 314

def http
    HTTP
end

#logged_in?(http_opts = {}, &block) ⇒ Bool?

Uses the block in #login_check to check in we’re logged in to the webapp.

Parameters:

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

    Extra HTTP options to use for the check.

  • block (Block)

    If a block has been provided the check will be async and the result will be passed to it, otherwise the method will return the result.

Returns:

  • (Bool, nil)

    ‘true` if we’re logged-in, ‘false` if not, `nil` if no #login_sequence has been set.



244
245
246
# File 'lib/arachni/session.rb', line 244

def logged_in?( http_opts = {}, &block )
    .call( http_opts, block ) if 
end

#loginBool?

Uses the block in #login_sequence to login to the webapp.

Returns:

  • (Bool, nil)

    ‘true` if login was successful, `false` if not, `nil` if no #login_sequence has been set.



222
223
224
# File 'lib/arachni/session.rb', line 222

def 
    .call if 
end

#set_login_check(url, pattern) ⇒ Object

Sets a login check using the provided ‘url` and `regexp`.

Parameters:

  • url (String, #to_s)

    URL to request.

  • pattern (String, Regexp)

    Pattern to match against the body of the response.



301
302
303
304
305
306
307
308
309
310
311
# File 'lib/arachni/session.rb', line 301

def ( url, pattern )
     do |opts, block|
        bool = nil
        http.get( url.to_s, opts.merge( async: !!block ) ) do |res|
            bool = !!res.body.match( pattern )
            block.call( bool ) if block
        end

        bool
    end
end