Class: Ronin::Vulns::SSTI

Inherits:
WebVuln show all
Defined in:
lib/ronin/vulns/ssti.rb,
lib/ronin/vulns/ssti/test_expression.rb

Overview

Represents a Server Side Template Injection (SSTI) vulnerability.

Defined Under Namespace

Classes: TestExpression

Constant Summary collapse

ESCAPES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

List of common Server Side Template Injection (SSTI) escapes.

{
  nil => nil, # does not escape the expression

  double_curly_braces:        ->(expression) { "{{#{expression}}}"    },
  dollar_curly_braces:        ->(expression) { "${#{expression}}"     },
  dollar_double_curly_braces: ->(expression) { "${{#{expression}}}"   },
  pound_curly_braces:         ->(expression) { "\#{#{expression}}"    },
  angle_brackets_percent:     ->(expression) { "<%= #{expression} %>" }
}

Instance Attribute Summary collapse

Attributes inherited from WebVuln

#cookie, #cookie_param, #form_data, #form_param, #header_name, #headers, #http, #password, #query_param, #query_params, #referer, #request_method, #url, #user, #user_agent

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from WebVuln

#exploit, #exploit_cookie, #exploit_form_data, #exploit_headers, #exploit_query_params, #original_value, #random_value, #request, scan, scan_cookie_params, scan_form_params, scan_headers, scan_query_params, test, #to_curl, #to_http, #to_s

Constructor Details

#initialize(url, escape: nil, test_expr: self.class.random_test, **kwargs) ⇒ SSTI

Initializes the Server Side Template Injection (SSTI) vulnerability.

Parameters:

  • url (String, URI::HTTP)

    The URL to exploit.

  • escape (:double_curly_braces, :dollar_curly_braces, :dollar_double_curly_braces, :pound_curly_braces, :angle_brackets_percent, :custom, Proc, nil) (defaults to: nil)

    How to escape a given payload. Either a proc that will accept a String and return a String, a Symbol describing the template syntax to use, or nil to indicate that the payload will not be escaped.

  • test_expr (TestExpression) (defaults to: self.class.random_test)

    The test payload and expected result to check for when testing the URL for SSTI.

Raises:

  • (ArgumentError)

    An unknown escape_type: or escape: value was given, or no test_expr: was given.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ronin/vulns/ssti.rb', line 82

def initialize(url, escape:    nil,
                    test_expr: self.class.random_test,
                    **kwargs)
  super(url,**kwargs)

  case escape
  when Symbol
    @escape_type = escape
    @escape      = ESCAPES.fetch(escape) do
                     raise(ArgumentError,"unknown template syntax: #{escape_type.inspect}")
                   end
  when Proc
    @escape_type = :custom
    @escape      = escape
  when nil # no-op
  else
    raise(ArgumentError,"invalid escape type, must be a Symbol, Proc, or nil: #{escape.inspect}")
  end

  @test_expr = test_expr

  unless @test_expr
    raise(ArgumentError,"must specify both a test expression")
  end
end

Instance Attribute Details

#escapeProc? (readonly)

How to escape the payload so that it's executed.

Returns:

  • (Proc, nil)

    The proc that will accept a String and return a String, or nil to indicate that the payload will not be escaped.



56
57
58
# File 'lib/ronin/vulns/ssti.rb', line 56

def escape
  @escape
end

#escape_type:double_curly_braces, ... (readonly)

The type of SSTI escape used.

Returns:

  • (:double_curly_braces, :dollar_curly_braces, :dollar_double_curly_braces, :pound_curly_braces, :angle_brackets_percent, :custom, nil)

Since:

  • 0.2.0



49
50
51
# File 'lib/ronin/vulns/ssti.rb', line 49

def escape_type
  @escape_type
end

#test_exprTestExpression (readonly)

The test expression to use when testing the URL for SSTI.

Returns:



61
62
63
# File 'lib/ronin/vulns/ssti.rb', line 61

def test_expr
  @test_expr
end

Class Method Details

.random_testTestExpression

Generates a random N*M SSTI test.

Returns:



114
115
116
117
118
119
120
121
122
# File 'lib/ronin/vulns/ssti.rb', line 114

def self.random_test
  int1 = rand(1_000..1_999)
  int2 = rand(1_000..1_999)

  string  = "#{int1}*#{int2}"
  result  = (int1 * int2).to_s

  return TestExpression.new(string,result)
end

.test_param(url, escape: ESCAPES.keys, http:, **kwargs) ⇒ SSTI?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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.

Parameters:

  • url (URI::HTTP)

    The URL to test.

  • escape (Array<Symbol, Proc>, Symbol, Proc, nil) (defaults to: ESCAPES.keys)

    The escape method to use. If escape: is not given, then all escapes names in ESCAPES will be tested..

  • http (Ronin::Support::Network::HTTP)

    The HTTP session to use for testing the URL.

  • kwargs (Hash{Symbol => Object})

    Additional keyword arguments for #initialize.

Options Hash (**kwargs):

  • :query_param (Symbol, String, true, nil)

    The query param name to test.

  • :header_name (Symbol, String, nil)

    The header name to test.

  • :cookie_param (Symbol, String, true, nil)

    The cookie param name to test.

  • :form_param (Symbol, String, nil)

    The form param name to test.

Returns:

  • (SSTI, nil)

    The first discovered web vulnerability for the specific query param, header name, cookie param, or form param.

Since:

  • 0.2.0



162
163
164
165
166
167
168
169
170
171
172
# File 'lib/ronin/vulns/ssti.rb', line 162

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

    return vuln if vuln.vulnerable?
  end

  return nil
end

.vuln_typeSymbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method is abstract.
Note:

This is used internally to map an vulnerability class to a printable type.

Returns the type or kind of vulnerability.

Returns:

  • (Symbol)


213
214
215
# File 'lib/ronin/vulns/ssti.rb', line 213

def self.vuln_type
  :ssti
end

Instance Method Details

#encode_payload(payload) ⇒ String

Escapes the payload using #escape.

Parameters:

  • payload (String)

Returns:

  • (String)


181
182
183
184
185
# File 'lib/ronin/vulns/ssti.rb', line 181

def encode_payload(payload)
  if @escape then @escape.call(payload)
  else            payload
  end
end

#vulnerable?Boolean

Determine whether the URL is vulnerable to Server Side Template Injection (SSTI).

Returns:

  • (Boolean)


193
194
195
196
197
198
# File 'lib/ronin/vulns/ssti.rb', line 193

def vulnerable?
  response = exploit(@test_expr.string)
  body     = response.body

  return body.include?(@test_expr.result)
end