module Arachni::Utilities

Includes some useful methods for the system.

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

Public Class Methods

available_port_mutex() click to toggle source
# File lib/arachni/utilities.rb, line 358
def self.available_port_mutex
    @available_port_mutex ||= Mutex.new
end

Public Instance Methods

available_port() click to toggle source

@return [Fixnum]

Random available port number.
# File lib/arachni/utilities.rb, line 343
def available_port
    available_port_mutex.synchronize do
        @used_ports ||= Set.new

        loop do
            port = self.rand_port

            if port_available?( port ) && !@used_ports.include?( port )
                @used_ports << port
                return port
            end
        end
    end
end
bytes_to_kilobytes( bytes ) click to toggle source
# File lib/arachni/utilities.rb, line 415
def bytes_to_kilobytes( bytes )
    (bytes / 1024.0 ).round( 3 )
end
bytes_to_megabytes( bytes ) click to toggle source
# File lib/arachni/utilities.rb, line 411
def bytes_to_megabytes( bytes )
    (bytes / 1024.0 / 1024.0).round( 3 )
end
caller_name() click to toggle source

@return [String]

Filename (without extension) of the caller.
# File lib/arachni/utilities.rb, line 22
def caller_name
    File.basename( caller_path( 3 ), '.rb' )
end
caller_path( offset = 2 ) click to toggle source

@return [String]

Filepath of the caller.
# File lib/arachni/utilities.rb, line 28
def caller_path( offset = 2 )
    ::Kernel.caller[offset].split( /:(\d+):in/ ).first
end
cookies_from_file( *args ) click to toggle source

@see Arachni::Element::Cookie.from_file

# File lib/arachni/utilities.rb, line 88
def cookies_from_file( *args )
    Cookie.from_file( *args )
end
cookies_from_parser( *args ) click to toggle source

@see Arachni::Element::Cookie.from_parser

# File lib/arachni/utilities.rb, line 78
def cookies_from_parser( *args )
    Cookie.from_parser(*args )
end
cookies_from_response( *args ) click to toggle source

@see Arachni::Element::Cookie.from_response

# File lib/arachni/utilities.rb, line 73
def cookies_from_response( *args )
    Cookie.from_response( *args )
end
exception_jail( raise_exception = true, &block ) click to toggle source

Wraps the ‘block` in exception handling code and runs it.

@param [Bool] raise_exception

Re-raise exception?

@param [Block] block

# File lib/arachni/utilities.rb, line 424
def exception_jail( raise_exception = true, &block )
    block.call
rescue => e
    if respond_to?( :print_error ) && respond_to?( :print_exception )
        print_exception e
        print_error
        print_error 'Parent:'
        print_error  self.class.to_s
        print_error
        print_error 'Block:'
        print_error block.to_s
        print_error
        print_error 'Caller:'
        ::Kernel.caller.each { |l| print_error l }
        print_error '-' * 80
    end

    raise e if raise_exception

    nil
end
exclude_path?( url ) click to toggle source

Decides whether the given ‘url` matches any framework exclusion rules.

@param [String] url

@return [Bool]

@see URI.exclude? @see OptionGroups::Scope#exclude_path_patterns

# File lib/arachni/utilities.rb, line 208
def exclude_path?( url )
    uri_parse( url ).scope.exclude?
end
follow_protocol?( url, reference = Options.url ) click to toggle source

Decides whether the given ‘url` has an acceptable protocol.

@param [String] url @param [String] reference Reference URL.

@return [Bool]

@see OptionGroups::Scope#https_only @see OptionGroups::Scope#https_only?

# File lib/arachni/utilities.rb, line 250
def follow_protocol?( url, reference = Options.url )
    uri_parse( url ).scope.follow_protocol?( reference )
end
form_decode( *args ) click to toggle source

@see Arachni::Element::Form.decode

# File lib/arachni/utilities.rb, line 53
def form_decode( *args )
    Form.decode( *args )
end
form_encode( *args ) click to toggle source

@see Arachni::Element::Form.encode

# File lib/arachni/utilities.rb, line 48
def form_encode( *args )
    Form.encode( *args )
end
forms_from_parser( *args ) click to toggle source

@see Arachni::Element::Form.from_parser

# File lib/arachni/utilities.rb, line 43
def forms_from_parser( *args )
    Form.from_parser(*args )
end
forms_from_response( *args ) click to toggle source

@see Arachni::Element::Form.from_response

# File lib/arachni/utilities.rb, line 38
def forms_from_response( *args )
    Form.from_response( *args )
end
full_and_absolute_url?( url ) click to toggle source

@see URI.full_and_absolute?

# File lib/arachni/utilities.rb, line 162
def full_and_absolute_url?( url )
    Arachni::URI.full_and_absolute?( url.to_s )
end
generate_token() click to toggle source
# File lib/arachni/utilities.rb, line 374
def generate_token
    SecureRandom.hex
end
get_path( url ) click to toggle source

@param [String] url

@return [String] path

Full URL up to the path component (no resource, query etc.).

@see URI.up_to_path

# File lib/arachni/utilities.rb, line 172
def get_path( url )
    uri_parse( url ).up_to_path
end
hms_to_seconds( time ) click to toggle source
# File lib/arachni/utilities.rb, line 404
def hms_to_seconds( time )
    a = [1, 60, 3600] * 2
    time.split( /[:\.]/ ).map { |t| t.to_i * a.pop }.inject(&:+)
rescue
    0
end
html_decode( str ) click to toggle source
# File lib/arachni/utilities.rb, line 112
def html_decode( str )
    ::CGI.unescapeHTML( str.to_s )
end
Also aliased as: html_unescape
html_encode( str ) click to toggle source
# File lib/arachni/utilities.rb, line 117
def html_encode( str )
    ::CGI.escapeHTML( str.to_s )
end
Also aliased as: html_escape
html_escape( str )
Alias for: html_encode
html_unescape( str )
Alias for: html_decode
include_path?( url ) click to toggle source

Decides whether the given ‘url` matches any framework inclusion rules.

