diff --git a/.travis.yml b/.travis.yml index 9406d88..b079289 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: false language: ruby rvm: - - 2.0.0 + - 2.3.0 before_install: gem install bundler -v 1.12.5 diff --git a/API_Fuzzer.gemspec b/API_Fuzzer.gemspec index 59e9c74..d2a6b41 100644 --- a/API_Fuzzer.gemspec +++ b/API_Fuzzer.gemspec @@ -28,6 +28,8 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency 'http', '~> 2.0' + spec.add_dependency 'activesupport' + spec.add_dependency 'rails', '>= 4.2' spec.add_development_dependency "bundler", "~> 1.12" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "minitest", "~> 5.0" diff --git a/Gemfile b/Gemfile index fd4d19f..adb8966 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,7 @@ source 'https://rubygems.org' # Specify your gem's dependencies in API_Fuzzer.gemspec gem 'http' +gem 'builder' group :development do gem 'byebug' diff --git a/app/controllers/ping_controller.rb b/app/controllers/ping_controller.rb new file mode 100644 index 0000000..74651d0 --- /dev/null +++ b/app/controllers/ping_controller.rb @@ -0,0 +1,18 @@ +class PingController < ActionController::Base + def index + @scan = Scan.find(params[:id]) + @scan.vulnerabilities.create!( + status: 'HIGH', + class_type: 'Vulnerability', + description: 'Possible XXE vulnerability in #{@scan.url}', + value: body + ) if @scan + render json: { status: :ok } + end + + private + + def body + @scan.parameters.gsub(/\>\s*[a-zA-Z0-9]*\s*\<\//, '>&xxe;<') + end +end diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..a8f5066 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,3 @@ +API_Fuzzer::Engine.routes.draw do + get '/ping/:id' => 'ping#index' +end diff --git a/lib/API_Fuzzer.rb b/lib/API_Fuzzer.rb index 5c91cc3..8896dbf 100644 --- a/lib/API_Fuzzer.rb +++ b/lib/API_Fuzzer.rb @@ -5,6 +5,8 @@ require 'API_Fuzzer/sql_blind_check' require 'API_Fuzzer/xss_check' require 'API_Fuzzer/request' +require 'API_Fuzzer/engine' +require 'API_Fuzzer/xxe_check' module API_Fuzzer # Scans all the checks @@ -16,6 +18,7 @@ def self.scan(options = {}) vulnerabilities << API_Fuzzer::XssCheck.scan(options) vulnerabilities << API_Fuzzer::SqlCheck.scan(options) vulnerabilities << API_Fuzzer::SqlBlindCheck.scan(options) + API_Fuzzer::XxeCheck.scan(options) vulnerabilities.uniq.flatten end diff --git a/lib/API_Fuzzer/engine.rb b/lib/API_Fuzzer/engine.rb new file mode 100644 index 0000000..c47224d --- /dev/null +++ b/lib/API_Fuzzer/engine.rb @@ -0,0 +1,5 @@ +require 'rails' + +module API_Fuzzer + class Engine < ::Rails::Engine; end +end diff --git a/lib/API_Fuzzer/request.rb b/lib/API_Fuzzer/request.rb index fee1a60..cb42d09 100644 --- a/lib/API_Fuzzer/request.rb +++ b/lib/API_Fuzzer/request.rb @@ -10,6 +10,7 @@ def send_api_request(options = {}) @params = options.delete(:params) || {} @method = options.delete(:method) || :get @json = options.delete(:json) ? true : false + @body = options.delete(:body) ? true : false @request = set_cookies(options) send_request end @@ -56,6 +57,8 @@ def self.set_params { 'json' => @params } elsif method_get? { 'params' => @params } + elsif @body + { 'body' => @params } else { 'form' => @params } end diff --git a/lib/API_Fuzzer/xxe_check.rb b/lib/API_Fuzzer/xxe_check.rb new file mode 100644 index 0000000..c5079b4 --- /dev/null +++ b/lib/API_Fuzzer/xxe_check.rb @@ -0,0 +1,43 @@ +require 'API_Fuzzer/vulnerability' +require 'API_Fuzzer/error' +require 'API_Fuzzer/request' + +module API_Fuzzer + class XxeCheck + + def self.scan(options = {}) + @url = options[:url] || nil + @params = options[:params] + @scan_hash = options[:scan] + fuzz_xml_params + end + + private + + def self.fuzz_xml_params + return unless @params + body = params_serialize.gsub(/\>\s*[a-zA-Z0-9]*\s*\<\//, '>&xxe;<') + payload = <<-XXEPAYLOAD + + +]> + XXEPAYLOAD + payload << body + API_Fuzzer::Request.send_api_request( + url: @url, + params: payload, + body: true, + method: :post + ) + end + + def self.params_serialize + body = [] + @params.keys.each do |key, value| + body << "#{key}=#{value}" + end + body.join('&') + end + end +end