Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
POC-CVE-2026-65971 — Prueba de concepto y análisis técnico para CVE-2026-65971 — inyección SQL mediante la propiedad sortDirection de Livewire en power-components/livewire-powergrid (< 6.10.4) | Kitploit
Herramientas/GitHubGitHub/biitts/poc-cve-2026-65971
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónPapers e InvestigaciónAprendizaje y Educación
GitHubbiitts/poc-cve-2026-65971

POC-CVE-2026-65971

Prueba de concepto y análisis técnico para CVE-2026-65971 — inyección SQL mediante la propiedad sortDirection de Livewire en power-components/livewire-powergrid (< 6.10.4)

Ver Repositorio
19hace 2 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-65971 — Inyección SQL en Livewire PowerGrid mediante sortDirection

Prueba de concepto e informe técnico completo para CVE-2026-65971 / GHSA-7fgc-3h6c-698r, una inyección SQL en power-components/livewire-powergrid accesible a través de la propiedad pública sortDirection de Livewire.

CVECVE-2026-65971
GHSAGHSA-7fgc-3h6c-698r
Paquetepower-components/livewire-powergrid (Composer / Packagist)
Afectado>= 6.0.0, < 6.10.4
Corregido6.10.4
DebilidadCWE-89 — Neutralización incorrecta de elementos especiales utilizados en un comando SQL
Gravedad7.6 Alta — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
Reportado porCaio Fabrício (@BiiTts)
DivulgaciónCoordinada, mediante aviso de seguridad privado de 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
---

## 🧠 Resumen

PowerGrid es un componente de datatable para Laravel + Livewire (~2k estrellas, ampliamente utilizado en
paneles de administración de Laravel). Su estado de ordenamiento reside en dos **propiedades públicas de Livewire**:```php
public string $sortField = 'id';
public string $sortDirection = 'asc';

En Livewire, una propiedad pública forma parte del formato wire del componente: cualquier cliente que pueda alcanzar el componente puede establecerla mediante POST /livewire/update. Eso es por diseño; la frontera de seguridad es lo que el servidor hace con el valor.

La función naturalSort() de PowerGrid construye una expresión ORDER BY cruda que contiene el placeholder literal {sortDirection}, y un pipeline sustituye ese placeholder por el valor de la propiedad sin validar antes de pasar la cadena a orderByRaw(). Por lo tanto, la palabra clave de dirección acaba literalmente dentro del SQL.

El propio orderBy() de Laravel rechaza cualquier cosa que no sea asc/desc, y esa validación es lo que hace seguro el camino de ordenación ordinario. El fallo es que existe un segundo camino sin validar hacia la misma cláusula — y un atacante puede alcanzarlo saltándose por completo el camino que sí valida (véase El bypass).

Resultado: SQL arbitrario en la cláusula ORDER BY, explotable como oráculo ciego booleano/basado en tiempo para leer cualquier dato que el usuario de la base de datos pueda leer.


🔥 Impacto

Cualquiera que pueda acceder a una tabla de PowerGrid que use naturalSort puede leer datos arbitrarios de la base de datos — otras tablas, hashes de contraseñas, tokens de sesión, claves de API, registros de otros inquilinos — mediante un oráculo basado en tiempo / booleano.

  • Confidencialidad: Alta. Lectura completa de cualquier cosa que el usuario de la BD pueda SELECT.
  • Integridad: Baja. Las consultas apiladas están bloqueadas por la configuración predeterminada de PDO MySQL, por lo que ; UPDATE ... no se ejecuta. El impacto de escritura se limita a lo que una subconsulta pueda desencadenar.
  • Disponibilidad: Baja. La misma primitiva le da a un atacante SLEEP() y subconsultas pesadas — trivialmente abusable para inmovilizar hilos de la base de datos.
  • La ubicación típica es el factor agravante. Las tablas de PowerGrid se encuentran en paneles de administración y back-offices multiinquilino — exactamente donde están los datos interesantes. Un usuario inquilino con pocos privilegios que llegue a una de esas tablas puede exfiltrar toda la base de datos.

Privilegios requeridos: PR:L porque una tabla de datos normalmente está detrás de la autenticación de la aplicación. Si la tabla afectada se renderiza en una página no autenticada, recalcular con PR:N → 8.2 Alta.


🧩 Causa raíz — la cadena de taint completa

Tres archivos, tres etapas. Todas las referencias apuntan a la etiqueta vulnerable v6.10.3.

Etapa 1 — Origen: una propiedad pública controlada por el atacante

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

Ninguna de las dos propiedades tiene una lista blanca, una regla de validación ni un setter de normalización. `sortDirection` solo se asigna o se invierte:```php
public function reverseSort(): string    // line 37
{
    return $this->sortDirection === 'asc' ? 'desc' : 'asc';
}

updatedSortDirection() (línea 103) existe — el lugar natural para la validación — pero en v6.10.3 solo maneja la contabilidad de la carga diferida. Nunca inspecciona el valor.

Debido a que Livewire hidrata las propiedades públicas directamente desde la solicitud, sortDirection es completamente controlable por el atacante, como una cadena arbitraria, en este punto.

Etapa 2 — La cláusula cruda: naturalSort() inserta un marcador de posición

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

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

return $this;

});

`Sql::sortStringAsNumber()` se resuelve a una expresión por driver construida por
`getSortSqlByDriver()` en `src/DataSource/Support/Sql.php` (líneas 60–100). Cada variante de driver
termina con el mismo marcador de posición literal:```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

The vulnerability is independiente del controlador — every branch interpolates {sortDirection}.

Etapa 3 — Sumidero: el marcador de posición se resuelve con el valor bruto de la propiedad

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

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

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

}

y la ejecución, línea 52:```php
$query->{$method}($resolvedSql, $resolvedBindings);   // $method === 'orderByRaw'

data_get($this->component, 'sortDirection') devuelve la cadena del atacante, preg_replace_callback la inserta en el texto SQL, y orderByRaw() — que por contrato no escapa su argumento — la pasa a la base de datos.

Descargar herramienta