module Arachni::Utilities
Includes some useful methods for the system.
@author Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>
Public Class Methods
# File lib/arachni/utilities.rb, line 358 def self.available_port_mutex @available_port_mutex ||= Mutex.new end
Public Instance Methods
@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
# File lib/arachni/utilities.rb, line 415 def bytes_to_kilobytes( bytes ) (bytes / 1024.0 ).round( 3 ) end
# File lib/arachni/utilities.rb, line 411 def bytes_to_megabytes( bytes ) (bytes / 1024.0 / 1024.0).round( 3 ) end
@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
@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
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
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
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
@see Arachni::Element::Form.decode
# File lib/arachni/utilities.rb, line 53 def form_decode( *args ) Form.decode( *args ) end
@see Arachni::Element::Form.encode
# File lib/arachni/utilities.rb, line 48 def form_encode( *args ) Form.encode( *args ) end
@see Arachni::Element::Form.from_parser
# File lib/arachni/utilities.rb, line 43 def forms_from_parser( *args ) Form.from_parser(*args ) end
@see Arachni::Element::Form.from_response
# File lib/arachni/utilities.rb, line 38 def forms_from_response( *args ) Form.from_response( *args ) end
# File lib/arachni/utilities.rb, line 162 def full_and_absolute_url?( url ) Arachni::URI.full_and_absolute?( url.to_s ) end
# File lib/arachni/utilities.rb, line 374 def generate_token SecureRandom.hex end
@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
# 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
# File lib/arachni/utilities.rb, line 112 def html_decode( str ) ::CGI.unescapeHTML( str.to_s ) end
# File lib/arachni/utilities.rb, line 117 def html_encode( str ) ::CGI.escapeHTML( str.to_s ) end
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
@see Arachni::Element::Link.from_parser
# File lib/arachni/utilities.rb, line 68 def links_from_parser( *args ) Link.from_parser(*args ) end
@see Arachni::Element::Link.from_response
# File lib/arachni/utilities.rb, line 63 def links_from_response( *args ) Link.from_response( *args ) end
@see URI.normalize
# File lib/arachni/utilities.rb, line 157 def normalize_url( url ) URI.normalize( url ) end
@see Arachni::Page.from_response
# File lib/arachni/utilities.rb, line 103 def page_from_response( *args ) Page.from_response( *args ) end
# File lib/arachni/utilities.rb, line 108 def page_from_url( *args, &block ) Page.from_url( *args, &block ) end
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
@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
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
@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
@return [String] random HEX (SHA2) string
# File lib/arachni/utilities.rb, line 33 def random_seed @@random_seed ||= generate_token end
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
# 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
# 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
@see Arachni::HTTP::Request.parse_body
# File lib/arachni/utilities.rb, line 58 def request_parse_body( *args ) HTTP::Request.parse_body( *args ) end
@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
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
@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
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
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
@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
@see URI.encode
# File lib/arachni/utilities.rb, line 138 def uri_decode( url ) URI.decode( url ) end
@see URI.encode
# File lib/arachni/utilities.rb, line 133 def uri_encode( *args ) URI.encode( *args ) end
@see URI.parse
# File lib/arachni/utilities.rb, line 128 def uri_parse( url ) URI.parse( url ) end
# File lib/arachni/utilities.rb, line 147 def uri_parse_query( url ) URI.parse_query( url ) end
@return [URI::Parser] cached URI
parser
# File lib/arachni/utilities.rb, line 123 def uri_parser URI.parser end
# File lib/arachni/utilities.rb, line 142 def uri_rewrite( *args ) URI.rewrite( *args ) end