class Arachni::Element::NestedCookie

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

Constants

DEFAULT

Default cookie values

Attributes

data[R]

Private Class Methods

decode( str ) click to toggle source

Decodes a {String} encoded for the ‘Cookie` header field.

@param [String] str

@return [String]

# File lib/arachni/element/nested_cookie.rb, line 351
def decode( str )
    Cookie.decode( str )
end
encode( str ) click to toggle source

Encodes a {String}‘s reserved characters in order to prepare it for the `Cookie` header field.

@param [String] str

@return [String]

# File lib/arachni/element/nested_cookie.rb, line 342
def encode( str )
    Cookie.encode( str )
end
from_cookies( cookies ) click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 311
def from_cookies( cookies )
    [cookies].flatten.compact.map do |cookie|
        next if !cookie.value.include?( '=' )

        inputs = parse_inputs( cookie.value )
        next if inputs.empty?

        new({
            url:    cookie.url,
            action: cookie.action,
            method: cookie.method,
            inputs: inputs,
            source: cookie.source
        }.merge( cookie.data ))
    end.compact
end
from_file( url, filepath ) click to toggle source

Parses a Netscape Cookie-jar into an Array of {Cookie}.

@param [String] url

{HTTP::Request} URL.

@param [String] filepath

Netscape HTTP cookiejar file.

@return [Array<NestedCookie>]

@see curl.haxx.se/rfc/cookie_spec.html

# File lib/arachni/element/nested_cookie.rb, line 239
def from_file( url, filepath )
    from_cookies( Cookie.from_file( url, filepath ) )
end
from_headers( url, headers ) click to toggle source

Extracts cookies from the ‘Set-Cookie` HTTP response header field.

@param [String] url

{HTTP::Request} URL.

@param [Hash] headers

@return [Array<NestedCookie>]

@see .forms_set_cookie

# File lib/arachni/element/nested_cookie.rb, line 281
def from_headers( url, headers )
    from_cookies( Cookie.from_headers( url, headers ) )
end
from_parser( parser ) click to toggle source

Extracts cookies from a document based on ‘Set-Cookie` `http-equiv` meta tags.

@param [Arachni::Parser] parser

@return [Array<NestedCookie>]

@see .parse_set_cookie

# File lib/arachni/element/nested_cookie.rb, line 264
def from_parser( parser )
    from_cookies( Cookie.from_parser( parser ) )
end
from_response( response ) click to toggle source

Extracts cookies from an HTTP {Arachni::HTTP::Response response}.

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

@return [Array<NestedCookie>]

@see .from_parser @see .from_headers

# File lib/arachni/element/nested_cookie.rb, line 251
def from_response( response )
    from_parser( Arachni::Parser.new( response ) ) +
        from_headers( response.url, response.headers )
end
from_rpc_data( data ) click to toggle source
Calls superclass method Arachni::Element::Base::from_rpc_data
# File lib/arachni/element/nested_cookie.rb, line 214
def from_rpc_data( data )
    if data['initialization_options']['expires']
        data['initialization_options']['expires'] =
            Time.parse( data['initialization_options']['expires'] )
    end

    if data['data']['expires']
        data['data']['expires'] = Time.parse( data['data']['expires'] )
    end

    data['data'] = data['data'].my_symbolize_keys(false)

    super data
end
from_string( url, string ) click to toggle source

Parses a string formatted for the ‘Cookie` HTTP request header field into cookie elements.

@param [String] url

{HTTP::Request} URL.

@param [Hash] string

`Cookie` string.

@return [Array<NestedCookie>]

# File lib/arachni/element/nested_cookie.rb, line 307
def from_string( url, string )
    from_cookies( Cookie.from_string( url, string ) )
end
in_html?( html ) click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 268
def in_html?( html )
    html =~ /set-cookie.*&/i
end
new( options ) click to toggle source

@param [Hash] options

For options see {DEFAULT}, with the following extras:

@option options [String] :url

URL of the page which created the cookie -- **required**.

@option options [String] :action

URL of the page to submit the cookie -- defaults to `:url`.

@option options [Hash] :inputs

Allows you to pass cookie data as a `name => value` pair instead of the
more complex {DEFAULT} structure.
# File lib/arachni/element/nested_cookie.rb, line 44
def initialize( options )
    @data = {}
    super( options )

    if options[:name] && options[:value]
        options[:name]  = options[:name].to_s.recode
        options[:value] = options[:value].to_s.recode

        self.inputs = self.class.parse_inputs( options[:value] )
        @data.merge!( options )
    else
        self.inputs = (options[:inputs] || {}).dup
    end

    @data.merge!( DEFAULT.merge( @data ) )
    @data[:value] = decode( @data[:value].to_s ) rescue @data[:value].to_s

    parsed_uri = uri_parse( action )
    if !@data[:path]
        path = parsed_uri.path
        path = !path.empty? ? path : '/'
        @data[:path] = path
    end

    if @data[:expires] && !@data[:expires].is_a?( Time )
        @data[:expires] = Time.parse( @data[:expires].to_s ) rescue nil
    end

    @data[:domain] ||= parsed_uri.host

    @default_inputs = self.inputs.dup.freeze
