spec/support/shared/element/capabilities/mutable.rb in arachni-1.0.6 vs spec/support/shared/element/capabilities/mutable.rb in arachni-1.1

- old
+ new

@@ -6,20 +6,24 @@ supports_nulls: true }.merge( options ) end let(:inputs) do + return opts[:inputs] if opts[:inputs] + if opts[:single_input] { 'input1' => 'value1' } else { 'input1' => 'value1', 'input2' => 'value2' } end end + let(:valid_key) { inputs.keys.first.to_s } + let(:seed) { 'my_seed' } let(:mutable) do if defined? super super() else @@ -92,11 +96,11 @@ end end describe '#immutables' do it 'skips contained inputs' do - input = mutable.inputs.first.first + input = mutable.inputs.keys.first mutable.immutables << input mutable.mutations( seed ). reject { |e| e.affected_input_name != input }. should be_empty @@ -131,172 +135,259 @@ checked.should be_true end context 'with no options' do it 'returns all combinations' do - # We set the skip_original option because it only applies to forms. mutable.mutations( seed, skip_original: true ).size.should == - (opts[:single_input] ? 4 : 8) / (opts[:supports_nulls] ? 1 : 2) + (inputs.size * 4) / (opts[:supports_nulls] ? 1 : 2) end end context 'with option' do - describe :respect_method, + describe :parameter_values do + describe true do + it 'injects the payload into parameter values' do + mutable.mutations( seed, parameter_values: true ). + find { |m| m.affected_input_value.include? seed }. + should be_true + end + end + describe false do + it 'does not inject the payload into parameter values' do + mutable.mutations( seed, parameter_values: false ). + find { |m| m.affected_input_value.include? seed }. + should be_false + end + end + describe 'nil' do + it 'injects the payload into parameter names' do + mutable.mutations( seed ). + find { |m| m.affected_input_value.include? seed }. + should be_true + end + end + + describe "#{Arachni::OptionGroups::Audit}#parameter_values" do + it 'serves as the default value of :parameter_values' do + Arachni::Options.audit.parameter_values = true + mutable.mutations( seed ). + find { |m| m.affected_input_value.include? seed }. + should be_true + + Arachni::Options.audit.parameter_values = false + mutable.mutations( seed ). + find { |m| m.affected_input_value.include? seed }. + should be_false + end + end + end + + describe :with_extra_parameter, if: !described_class.ancestors.include?( Arachni::Element::Capabilities::Auditable::DOM - ) do + ) && described_class != Arachni::Element::LinkTemplate && + described_class != Arachni::Element::XML do + let(:extra_name) { described_class::EXTRA_NAME } + describe true do - it 'does not fuzz methods' do - respect_method = mutable.mutations( seed, respect_method: true ) - respect_method.map{ |m| m.method }.uniq.should eq [mutable.method] + it 'injects the payload into an extra parameter' do + mutable.mutations( seed, with_extra_parameter: true ). + find { |m| m[extra_name].to_s.include? seed }.should be_true end end describe false do + it 'does not inject the payload into an extra parameter' do + mutable.mutations( seed, with_extra_parameter: false ). + find { |m| m[extra_name].to_s.include? seed }.should be_false + end + end + describe 'nil' do + it 'does not inject the payload into an extra parameter' do + mutable.mutations( seed ). + find { |m| m[extra_name].to_s.include? seed }.should be_false + end + end + + describe "#{Arachni::OptionGroups::Audit}#with_extra_parameter" do + it 'serves as the default value of :with_extra_parameter' do + Arachni::Options.audit.with_extra_parameter = true + mutable.mutations( seed ). + find { |m| m[extra_name].to_s.include? seed }.should be_true + + Arachni::Options.audit.with_extra_parameter = false + mutable.mutations( seed ). + find { |m| m[extra_name].to_s.include? seed }.should be_false + end + end + end + + describe :with_both_http_methods, + if: !described_class.ancestors.include?( + Arachni::Element::Capabilities::Auditable::DOM + ) && described_class != Arachni::Element::JSON && + described_class != Arachni::Element::XML do + + describe false do + it 'does not fuzz methods' do + mutable.mutations( seed, with_both_http_methods: false ). + map(&:method).uniq.should eq [mutable.method] + end + end + describe true do it 'fuzzes methods' do - no_respect_method = mutable.mutations( seed, respect_method: false ) - no_respect_method.map{ |m| m.method }.uniq.should eq [:get, :post] + mutable.mutations( seed, with_both_http_methods: true ). + map(&:method).uniq.should eq [:get, :post] end end describe 'nil' do it 'does not fuzz methods' do - respect_method = mutable.mutations( seed ) - respect_method.map{ |m| m.method }.uniq.should == [mutable.method] + mutable.mutations( seed ).map(&:method).uniq. + should == [mutable.method] end end + + describe "#{Arachni::OptionGroups::Audit}#with_both_http_methods" do + it 'serves as the default value of :with_both_http_methods' do + Arachni::Options.audit.with_both_http_methods = true + mutable.mutations( seed ).map(&:method).uniq. + should eq [:get, :post] + + Arachni::Options.audit.with_both_http_methods = false + mutable.mutations( seed ).map(&:method).uniq. + should == [mutable.method] + end + end end - describe 'Options.audit.with_both_http_methods', + + describe :parameter_names, if: !described_class.ancestors.include?( Arachni::Element::Capabilities::Auditable::DOM - ) do + ) && described_class != Arachni::Element::LinkTemplate && + described_class != Arachni::Element::XML do - it 'serves as the default value of :respect_method' do - Arachni::Options.audit.with_both_http_methods = true - no_respect_method = mutable.mutations( seed ) + describe true do + it 'uses the seed as a parameter name' do + mutable.mutations( seed, parameter_names: true ). + find { |m| m.inputs.keys.include? seed }. + should be_true + end + end + describe false do + it 'does not use the seed as a parameter name' do + mutable.class.any_instance. + stub(:valid_input_name_data?) { |name| name != seed } - no_respect_method.map{ |m| m.method }.uniq.should eq [:get, :post] + mutable.mutations( seed, parameter_names: false ). + find { |m| m.inputs.keys.include? seed }. + should be_false + end + end + describe 'nil' do + it 'does not use the seed as a parameter name' do + described_class.any_instance. + stub(:valid_input_name_data?) { |name| name != seed } - Arachni::Options.audit.with_both_http_methods = false - respect_method = mutable.mutations( seed ) + mutable.mutations( seed ). + find { |m| m.inputs.keys.include? seed }. + should be_false + end + end - respect_method.map{ |m| m.method }.uniq.should == [mutable.method] + describe "#{Arachni::OptionGroups::Audit}#parameter_names" do + it 'serves as the default value of :parameter_names' do + Arachni::Options.audit.parameter_names = true + mutable.mutations( seed ). + find { |m| m.inputs.keys.include? seed }. + should be_true + + Arachni::Options.audit.parameter_names = false + mutable.mutations( seed ). + find { |m| m.inputs.keys.include? seed }. + should be_false + end end end describe :skip do it 'skips mutation of parameters with these names' do mutable.mutations( seed, skip: [ 'input_one' ] ) end end - describe :param_flip, - if: !described_class.ancestors.include?( - Arachni::Element::Capabilities::Auditable::DOM - ) && described_class != Arachni::Element::LinkTemplate do - - it 'uses the seed as a param name' do - mutable.mutations( - seed, - format: [Arachni::Element::Capabilities::Mutable::Format::STRAIGHT], - param_flip: true, - skip_original: true - ).select { |m| m.inputs.include? seed }.size.should > 0 - end - end - describe :format do describe 'Format::STRAIGHT' do it 'injects the seed as is' do m = mutable.mutations( seed, format: [Arachni::Element::Capabilities::Mutable::Format::STRAIGHT], skip_original: true ).first - m.inputs[m.affected_input_name].should == seed + m[m.affected_input_name].should == seed end end describe 'Format::APPEND' do it 'appends the seed to the current value' do m = mutable.mutations( seed, format: [Arachni::Element::Capabilities::Mutable::Format::APPEND], skip_original: true ).first - m.inputs[m.affected_input_name].should == inputs[m.affected_input_name] + seed + m[m.affected_input_name].should == inputs[m.affected_input_name] + seed end end describe 'Format::NULL' do it 'terminates the string with a null character', if: described_class != Arachni::Element::Header && described_class.is_a?( Arachni::Element::Capabilities::Auditable::DOM ) do m = mutable.mutations( seed, format: [Arachni::Element::Capabilities::Mutable::Format::NULL], skip_original: true ).first - m.inputs[m.affected_input_name].should == seed + "\0" + m[m.affected_input_name].should == seed + "\0" end end describe 'Format::SEMICOLON' do it 'prepends the seed with a semicolon' do m = mutable.mutations( seed, format: [Arachni::Element::Capabilities::Mutable::Format::SEMICOLON], skip_original: true ).first - m.inputs[m.affected_input_name].should == ';' + seed + m[m.affected_input_name].should == ';' + seed end end describe 'Format::APPEND | Format::NULL' do it 'appends the seed and terminate the string with a null character', if: described_class != Arachni::Element::Header && described_class.is_a?( Arachni::Element::Capabilities::Auditable::DOM ) do format = [Arachni::Element::Capabilities::Mutable::Format::APPEND | Arachni::Element::Capabilities::Mutable::Format::NULL] m = mutable.mutations( seed, format: format, skip_original: true ).first - m.inputs[m.affected_input_name].should == inputs[m.affected_input_name] + seed + "\0" + m[m.affected_input_name].should == inputs[m.affected_input_name] + seed + "\0" end end end end context 'when the payload is not supported' do it 'returns an empty array' do - described_class.any_instance.stub(:valid_input_data?) { |i| i != '1' } + mutable + mutable.class.any_instance.stub(:valid_input_data?) { |i| i != '1' } mutable.mutations('1', skip_original: true ).size.should == 0 end context 'as a value' do it 'skips the mutation' do mutable.mutations(seed). select { |m| m.affected_input_value.include? seed }. size.should > 0 - described_class.any_instance. + mutable.class.any_instance. stub(:valid_input_value_data?) { |value| value.include? seed } mutable.mutations('1'). select { |m| m.affected_input_value.include? seed }. size.should == 0 end end - - context 'as a name', - if: !described_class.ancestors.include?( - Arachni::Element::Capabilities::Auditable::DOM - ) && described_class != Arachni::Element::LinkTemplate do - - it 'skips the mutation' do - seed = 'payload' - - mutable.mutations( seed, param_flip: true ). - select { |m| m.inputs.keys.include? seed }. - size.should > 0 - - described_class.any_instance. - stub(:valid_input_name_data?) { |name| name != seed } - - mutable.mutations( seed, param_flip: true ). - select { |m| m.inputs.keys.include? seed }. - size.should == 0 - end - end end end describe '#affected_input_name' do it 'returns the name of the mutated input' do @@ -336,9 +427,13 @@ it 'preserves #affected_input_name' do dupped.affected_input_name.should == mutation.affected_input_name end it 'preserves #format' do dupped.format.should == mutation.format + end + it 'preserves #immutables' do + mutation.immutables << 'stuff' + dupped.immutables.should == mutation.immutables end end describe '#to_h' do it 'returns a hash representation of self' do