# frozen_string_literal: true # # ronin-exploits - A Ruby library for ronin-rb that provides exploitation and # payload crafting functionality. # # Copyright (c) 2007-2023 Hal Brodigan (postmodern.mod3 at gmail.com) # # ronin-exploits is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # ronin-exploits is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with ronin-exploits. If not, see . # require 'ronin/exploits/web' require 'ronin/exploits/mixins/has_payload' module Ronin module Exploits # # An {Exploit} class that represents a common web vulnerability # (ex: RFI, LFI, SQLI, XSS, etc). # # @since 1.0.0 # class WebVuln < Web include Mixins::HasPayload # # Gets or sets the HTTP request method to use. # # @param [:copy, :delete, :get, :head, :lock, :mkcol, :move, # :options, :patch, :post, :propfind, :proppatch, :put, # :trace, :unlock, nil] new_request_method # # @return [:copy, :delete, :get, :head, :lock, :mkcol, :move, # :options, :patch, :post, :propfind, :proppatch, :put, # :trace, :unlock] # The previously set HTTP request method or `:get`. # def self.request_method(new_request_method=nil) if new_request_method @request_method = new_request_method else @request_method ||= if superclass < WebVuln superclass.request_method else :get end end end # # Gets or sets the base path for the web vulnerability. # # @param [String, nil] new_base_path # The optional new base path value to set. # # @return [String] # The base path for the web vulnerability. # # @raise [NotImplementedError] # The exploit class did not set a base path. # # @example # base_path '/path/to/page.php' # def self.base_path(new_base_path=nil) if new_base_path @base_path = new_base_path else @base_path ||= if superclass < WebVuln superclass.base_path else raise(NotImplementedError,"#{self} did not set base_path") end end end # # Gets or sets the query param to exploit. # # @param [String, nil] new_query_param # The optional new query param value to set. # # @return [String, nil] # The query param for the web vulnerability. # # @example # query_param 'id' # def self.query_param(new_query_param=nil) if new_query_param @query_param = new_query_param else @query_param ||= if superclass < WebVuln superclass.query_param end end end # # Gets or sets the HTTP header name to exploit. # # @param [String, nil] new_header_name # The optional new header name value to set. # # @return [String, nil] # The header name for the web vulnerability. # # @example # header_name 'User-Agent' # def self.header_name(new_header_name=nil) if new_header_name @header_name = new_header_name else @header_name ||= if superclass < WebVuln superclass.header_name end end end # # Gets or sets the HTTP cookie param to exploit. # # @param [String, nil] new_cookie_param # The optional new cookie param value to set. # # @return [String, nil] # The cookie param for the web vulnerability. # # @example # cookie_param 'foo' # def self.cookie_param(new_cookie_param=nil) if new_cookie_param @cookie_param = new_cookie_param else @cookie_param ||= if superclass < WebVuln superclass.cookie_param end end end # # Gets or sets the form param to exploit. # # @param [String, nil] new_form_param # The optional new form param value to set. # # @return [String, nil] # The form param for the web vulnerability. # # @example # form_param 'user' # def self.form_param(new_form_param=nil) if new_form_param @form_param = new_form_param else @form_param ||= if superclass < WebVuln superclass.form_param end end end # # Gets or sets the exploit's default headers. # # @param [Hash{Symbol,String => String}, nil] new_headers # The optional new default headers values to set. # # @return [Hash{Symbol,String => String}, nil] # The default headers for the web vulnerability. # # @example # headers 'X-Foo' => 'foo', 'X-Bar' => 'bar' # def self.headers(new_headers=nil) if new_headers @headers = new_headers else @headers ||= if superclass < WebVuln superclass.headers end end end # # Gets or sets the exploit's default HTTP cookie data. # # @param [String, Hash{String => String}, nil] new_cookie # The optional new default cookie values to set. # # @return [String, Hash{String => String}, nil] # The default cookie values for the web vulnerability. # # @example # cookie 'lang' => 'en', 'foo' => 'bar' # def self.cookie(new_cookie=nil) if new_cookie @cookie = new_cookie else @cookie ||= if superclass < WebVuln superclass.cookie end end end # # Gets or sets the exploit's default form data. # # @param [String, Hash, nil] new_form_data # The optional new default form data values to set. # # @return [String, Hash, nil] # The default form data values for the web vulnerability. # # @example # form_data 'foo' => 'a', 'bar' => 'b' # def self.form_data(new_form_data=nil) if new_form_data @form_data = new_form_data else @form_data ||= if superclass < WebVuln superclass.form_data end end end # # Gets or sets the exploit's default `Referer` path. # # @param [String, nil] new_referer # The optional new default `Referer` value to set. # May be either a path or a fully qualified URL. # # @return [String, nil] # The default `Referer` values for the web vulnerability. # # @example with a path: # referer '/previous/page.php' # # @example with a fully qualified URL: # referer 'https://other.website.com/page.php' # def self.referer(new_referer=nil) if new_referer @referer = new_referer else @referer ||= if superclass < WebVuln superclass.referer end end end param :http_user, String, desc: 'The user for HTTP Basic-Auth' param :http_password, String, desc: 'The password for HTTP Basic-Auth' # # The target URL for the web vulnerability. # # @return [URI::HTTP] # def url @url ||= url_for(self.class.base_path) end # # Additional HTTP header names and values to add to the exploit request. # # @return [Hash{Symbol,String => String}, nil] # # @see headers # def headers self.class.headers end # # Additional `Cookie` header to send with the exploit request. # # @return [String, Hash{String => String}, nil] # # @see cookie # def cookie self.class.cookie end # # The form data that may be sent in the body of the exploit request. # # @return [Hash, String, nil] # # @see form_data # def form_data self.class.form_data end # # The optional HTTP `Referer` header to send with the exploit request. # # @return [String, nil] # # @see referer # def referer if (referer = self.class.referer) url_for(referer) end end # # Common keyword arguments for `Ronin::Vulns::Web#initialize`. # # @return [Hash{Symbol => Object}] # # @api private # def web_vuln_kwargs { query_param: self.class.query_param, header_name: self.class.header_name, cookie_param: self.class.cookie_param, form_param: self.class.form_param, request_method: self.class.request_method, http: http, user: params[:http_user], password: params[:http_password], headers: headers, cookie: cookie, form_data: form_data, referer: referer } end # # Creates the `Ronin::Vulns::WebVuln` object based on the information # defined in the exploit class and params. # # @return [Ronin::Vulns::WebVuln] # # @abstract # def vuln raise(NotImplementedError,"#{self.class}##{__method__} was not implemented") end # # Determines if the URL is vulnerable to the web vulnerability. # # @return [TestResult::Vulnerable, TestResult::NotVulnerable] # Indicates whether the URL is vulnerable or not vulnerable. # def test if vuln.vulnerable? Vulnerable("The target URL is vulnerable") else NotVulnerable("The target URL is not vulnerable") end end end end end