Class: Arachni::Element::Form
- Includes:
- Capabilities::Refreshable
- Defined in:
- lib/arachni/element/form.rb
Constant Summary collapse
- ORIGINAL_VALUES =
'__original_values__'- SAMPLE_VALUES =
'__sample_values__'
Constants included from Capabilities::Auditable
Capabilities::Auditable::OPTIONS
Constants included from Capabilities::Auditable::RDiff
Capabilities::Auditable::RDiff::RDIFF_OPTIONS
Constants included from Capabilities::Auditable::Taint
Capabilities::Auditable::Taint::TAINT_OPTIONS
Constants included from Capabilities::Mutable
Capabilities::Mutable::MUTATION_OPTIONS
Instance Attribute Summary collapse
-
#nonce_name ⇒ String
The name of the input name that holds the nonce.
Attributes inherited from Base
Attributes included from Capabilities::Auditable
Attributes included from Capabilities::Mutable
Class Method Summary collapse
-
.decode(str) ⇒ String
Decodes a String encoded for an HTTP request’s body.
-
.encode(str) ⇒ String
Encodes a String‘s reserved characters in order to prepare it to be included in a request body.
-
.from_document(url, document) ⇒ Array<Form>
Returns an array of forms from an HTML document.
-
.from_response(response) ⇒ Array<Form>
Returns an array of forms by parsing the body of an HTTP response.
-
.parse_request_body(body) ⇒ Hash
Parses an HTTP request body generated by submitting a form.
Instance Method Summary collapse
- #audit_id(injection_str = '', opts = {}) ⇒ Object
- #decode(str) ⇒ Object
- #dup ⇒ Object
- #encode(str) ⇒ Object
-
#field_type_for(name) ⇒ String
Retrieves a field type for the given field
name. -
#has_nonce? ⇒ Bool
trueif the form contains a nonce,falseotherwise. -
#id ⇒ String
Unique form ID.
- #id_from(type = :auditable) ⇒ Object
-
#initialize(url, raw = {}) ⇒ Form
constructor
Creates a new Form element from a URL and auditable data.
-
#mutations(seed, opts = {}) ⇒ Array<Form>
Overrides Mutable#mutations adding support for mutations with: * sample values (filled by Module::KeyFiller.fill) * original values * password fields requiring identical values (in order to pass server-side validation).
-
#name ⇒ String?
Name of the form if it has one.
-
#original? ⇒ Bool
trueif the element has not been mutated,falseotherwise. - #parse_request_body(body) ⇒ Object
-
#requires_password? ⇒ Bool
Checks whether or not the form contains 1 or more password fields.
-
#sample? ⇒ Bool
trueif the element has been populated with sample (Module::KeyFiller) values,falseotherwise. -
#simple ⇒ Hash
A simple representation of self including attributes and auditables.
-
#type ⇒ String
‘form’.
Methods included from Capabilities::Refreshable
Methods inherited from Base
#action, #action=, #method, #method=, #url, #url=
Methods included from Utilities
#cookie_encode, #cookies_from_document, #cookies_from_file, #cookies_from_response, #exception_jail, #exclude_path?, #extract_domain, #form_decode, #form_encode, #form_parse_request_body, #forms_from_document, #forms_from_response, #get_path, #hash_keys_to_str, #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?, #remove_constants, #seed, #skip_path?, #to_absolute, #uri_decode, #uri_encode, #uri_parse, #uri_parser, #url_sanitize
Methods included from Capabilities::Auditable
#==, #[], #[]=, #audit, #auditable, #auditable=, #changes, #debug?, #has_inputs?, #hash, #http, #info, #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_path?, #status_string, #submit, #update
Methods included from Capabilities::Auditable::RDiff
Methods included from Capabilities::Auditable::Timeout
add_timeout_audit_block, add_timeout_candidate, #call_on_timing_blocks, call_on_timing_blocks, current_timeout_audit_operations_cnt, included, on_timing_attacks, #responsive?, running_timeout_attacks?, #timeout_analysis, timeout_analysis_phase_2, timeout_audit_blocks, timeout_audit_operations_cnt, timeout_audit_run, timeout_loaded_modules
Methods included from Capabilities::Auditable::Taint
Methods included from Capabilities::Mutable
#altered_value, #altered_value=, #immutables, #mutated?, #mutations_for, #permutations, #permutations_for
Constructor Details
#initialize(url, raw = {}) ⇒ Form
Creates a new Form element from a URL and auditable data.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/arachni/element/form.rb', line 60 def initialize( url, raw = {} ) super( url, raw ) was_opts_hash = false begin self.action = @raw['action'] || @raw[:action] || @raw['attrs']['action'] was_opts_hash = true rescue self.action = self.url end begin self.method = @raw['method'] || @raw[:method] || @raw['attrs']['method'] was_opts_hash = true rescue self.method = 'get' end if !was_opts_hash && (@raw.keys & [:inputs, 'inputs', 'auditable']).empty? self.auditable = @raw else self.auditable = @raw[:inputs] || @raw['inputs'] || simple['auditable'] end self.auditable ||= {} @orig = self.auditable.dup @orig.freeze end |
Instance Attribute Details
#nonce_name ⇒ String
Returns the name of the input name that holds the nonce.
31 32 33 |
# File 'lib/arachni/element/form.rb', line 31 def nonce_name @nonce_name end |
Class Method Details
.decode(str) ⇒ String
Decodes a String encoded for an HTTP request’s body.
1218 1219 1220 |
# File 'lib/arachni/element/form.rb', line 1218 def self.decode( str ) URI.decode( str.to_s.recode.gsub( '+', ' ' ) ) end |
.encode(str) ⇒ String
Encodes a String‘s reserved characters in order to prepare it to be included in a request body.
#example
p Form.encode "+% ;&\\=\0"
#=> "%2B%25+%3B%26%5C%3D%00"
1199 1200 1201 |
# File 'lib/arachni/element/form.rb', line 1199 def self.encode( str ) ::URI.encode( ::URI.encode( str, '+%' ).recode.gsub( ' ', '+' ), ";&\\=\0" ) end |
.from_document(url, document) ⇒ Array<Form>
Returns an array of forms from an HTML document.
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 |
# File 'lib/arachni/element/form.rb', line 1143 def self.from_document( url, document ) document = Nokogiri::HTML( document.to_s ) if !document.is_a?( Nokogiri::HTML::Document ) base_url = url begin base_url = document.search( '//base[@href]' )[0]['href'] rescue base_url = url end document.search( '//form' ).map do |form| next if !(form = form_from_element( base_url, form )) form.url = url form end.compact end |
.from_response(response) ⇒ Array<Form>
Returns an array of forms by parsing the body of an HTTP response.
1053 1054 1055 |
# File 'lib/arachni/element/form.rb', line 1053 def self.from_response( response ) from_document( response.effective_url, response.body ) end |
.parse_request_body(body) ⇒ Hash
Parses an HTTP request body generated by submitting a form.
1175 1176 1177 1178 1179 1180 1181 |
# File 'lib/arachni/element/form.rb', line 1175 def self.parse_request_body( body ) body.to_s.split( '&' ).inject( {} ) do |h, pair| name, value = pair.split( '=', 2 ) h[decode( name.to_s )] = decode( value ) h end end |
Instance Method Details
#audit_id(injection_str = '', opts = {}) ⇒ Object
356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/arachni/element/form.rb', line 356 def audit_id( injection_str = '', opts = {} ) str = if original? opts[:no_auditor] = true ORIGINAL_VALUES elsif sample? opts[:no_auditor] = true SAMPLE_VALUES else injection_str end super( str, opts ) end |
#decode(str) ⇒ Object
1222 1223 1224 |
# File 'lib/arachni/element/form.rb', line 1222 def decode( str ) self.class.decode( str ) end |
#dup ⇒ Object
1226 1227 1228 1229 1230 |
# File 'lib/arachni/element/form.rb', line 1226 def dup f = super f.nonce_name = nonce_name.dup if nonce_name f end |
#encode(str) ⇒ Object
1203 1204 1205 |
# File 'lib/arachni/element/form.rb', line 1203 def encode( str ) self.class.encode( str ) end |
#field_type_for(name) ⇒ String
Retrieves a field type for the given field name.
988 989 990 991 992 993 994 995 |
# File 'lib/arachni/element/form.rb', line 988 def field_type_for( name ) return if !@raw['auditable'] field = @raw['auditable'].select { |f| f['name'] == name }.first return if !field field['type'].to_s.downcase end |
#has_nonce? ⇒ Bool
Returns true if the form contains a nonce, false otherwise.
937 938 939 |
# File 'lib/arachni/element/form.rb', line 937 def has_nonce? !!nonce_name end |
#id ⇒ String
Returns unique form ID.
132 133 134 |
# File 'lib/arachni/element/form.rb', line 132 def id id_from :auditable end |
#id_from(type = :auditable) ⇒ Object
187 188 189 190 191 |
# File 'lib/arachni/element/form.rb', line 187 def id_from( type = :auditable ) query_vars = parse_url_vars( self.action ) "#{self.action.split( '?' ).first.to_s.split( ';' ).first}::" << "#{self.method}::#{query_vars.merge( self.send( type ) ).keys.compact.sort.to_s}" end |
#mutations(seed, opts = {}) ⇒ Array<Form>
Overrides Mutable#mutations adding support for mutations with:
-
sample values (filled by Module::KeyFiller.fill)
-
original values
-
password fields requiring identical values (in order to pass server-side validation)
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 |
# File 'lib/arachni/element/form.rb', line 861 def mutations( seed, opts = {} ) opts = MUTATION_OPTIONS.merge( opts ) var_combo = super( seed, opts ) if !opts[:skip_orig] # this is the original hash, in case the default values # are valid and present us with new attack vectors elem = self.dup elem.altered = ORIGINAL_VALUES var_combo << elem elem = self.dup elem.auditable = Arachni::Module::KeyFiller.fill( auditable.dup ) elem.altered = SAMPLE_VALUES var_combo << elem end # if there are two password type fields in the form there's a good # chance that it's a 'please retype your password' thing so make sure # that we have a variation which has identical password values password_fields = auditable.keys. select { |input| field_type_for( input ) == 'password' } # mirror the password fields if password_fields.size == 2 var_combo.each do |f| f[password_fields[0]] = f[password_fields[1]] end.compact end var_combo.uniq end |
#name ⇒ String?
Returns name of the form if it has one.
109 110 111 |
# File 'lib/arachni/element/form.rb', line 109 def name @raw['attrs']['name'] if @raw['attrs'].is_a?( Hash ) end |
#original? ⇒ Bool
Returns true if the element has not been mutated, false otherwise.
289 290 291 |
# File 'lib/arachni/element/form.rb', line 289 def original? self.altered == ORIGINAL_VALUES end |
#parse_request_body(body) ⇒ Object
1183 1184 1185 |
# File 'lib/arachni/element/form.rb', line 1183 def parse_request_body( body ) self.class.parse_request_body( body ) end |
#requires_password? ⇒ Bool
Checks whether or not the form contains 1 or more password fields.
920 921 922 923 |
# File 'lib/arachni/element/form.rb', line 920 def requires_password? return if !self.raw.is_a?( Hash ) || !self.raw['input'].is_a?( Array ) self.raw['input'].select { |i| i['type'] == 'password' }.any? end |
#sample? ⇒ Bool
Returns true if the element has been populated with sample (Module::KeyFiller) values, false otherwise.
352 353 354 |
# File 'lib/arachni/element/form.rb', line 352 def sample? self.altered == SAMPLE_VALUES end |
#simple ⇒ Hash
Returns a simple representation of self including attributes and auditables.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/arachni/element/form.rb', line 203 def simple form = {} form['auditable'] = {} if @raw['auditable'] && !@raw['auditable'].empty? @raw['auditable'].each do |item| next if !item['name'] form['auditable'][item['name']] = item['value'] end end if @raw['attrs'] form['attrs'] = @raw['attrs'] else form['attrs'] = { 'method' => @method, 'action' => @action } end if form['auditable'].empty? && @auditable && !@auditable.empty? form['auditable'] = @auditable end form.dup end |
#type ⇒ String
Returns ‘form’.
998 999 1000 |
# File 'lib/arachni/element/form.rb', line 998 def type Arachni::Element::FORM end |