@param [String] url

@return [Bool]

@see URI.include? @see Options#include

# File lib/arachni/utilities.rb, line 220
def include_path?( url )
    uri_parse( url ).scope.include?
end
normalize_url( url ) click to toggle source

@see URI.normalize

# File lib/arachni/utilities.rb, line 157
def normalize_url( url )
    URI.normalize( url )
end
page_from_response( *args ) click to toggle source

@see Arachni::Page.from_response

# File lib/arachni/utilities.rb, line 103
def page_from_response( *args )
    Page.from_response( *args )
end
page_from_url( *args, &block ) click to toggle source

@see Arachni::Page.from_url

# File lib/arachni/utilities.rb, line 108
def page_from_url( *args, &block )
    Page.from_url( *args, &block )
end
path_in_domain?( url, reference = Options.url ) click to toggle source

Compares 2 urls in order to decide whether or not they belong to the same domain.

@param [String] url @param [String] reference

@return [Bool]

`true` if self is in the same domain as the `reference` URL, false otherwise.

@see URI.in_domain? @see OptionGroups::Scope#include_subdomains

# File lib/arachni/utilities.rb, line 196
def path_in_domain?( url, reference = Options.url )
    uri_parse( url ).scope.in_domain?( reference )
end
path_too_deep?( url ) click to toggle source

@param [String] url

@return [Bool]

`true` is the path exceeds the framework limit, `false` otherwise.

@see URI::Scope.too_deep?

# File lib/arachni/utilities.rb, line 182
def path_too_deep?( url )
    uri_parse( url ).scope.too_deep?
end
port_available?( port ) click to toggle source

Checks whether the port number is available.

@param [Fixnum] port

@return [Bool]

# File lib/arachni/utilities.rb, line 383
def port_available?( port )
    begin
        socket = ::Socket.new( :INET, :STREAM, 0 )
        socket.bind( ::Socket.sockaddr_in( port, '127.0.0.1' ) )
        socket.close
        true
    rescue Errno::EADDRINUSE, Errno::EACCES
        false
    end
end
rand_port() click to toggle source

@return [Integer]

Random port within the user specified range.

@see OptionGroups::Dispatcher#instance_port_range

# File lib/arachni/utilities.rb, line 367
def rand_port
    first, last = Options.dispatcher.instance_port_range
    range = (first..last).to_a

    range[ rand( range.last - range.first ) ]
end
random_seed() click to toggle source

@return [String] random HEX (SHA2) string

# File lib/arachni/utilities.rb, line 33
def random_seed
    @@random_seed ||= generate_token
end
redundant_path?( url, update_counters = false ) click to toggle source

Checks if the provided URL matches a redundant filter and decreases its counter if so.

If a filter’s counter has reached 0 the method returns true.

@param [String] url

@return [Bool]

`true` if the `url` is redundant, `false` otherwise.

@see OptionGroups::Scope#redundant_path_patterns?

# File lib/arachni/utilities.rb, line 235
def redundant_path?( url, update_counters = false )
    uri_parse( url ).scope.redundant?( update_counters )
end
regexp_array_match( regexps, str ) click to toggle source
# File lib/arachni/utilities.rb, line 446
def regexp_array_match( regexps, str )
    regexps = [regexps].flatten.compact.
        map { |s| s.is_a?( Regexp ) ? s : Regexp.new( s.to_s ) }
    return true if regexps.empty?

    cnt = 0
    regexps.each { |filter| cnt += 1 if str =~ filter }
    cnt == regexps.size
