Class: Arachni::Element::Cookie
- Defined in:
- lib/arachni/element/cookie.rb
Overview
Represents a Cookie object and provides helper class methods for parsing, encoding, etc.
Constant Summary collapse
- DEFAULT =
Default cookie values
{ "name" => nil, "value" => nil, "version" => 0, "port" => nil, "discard" => nil, "comment_url" => nil, "expires" => nil, "max_age" => nil, "comment" => nil, "secure" => nil, "path" => nil, "domain" => nil, "httponly" => false }
Constants included from Arachni::Element::Capabilities::Auditable
Arachni::Element::Capabilities::Auditable::OPTIONS
Constants included from Arachni::Element::Capabilities::Auditable::RDiff
Arachni::Element::Capabilities::Auditable::RDiff::RDIFF_OPTIONS
Constants included from Arachni::Element::Capabilities::Auditable::Taint
Arachni::Element::Capabilities::Auditable::Taint::REMARK, Arachni::Element::Capabilities::Auditable::Taint::TAINT_OPTIONS
Constants included from Arachni::Element::Capabilities::Mutable
Arachni::Element::Capabilities::Mutable::MUTATION_OPTIONS
Instance Attribute Summary
Attributes inherited from Base
Attributes included from Arachni::Element::Capabilities::Auditable
Attributes included from Arachni::Element::Capabilities::Mutable
Class Method Summary collapse
-
.decode(str) ⇒ String
Decodes a String encoded for the ‘Cookie` header field.
-
.encode(str, type = :value) ⇒ String
Encodes a String‘s reserved characters in order to prepare it for the `Cookie` header field.
-
.expires_to_time(expires) ⇒ Time
Converts a cookie’s expiration date to a Ruby ‘Time` object.
-
.from_document(url, document) ⇒ Array<Cookie>
Extracts cookies from a document based on ‘Set-Cookie` `http-equiv` meta tags.
-
.from_file(url, filepath) ⇒ Array<Cookie>
Parses a Netscape Cookie-jar into an Array of Cookie.
-
.from_headers(url, headers) ⇒ Array<Cookie>
Extracts cookies from the ‘Set-Cookie` HTTP response header field.
-
.from_response(response) ⇒ Array<Cookie>
Extracts cookies from an HTTP response.
-
.from_set_cookie(url, str) ⇒ Array<Cookie>
Parses the ‘Set-Cookie` header value into cookie elements.
-
.from_string(url, string) ⇒ Array<Cookie>
Parses a string formatted for the ‘Cookie` HTTP request header field into cookie elements.
- .parse_set_cookie(*args) ⇒ Object
Instance Method Summary collapse
-
#audit(*args) ⇒ Object
Overrides Arachni::Element::Capabilities::Auditable#audit to enforce cookie exclusion settings from Options#exclude_cookies.
- #auditable=(inputs) ⇒ Object
- #decode(str) ⇒ Object
- #dup ⇒ Object
- #each_extensive_mutation ⇒ Object
-
#each_mutation(injection_str, opts = {}) {|elem| ... } ⇒ Object
Overrides Arachni::Element::Capabilities::Mutable#each_mutation to handle cookie-specific limitations and the Options#audit_cookies_extensively option.
- #encode(*args) ⇒ Object
-
#expired?(time = Time.now) ⇒ Boolean
Indicates whether or not the cookie has expired.
-
#expires_at ⇒ Time, NilClass
Expiration ‘Time` of the cookie or `nil` if it doesn’t have one (i.e. is a session cookie).
-
#http_only? ⇒ Bool
Indicates whether the cookie is safe from modification from client-side code.
-
#initialize(url, raw = {}) ⇒ Cookie
constructor
A new instance of Cookie.
-
#method_missing(sym, *args, &block) ⇒ Object
Uses the method name as a key to cookie attributes in DEFAULT.
-
#respond_to?(sym) ⇒ Bool
Used by #method_missing to determine if it should process the call.
-
#secure? ⇒ Bool
Indicates whether the cookie must be only sent over an encrypted channel.
-
#session? ⇒ Bool
Indicates whether the cookie is to be discarded at the end of the session.
-
#simple ⇒ Hash
Simple representation of the cookie as a hash – with the cookie name as ‘key` and the cookie value as `value`.
-
#to_s ⇒ String
To be used in a ‘Cookie` HTTP request header.
-
#type ⇒ String
Name of the current element, ‘cookie’ in this case.
Methods inherited from Base
#action, #action=, #id, #method, #method=, #platforms, #url, #url=
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 Arachni::Element::Capabilities::Auditable
#==, #[], #[]=, #audit_id, #auditable, #changes, #debug?, #has_inputs?, #hash, #http, #matches_skip_like_blocks?, #orphan?, #override_instance_scope, #override_instance_scope?, #print_bad, #print_debug, #print_debug_backtrace, #print_error, #print_error_backtrace, #print_info, #print_line, #print_ok, #print_status, #provisioned_issue_id, #remove_auditor, #reset, reset, reset_instance_scope, #reset_scope_override, restrict_to_elements, #scope_audit_id, #skip?, skip_like, #status_string, #submit, #update, #use_anonymous_auditor
Methods included from Arachni::Element::Capabilities::Auditable::RDiff
Methods included from Arachni::Element::Capabilities::Auditable::Timeout
add_timeout_candidate, add_timeout_phase3_candidate, #call_on_timing_blocks, call_on_timing_blocks, current_timeout_audit_operations_cnt, deduplicate?, #deduplicate?, #disable_deduplication, disable_deduplication, enable_deduplication, #enable_deduplication, included, on_timing_attacks, reset, #responsive?, running_timeout_attacks?, #timeout_analysis, timeout_analysis_phase_2, timeout_analysis_phase_3, timeout_audit_operations_cnt, timeout_audit_run, timeout_candidates, timeout_loaded_modules
Methods included from Arachni::Element::Capabilities::Auditable::Taint
Methods included from Arachni::Element::Capabilities::Mutable
#altered_value, #altered_value=, #immutables, #mutated?, #mutations, #mutations_for, #original?, #permutations, #permutations_for, #switch_method
Constructor Details
#initialize(url, raw = {}) ⇒ Cookie
Returns a new instance of Cookie.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/arachni/element/cookie.rb', line 52 def initialize( url, raw = {} ) super( url, raw ) self.action = @url self.method = 'get' @raw ||= {} if @raw['name'] && @raw['value'] self.auditable = { @raw['name'].to_s.recode => @raw['value'].to_s.recode } else self.auditable = raw.dup end @raw = @raw.merge( DEFAULT.merge( @raw ) ) if @raw['value'] && !@raw['value'].empty? @raw['value'] = decode( @raw['value'].to_s ) end parsed_uri = uri_parse( @url ) if !@raw['path'] path = parsed_uri.path path = !path.empty? ? path : '/' @raw['path'] = path end @raw['domain'] ||= parsed_uri.host @raw['max_age'] = @raw['max_age'] if @raw['max_age'] @orig = self.auditable.dup @orig.freeze end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
Class Method Details
.decode(str) ⇒ String
Decodes a String encoded for the ‘Cookie` header field.
1016 1017 1018 |
# File 'lib/arachni/element/cookie.rb', line 1016 def self.decode( str ) URI.decode( str.to_s.recode.gsub( '+', ' ' ) ) end |
.encode(str, type = :value) ⇒ String
Encodes a String‘s reserved characters in order to prepare it for the `Cookie` header field.
994 995 996 997 998 999 |
# File 'lib/arachni/element/cookie.rb', line 994 def self.encode( str, type = :value ) reserved = "+;%\0" reserved << '=' if type == :name URI.encode( str, reserved ).recode.gsub( ' ', '+' ) end |
.expires_to_time(expires) ⇒ Time
Converts a cookie’s expiration date to a Ruby ‘Time` object.
514 515 516 517 |
# File 'lib/arachni/element/cookie.rb', line 514 def self.expires_to_time( expires ) return nil if expires == '0' (expires_to_i = expires.to_i) > 0 ? Time.at( expires_to_i ) : Time.parse( expires ) end |
.from_document(url, document) ⇒ Array<Cookie>
Extracts cookies from a document based on ‘Set-Cookie` `http-equiv` meta tags.
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 |
# File 'lib/arachni/element/cookie.rb', line 730 def self.from_document( url, document ) # optimizations in case there are no cookies in the doc, # avoid parsing unless absolutely necessary! if !document.is_a?( Nokogiri::HTML::Document ) # get get the head in order to check if it has an http-equiv for set-cookie head = document.to_s.match( /<head(.*)<\/head>/imx ) # if it does feed the head to the parser in order to extract the cookies return [] if !head || !head.to_s.downcase.substring?( 'set-cookie' ) document = Nokogiri::HTML( head.to_s ) end Arachni::Utilities.exception_jail { document.search( "//meta[@http-equiv]" ).map do |elem| next if elem['http-equiv'].downcase != 'set-cookie' ( url, elem['content'] ) end.flatten.compact } rescue [] end |
.from_file(url, filepath) ⇒ Array<Cookie>
Parses a Netscape Cookie-jar into an Array of Arachni::Element::Cookie.
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
# File 'lib/arachni/element/cookie.rb', line 474 def self.from_file( url, filepath ) File.open( filepath, 'r' ).map do |line| # skip empty lines next if (line = line.strip).empty? || line[0] == '#' c = {} c['domain'], foo, c['path'], c['secure'], c['expires'], c['name'], c['value'] = *line.split( "\t" ) # expiry date is optional so if we don't have one push everything back begin c['expires'] = expires_to_time( c['expires'] ) rescue c['value'] = c['name'].dup c['name'] = c['expires'].dup c['expires'] = nil end c['secure'] = (c['secure'] == 'TRUE') ? true : false new( url, c ) end.flatten.compact end |
.from_headers(url, headers) ⇒ Array<Cookie>
Extracts cookies from the ‘Set-Cookie` HTTP response header field.
797 798 799 800 801 802 803 804 805 |
# File 'lib/arachni/element/cookie.rb', line 797 def self.from_headers( url, headers ) set_strings = [] headers.each { |k, v| set_strings = [v].flatten if k.downcase == 'set-cookie' } return set_strings if set_strings.empty? exception_jail { set_strings.map { |c| ( url, c ) }.flatten } rescue [] end |
.from_response(response) ⇒ Array<Cookie>
Extracts cookies from an HTTP response.
638 639 640 641 |
# File 'lib/arachni/element/cookie.rb', line 638 def self.from_response( response ) ( from_document( response.effective_url, response.body ) | from_headers( response.effective_url, response.headers_hash ) ) end |
.from_set_cookie(url, str) ⇒ Array<Cookie>
Parses the ‘Set-Cookie` header value into cookie elements.
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 |
# File 'lib/arachni/element/cookie.rb', line 852 def self.( url, str ) WEBrick::Cookie.( str ).flatten.uniq.map do || = {} .instance_variables.each do |var| [var.to_s.gsub( /@/, '' )] = .instance_variable_get( var ) end ['expires'] = .expires ['path'] ||= '/' ['name'] = decode( .name ) ['value'] = decode( .value ) new( url.to_s, ) end.flatten.compact end |
.from_string(url, string) ⇒ Array<Cookie>
Parses a string formatted for the ‘Cookie` HTTP request header field into cookie elements.
975 976 977 978 979 980 |
# File 'lib/arachni/element/cookie.rb', line 975 def self.from_string( url, string ) string.split( ';' ).map do || k, v = *.split( '=', 2 ) new( url, decode( k.strip ) => decode( v.strip ) ) end.flatten.compact end |
.parse_set_cookie(*args) ⇒ Object
867 868 869 |
# File 'lib/arachni/element/cookie.rb', line 867 def self.( *args ) ( *args ) end |
Instance Method Details
#audit(*args) ⇒ Object
Overrides Arachni::Element::Capabilities::Auditable#audit to enforce cookie exclusion settings from Options#exclude_cookies.
91 92 93 94 95 96 97 |
# File 'lib/arachni/element/cookie.rb', line 91 def audit( *args ) if Arachni::Options..include?( name ) auditor.print_info "Skipping audit of '#{name}' cookie." return end super( *args ) end |
#auditable=(inputs) ⇒ Object
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/arachni/element/cookie.rb', line 249 def auditable=( inputs ) k = inputs.keys.first.to_s v = inputs.values.first.to_s raw = @raw.dup raw['name'] = k raw['value'] = v @raw = raw.freeze if k.to_s.empty? super( {} ) else super( { k => v } ) end end |
#decode(str) ⇒ Object
1020 1021 1022 |
# File 'lib/arachni/element/cookie.rb', line 1020 def decode( str ) self.class.decode( str ) end |
#dup ⇒ Object
228 229 230 |
# File 'lib/arachni/element/cookie.rb', line 228 def dup super.tap { |d| d.action = self.action } end |
#each_extensive_mutation ⇒ Object
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/arachni/element/cookie.rb', line 298 def each_extensive_mutation return if orphan? (auditor.page.links | auditor.page.forms).each do |e| next if e.auditable.empty? c = e.dup c.altered = "mutation for the '#{name}' cookie" c.auditor = auditor c.opts[:cookies] = self.auditable.dup c.auditable = Arachni::Support::KeyFiller.fill( c.auditable.dup ) yield c end end |
#each_mutation(injection_str, opts = {}) {|elem| ... } ⇒ Object
Overrides Arachni::Element::Capabilities::Mutable#each_mutation to handle cookie-specific limitations and the Options#audit_cookies_extensively option.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/arachni/element/cookie.rb', line 275 def each_mutation( injection_str, opts = {}, &block ) flip = opts.delete( :param_flip ) super( injection_str, opts ) do |elem| yield elem next if !Arachni::Options. elem.each_extensive_mutation( &block ) end return if !flip elem = self.dup # when under HPG mode element auditing is strictly regulated # and when we flip params we essentially create a new element # which won't be on the whitelist elem.override_instance_scope elem.altered = 'Parameter flip' elem.auditable = { injection_str => seed } yield elem if block_given? end |
#encode(*args) ⇒ Object
1001 1002 1003 |
# File 'lib/arachni/element/cookie.rb', line 1001 def encode( *args ) self.class.encode( *args ) end |
#expired?(time = Time.now) ⇒ Boolean
Indicates whether or not the cookie has expired.
205 206 207 |
# File 'lib/arachni/element/cookie.rb', line 205 def expired?( time = Time.now ) expires_at != nil && time > expires_at end |
#expires_at ⇒ Time, NilClass
Returns Expiration ‘Time` of the cookie or `nil` if it doesn’t have one (i.e. is a session cookie).
164 165 166 |
# File 'lib/arachni/element/cookie.rb', line 164 def expires_at expires end |
#http_only? ⇒ Bool
Indicates whether the cookie is safe from modification from client-side code.
127 128 129 |
# File 'lib/arachni/element/cookie.rb', line 127 def http_only? @raw['httponly'] == true end |
#respond_to?(sym) ⇒ Bool
Used by #method_missing to determine if it should process the call.
340 341 342 |
# File 'lib/arachni/element/cookie.rb', line 340 def respond_to?( sym ) (@raw && @raw.include?( sym.to_s )) || super( sym ) end |
#secure? ⇒ Bool
Indicates whether the cookie must be only sent over an encrypted channel.
111 112 113 |
# File 'lib/arachni/element/cookie.rb', line 111 def secure? @raw['secure'] == true end |
#session? ⇒ Bool
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 modules and such.
147 148 149 |
# File 'lib/arachni/element/cookie.rb', line 147 def session? @raw['expires'].nil? end |
#simple ⇒ Hash
Returns Simple representation of the cookie as a hash – with the cookie name as ‘key` and the cookie value as `value`.
218 219 220 |
# File 'lib/arachni/element/cookie.rb', line 218 def simple self.auditable.dup end |
#to_s ⇒ String
Returns To be used in a ‘Cookie` HTTP request header.
355 356 357 |
# File 'lib/arachni/element/cookie.rb', line 355 def to_s "#{encode( name, :name )}=#{encode( value )}" end |