end
parse_inputs( value ) click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 328
def parse_inputs( value )
    value.to_s.split( '&' ).inject( {} ) do |h, pair|
        name, value = pair.split( '=', 2 )
        h[decode( name.to_s )] = decode( value.to_s )
        h
    end
end
type() click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 210
def type
    :nested_cookie
end

Private Instance Methods

decode( str ) click to toggle source

@see .decode

# File lib/arachni/element/nested_cookie.rb, line 188
def decode( str )
    self.class.decode( str )
end
encode( *args ) click to toggle source

@see .encode

# File lib/arachni/element/nested_cookie.rb, line 183
def encode( *args )
    self.class.encode( *args )
end
expired?( time = Time.now ) click to toggle source

Indicates whether or not the cookie has expired.

@param [Time] time

To compare against.

@return [Boolean]

# File lib/arachni/element/nested_cookie.rb, line 113
def expired?( time = Time.now )
    expires_at != nil && time > expires_at
end
expires_at() click to toggle source

@return [Time, NilClass]

Expiration `Time` of the cookie or `nil` if it doesn't have one
(i.e. is a session cookie).
# File lib/arachni/element/nested_cookie.rb, line 103
def expires_at
    @data[:expires]
end
http_only?() click to toggle source

Indicates whether the cookie is safe from modification from client-side code.

@return [Bool]

# File lib/arachni/element/nested_cookie.rb, line 87
def http_only?
    @data[:httponly] == true
end
http_request( opts = {}, &block ) click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 359
def http_request( opts = {}, &block )
    opts[:cookies] = opts.delete( :parameters )

    self.method == :get ?
        http.get( self.action, opts, &block ) :
        http.post( self.action, opts, &block )
end
method_missing( sym, *args, &block ) click to toggle source

Uses the method name as a key to cookie attributes in {DEFAULT}.

Calls superclass method
# File lib/arachni/element/nested_cookie.rb, line 125
def method_missing( sym, *args, &block )
    return @data[sym] if @data.include? sym
    super( sym, *args, &block )
end
respond_to?( *args ) click to toggle source

Used by {#method_missing} to determine if it should process the call.

@return [Bool]

Calls superclass method
# File lib/arachni/element/nested_cookie.rb, line 134
def respond_to?( *args )
    (@data && @data.include?( args.first )) || super
end
secure?() click to toggle source

Indicates whether the cookie must be only sent over an encrypted channel.

@return [Bool]

# File lib/arachni/element/nested_cookie.rb, line 80
def secure?
    @data[:secure] == true
end
session?() click to toggle source

Indicates whether the cookie is to be discarded at the end of the session.

Doesn’t play a role during the scan but it can provide useful info to checks and such.

@return [Bool]

# File lib/arachni/element/nested_cookie.rb, line 96
def session?
    @data[:expires].nil?
end
simple() click to toggle source

@return [Hash]

Simple representation of the cookie as a hash -- with the cookie name as
`key` and the cookie value as `value`.
# File lib/arachni/element/nested_cookie.rb, line 120
def simple
    self.inputs.dup
end
to_rpc_data() click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 192
def to_rpc_data
    h = super

    if h['initialization_options']['expires']
        h['initialization_options']['expires'] =
            h['initialization_options']['expires'].to_s
    end

    h['data'] = h['data'].my_stringify_keys(false)
    if h['data']['expires']
        h['data']['expires'] = h['data']['expires'].to_s
    end

    h
end
to_s() click to toggle source

@return [String]

To be used in a `Cookie` HTTP request header.
# File lib/arachni/element/nested_cookie.rb, line 144
def to_s
    # Only do encoding if we're dealing with updated inputs, otherwise pass
    # along the raw data as set in order to deal with server-side decoding
    # quirks.
    if updated? || !(raw_name || raw_value )
        "#{encode( name )}=#{value}"
    else
        "#{raw_name}=#{raw_value}"
    end
end
value() click to toggle source
# File lib/arachni/element/nested_cookie.rb, line 138
def value
    self.inputs.map { |n, v| "#{encode( n )}=#{encode( v )}" }.join( '&' )
end