end
remove_constants( mod, skip = [] ) click to toggle source
# File lib/arachni/utilities.rb, line 456
def remove_constants( mod, skip = [] )
    return if skip.include?( mod )
    return if !(mod.is_a?( Class ) || mod.is_a?( Module )) ||
        !mod.to_s.start_with?( 'Arachni' )

    parent = Object
    mod.to_s.split( '::' )[0..-2].each do |ancestor|
        parent = parent.const_get( ancestor.to_sym )
    end

    mod.constants.each { |m| mod.send( :remove_const, m ) }
    nil
end
request_parse_body( *args ) click to toggle source

@see Arachni::HTTP::Request.parse_body

# File lib/arachni/utilities.rb, line 58
def request_parse_body( *args )
    HTTP::Request.parse_body( *args )
end
seconds_to_hms( seconds ) click to toggle source

@param [String, Float, Integer] seconds

@return [String]

Time in `00:00:00` (`hours:minutes:seconds`) format.
# File lib/arachni/utilities.rb, line 398
def seconds_to_hms( seconds )
    seconds = seconds.to_i
    [seconds / 3600, seconds / 60 % 60, seconds % 60].
        map { |t| t.to_s.rjust( 2, '0' ) }.join( ':' )
end
skip_page?( page ) click to toggle source

Determines whether or not the given {Arachni::Page}.

@param [Page] page

@return [Bool]

`true` if the `#body` of the given object matches any of the exclusion
patterns or the  {OptionGroups::Scope#dom_depth_limit} has been reached,
`false` otherwise.

@see skip_path? @see OptionGroups::Audit#exclude_binaries? @see OptionGroups::Scope#exclude_page? @see OptionGroups::Scope#dom_depth_limit

# File lib/arachni/utilities.rb, line 304
def skip_page?( page )
    page.scope.out?
end
skip_path?( path ) click to toggle source

@note Does not call {#redundant_path?}.

Decides whether or not the provided ‘path` should be skipped based on:

  • {#include_path?}

  • {#exclude_path?}

  • {#path_too_deep?}

  • {#path_in_domain?}

@param [Arachni::URI, ::URI, Hash, String] path

@return [Bool]

# File lib/arachni/utilities.rb, line 266
def skip_path?( path )
    return true if !path

    parsed = uri_parse( path.to_s )
    return true if !parsed

    parsed.scope.out?
end
skip_resource?( resource ) click to toggle source

Determines whether or not the given ‘resource` should be ignored depending on its type and content.

@param [Page,Arachni::HTTP::Response,String] resource

If given a:

    * {Page}: both its URL and body will be examined.
    * {Arachni::HTTP::Response}: both its effective URL and body will be examined.
    * {String}: if multi-line it will be treated as a response body,
        otherwise as a path.

@return [Bool]

`true` if the resource should be ignore,`false` otherwise.

@see skip_path? @see ignore_page? @see ignore_response? @see Options#ignore?

# File lib/arachni/utilities.rb, line 328
def skip_resource?( resource )
    case resource
        when Page
            skip_page?( resource )

        when Arachni::HTTP::Response
            skip_response?( resource )

        else
            skip_path? resource.to_s
    end
end
skip_response?( response ) click to toggle source

Determines whether or not the given {Arachni::HTTP::Response} should be ignored.

@param [Arachni::HTTP::Response] response

@return [Bool]

`true` if the `#body` of the given object matches any of the exclusion
patterns, `false` otherwise.

@see skip_path? @see OptionGroups::Scope#exclude_binaries? @see OptionGroups::Scope#exclude_page?

# File lib/arachni/utilities.rb, line 287
def skip_response?( response )
    response.scope.out?
end
to_absolute( relative_url, reference_url = Options.instance.url.to_s ) click to toggle source

@see URI.to_absolute

# File lib/arachni/utilities.rb, line 152
def to_absolute( relative_url, reference_url = Options.instance.url.to_s )
    URI.to_absolute( relative_url, reference_url )
end
uri_decode( url ) click to toggle source

@see URI.encode

# File lib/arachni/utilities.rb, line 138
def uri_decode( url )
    URI.decode( url )
end
uri_encode( *args ) click to toggle source

@see URI.encode

# File lib/arachni/utilities.rb, line 133
def uri_encode( *args )
    URI.encode( *args )
end
uri_parse( url ) click to toggle source

@see URI.parse

# File lib/arachni/utilities.rb, line 128
def uri_parse( url )
    URI.parse( url )
end
uri_parse_query( url ) click to toggle source

@see Arachni::URI.parse_query

# File lib/arachni/utilities.rb, line 147
def uri_parse_query( url )
    URI.parse_query( url )
end
uri_parser() click to toggle source

@return [URI::Parser] cached URI parser

# File lib/arachni/utilities.rb, line 123
def uri_parser
    URI.parser
end
uri_rewrite( *args ) click to toggle source
# File lib/arachni/utilities.rb, line 142
def uri_rewrite( *args )
    URI.rewrite( *args )
end