Skip to content

Commit

Permalink
Added WebVuln.test_param for testing a single param (closes #69).
Browse files Browse the repository at this point in the history
* Added `CommandInjection.test_param` for enumerating over every
  combination of Command Injection escape quote, escape operator, and
  terminator character, for a single param.
* Added `SQLI.test_param` for enumerating over every combination of SQL
  injection escape quotes, escape quotes, and statement terminaton settings
  for a single param.
* Added `SSTI.test_param` for enumerating over every SSTI escape syntax
  for a single param.
* These new `.test_param` methods ensures that only one vulnerability is
  discovered per query param, header name, cookie param, or form param.
  • Loading branch information
postmodern committed Apr 16, 2024
1 parent b1656c0 commit 2269921
Show file tree
Hide file tree
Showing 8 changed files with 612 additions and 1,529 deletions.
64 changes: 37 additions & 27 deletions lib/ronin/vulns/command_injection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,12 @@ def build_escape_string
#
# Scans the URL for command injections.
#
# @param [URI::HTTP, String] url
# The URL to test or exploit.
# Tests the URL and a specific query param, header name, cookie param, or
# form param for Command Injection by enumerating over various Command
# Injection escape syntaxes.
#
# @param [URI::HTTP] url
# The URL to test.
#
# @param [Array<String, nil>, String, nil] escape_quote
# The optional escape quote character(s) to test.
Expand All @@ -117,42 +121,48 @@ def build_escape_string
# An HTTP session to use for testing the URL.
#
# @param [Hash{Symbol => Object}] kwargs
# Additional keyword arguments for {WebVuln.scan}.
# Additional keyword arguments for {#initialize}.
#
# @yield [command_injection]
# If a block is given it will be yielded each discovered command
# injection vulnerability.
# @option kwargs [Symbol, String, true, nil] :query_param
# The query param name to test.
#
# @yieldparam [CommandInjection] command_injection
# A discovered command injection vulnerability in the URL.
# @option kwargs [Symbol, String, nil] :header_name
# The header name to test.
#
# @return [Array<CommandInjection>]
# All discovered SQL injection vulnerabilities.
# @option kwargs [Symbol, String, true, nil] :cookie_param
# The cookie param name to test.
#
def self.scan(url, escape_quote: [nil, "'", '"', '`'],
escape_operator: [';', '|', '&', "\n"],
terminator: [nil, ';', '#', "\n"],
# WebVuln.scan keyword arguments
http: nil, **kwargs, &block)
url = URI(url)
http ||= Support::Network::HTTP.connect_uri(url)

vulns = []

# @option kwargs [Symbol, String, nil] :form_param
# The form param name to test.
#
# @return [CommandInjection, nil]
# The first discovered Command Injection vulnerability for the specific
# query param, header name, cookie param, or form param.
#
# @api private
#
# @since 0.2.0
#
def self.test_param(url, escape_quote: [nil, "'", '"', '`'],
escape_operator: [';', '|', '&', "\n"],
terminator: [nil, ';', '#', "\n"],
# keyword arguments for initialize
http: , **kwargs)
Array(escape_quote).each do |escape_quote_char|
Array(escape_operator).each do |escape_operator_char|
Array(terminator).each do |terminator_char|
vulns.concat(super(url, escape_quote: escape_quote_char,
escape_operator: escape_operator_char,
terminator: terminator_char,
http: http,
**kwargs,
&block))
vuln = new(url, escape_quote: escape_quote_char,
escape_operator: escape_operator_char,
terminator: terminator_char,
http: http,
**kwargs)

return vuln if vuln.vulnerable?
end
end
end

return vulns
return nil
end

#
Expand Down
62 changes: 35 additions & 27 deletions lib/ronin/vulns/sqli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,12 @@ def build_escape_string
public

#
# Scans the URL for SQL injections.
# Tests the URL and a specific query param, header name, cookie param, or
# form param for SQL injections by enumerating over various SQLi
# configurations.
#
# @param [URI::HTTP, String] url
# The URL to test or exploit.
# @param [URI::HTTP] url
# The URL to test.
#
# @param [Array<Boolean>, Boolean] escape_quote
# Controls whether to escape a quoted string value. If not specified,
Expand All @@ -123,40 +125,46 @@ def build_escape_string
# @param [Hash{Symbol => Object}] kwargs
# Additional keyword arguments for {WebVuln.scan}.
#
# @yield [sqli]
# If a block is given it will be yielded each discovered SQL injection
# vulnerability.
# @option kwargs [Symbol, String, nil] :query_param
# The query param name to test.
#
# @yieldparam [SQLI] sqli
# A discovered SQL injection vulnerability in the URL.
# @option kwargs [Symbol, String, nil] :header_name
# The header name to test.
#
# @return [Array<SQLI>]
# All discovered SQL injection vulnerabilities.
# @option kwargs [Symbol, String, true, nil] :cookie_param
# The cookie param name to test.
#
def self.scan(url, escape_quote: [false, true],
escape_parens: [false, true],
terminate: [false, true],
# WebVuln.scan keyword arguments
http: nil, **kwargs, &block)
url = URI(url)
http ||= Support::Network::HTTP.connect_uri(url)

vulns = []

# @option kwargs [Symbol, String, nil] :form_param
# The form param name to test.
#
# @return [SQLI] sqli
# The first discovered SQLi vulnerability for the specific query param,
# header name, cookie param, or form param.
#
# @api private
#
# @since 0.2.0
#
def self.test_param(url, escape_quote: [false, true],
escape_parens: [false, true],
terminate: [false, true],
# keyword arguments for initialize
http: , **kwargs)
Array(escape_quote).each do |escape_quote_value|
Array(escape_parens).each do |escape_parens_value|
Array(terminate).each do |terminate_value|
vulns.concat(super(url, escape_quote: escape_quote_value,
escape_parens: escape_parens_value,
terminate: terminate_value,
http: http,
**kwargs,
&block))
vuln = new(url, escape_quote: escape_quote_value,
escape_parens: escape_parens_value,
terminate: terminate_value,
http: http,
**kwargs)

return vuln if vuln.vulnerable?
end
end
end

return vulns
return nil
end

#
Expand Down
65 changes: 28 additions & 37 deletions lib/ronin/vulns/ssti.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,62 +122,53 @@ def self.random_test
end

#
# Scans the URL for Server Side Template Injection (SSTI) vulnerabilities.
# Tests the URL and a specific query param, header name, cookie param, or
# form param for a Server Side Template Injection (SSTI) vulnerability
# by enumerating over various SSTI syntaxes.
#
# @param [URI::HTTP, String] url
# The URL to scan.
# @param [URI::HTTP] url
# The URL to test.
#
# @param [Array<Symbol, Proc>, Symbol, Proc, nil] escape
# The escape method to use. If `escape:` is not given, then all escapes
# names in {ESCAPES} will be tested..
#
# @param [Ronin::Support::Network::HTTP] http
# The HTTP session to use for testing the URL.
#
# @param [Hash{Symbol => Object}] kwargs
# Additional keyword arguments for {#initialize}.
#
# @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :query_params
# The query param name(s) to test.
#
# @option kwargs [Array<Symbol, String>, Symbol, String, nil] :header_names
# The header name(s) to test.
#
# @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :cookie_params
# The cookie param name(s) to test.
#
# @option kwargs [Array<Symbol, String>, Symbol, String, nil] :form_params
# The form param name(s) to test.
#
# @option kwargs [Ronin::Support::Network::HTTP, nil] :http
# An HTTP session to use for testing the LFI.
# @option kwargs [Symbol, String, true, nil] :query_param
# The query param name to test.
#
# @option kwargs [Hash{String => String}, nil] :headers
# Additional headers to send with requests.
# @option kwargs [Symbol, String, nil] :header_name
# The header name to test.
#
# @option kwargs [String, Ronin::Support::Network::HTTP::Cookie, nil] :cookie
# Additional cookie params to send with requests.
# @option kwargs [Symbol, String, true, nil] :cookie_param
# The cookie param name to test.
#
# @option kwargs [String, nil] :referer
# Optional `Referer` header to send with requests.
# @option kwargs [Symbol, String, nil] :form_param
# The form param name to test.
#
# @option kwargs [Hash{String => String}, nil] :form_data
# Additional form data to send with requests.
# @return [SSTI, nil]
# The first discovered web vulnerability for the specific query param,
# header name, cookie param, or form param.
#
# @yield [vuln]
# If a block is given it will be yielded each discovered vulnerability.
#
# @yieldparam [SSTI] vuln
# A discovered SSTI vulnerability in the URL.
# @api private
#
# @return [Array<SSTI>]
# All discovered SSTI vulnerabilities.
# @since 0.2.0
#
def self.scan(url, escape: ESCAPES.keys, **kwargs,&block)
vulns = []

def self.test_param(url, escape: ESCAPES.keys,
# initialize keyword arguments
http: , **kwargs)
Array(escape).each do |escape_value|
vulns.concat(super(url, escape: escape_value, **kwargs, &block))
vuln = new(url, escape: escape_value, http: http, **kwargs)

return vuln if vuln.vulnerable?
end

return vulns
return nil
end

#
Expand Down
55 changes: 43 additions & 12 deletions lib/ronin/vulns/web_vuln.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,45 @@ def initialize(url, query_param: nil,
@referer = referer
end

#
# Internal method that tests combinations of configurations for a specific
# query param, header name, cookie param, or form param.
#
# @param [URI::HTTP] url
# The URL to test.
#
# @param [Ronin::Support::Network::HTTP, nil] http
# An HTTP session to use for testing the URL.
#
# @param [Hash{Symbol => Object}] kwargs
# Additional keyword arguments for {#initialize}.
#
# @option kwargs [Symbol, String, nil] :query_param
# The query param name to test.
#
# @option kwargs [Symbol, String, nil] :header_name
# The header name to test.
#
# @option kwargs [Symbol, String, true, nil] :cookie_param
# The cookie param name to test.
#
# @option kwargs [Symbol, String, nil] :form_param
# The form param name to test.
#
# @return [WebVuln, nil]
# The first discovered web vulnerability for the specific query param,
# header name, cookie param, or form param.
#
# @api private
#
# @since 0.2.0
#
def self.test_param(url, http: , **kwargs)
vuln = new(url, http: http, **kwargs)

return vuln if vuln.vulnerable?
end

#
# Scans the query parameters of the URL.
#
Expand Down Expand Up @@ -236,9 +275,7 @@ def self.scan_query_params(url,query_params=nil, http: nil, **kwargs)
vulns = []

query_params.each do |param|
vuln = new(url, query_param: param, http: http, **kwargs)

if vuln.vulnerable?
if (vuln = test_param(url, query_param: param, http: http, **kwargs))
yield vuln if block_given?
vulns << vuln
end
Expand Down Expand Up @@ -276,9 +313,7 @@ def self.scan_headers(url,header_names, http: nil, **kwargs)
vulns = []

header_names.each do |header_name|
vuln = new(url, header_name: header_name, http: http, **kwargs)

if vuln.vulnerable?
if (vuln = test_param(url, header_name: header_name, http: http, **kwargs))
yield vuln if block_given?
vulns << vuln
end
Expand Down Expand Up @@ -327,9 +362,7 @@ def self.scan_cookie_params(url,cookie_params=nil, http: nil, **kwargs)
vulns = []

cookie_params.each do |cookie_param|
vuln = new(url, cookie_param: cookie_param, http: http, **kwargs)

if vuln.vulnerable?
if (vuln = test_param(url, cookie_param: cookie_param, http: http, **kwargs))
yield vuln if block_given?
vulns << vuln
end
Expand Down Expand Up @@ -367,9 +400,7 @@ def self.scan_form_params(url,form_params, http: nil, **kwargs)
vulns = []

form_params.each do |form_param|
vuln = new(url, form_param: form_param, http: http, **kwargs)

if vuln.vulnerable?
if (vuln = test_param(url, form_param: form_param, http: http, **kwargs))
yield vuln if block_given?
vulns << vuln
end
Expand Down
Loading

0 comments on commit 2269921

Please sign in to comment.