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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cakephp-window-sqli — CakePHP 5.4.2 - Alta - Remota - SQLi - Desplazamientos de rango/frame de WindowExpression insertados en SQL | Kitploit
Herramientas/GitHubGitHub/abraxas/cakephp-window-sqli
Escáneres de VulnerabilidadesAnálisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebSeguridad WebSeguridad de Bases de Datos
GitHubabraxas/cakephp-window-sqli

cakephp-window-sqli

CakePHP 5.4.2 - Alta - Remota - SQLi - Desplazamientos de rango/frame de WindowExpression insertados en SQL

Ver Repositorio
17hace 8 díasAú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

Abraxas Labs - cakephp-window-sqli

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  cakephp-window-sqli

Write-up: https://abraxaslabs.tech/research/cakephp-window-sqli

cakephp-window-sqli

Clase: SQLi Alcance: Remoto

CakePHP 5.4.2 (887b641) - Cake Software Foundation

CVE-2026-79752 cerró cast / extract / dateAdd de FunctionsBuilder con ensureSimpleString(). WindowExpression::range() y frame() no estaban en esa corrección. rows() y groups() aceptan ?int. range() sigue aceptando una cadena. buildOffsetSql concatena el offset, el tipo de frame y PRECEDING / FOLLOWING en OVER. El binder no se usa a menos que el offset ya sea un ExpressionInterface.

Una aplicación que reenvía datos de la solicitud a func()->count('*')->over()->range($start, $end) coloca la cadena del llamador en RANGE BETWEEN sin bindear y sin comillas.

IDaún sin CVE
ClaseSQLi
AlcanceRemoto (aplicación que reenvía datos de la solicitud a range() / frame())
CWECWE-89
CVSSAlto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
ProductoCakePHP (cakephp/database)
Afectado5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63)
Autenticaciónaplicación que reenvía datos de query/formulario a ->over()->range($start, $end) / frame()
LicenciaGNU Affero GPL v3.0
Laboratoriosolo 127.0.0.1

Qué puede hacer un atacante

Un usuario que puede establecer el límite de ventana que la aplicación reenvía (analítica de "últimos N días", un generador de informes) convierte la cláusula OVER en SQL adicional.

PrivilegioMétodo / sinkTipoProbado en laboratorio o inferido
Empalmar un fragmento SQL en OVER (RANGE BETWEEN ...)GET /?mode=range&start= hacia AggregateExpression::range($start, $end) / WindowExpression::frame()Integridad del SQL compiladoProbado en laboratorio. El SQL compilado es RANGE BETWEEN 1) /* CAKEPHP-WINDOW-SQLI-WITNESS */ -- PRECEDING con un binder vacío
Leer o modificar filas como el usuario de BD de la aplicaciónLa misma consulta, ejecutadaIntegridad / reconocimiento de la BDInferido a partir del empalme. Este laboratorio es solo de compilación
Cambiar el tipo de frame o la dirección de la misma formaframe($type, $offset, $direction, ...) también concatena esas cadenasIntegridad del SQL compiladoInferido a partir de sql() / buildOffsetSql(). El laboratorio usó range()
Romper rows() / groups() de la misma formaTipado ?intCerradoProbado en laboratorio como cerrado. rows(3) es ROWS BETWEEN 3 PRECEDING, sin comillas, sin bindear

Cerrado en este pin: cast / extract / dateAdd / jsonValue de FunctionsBuilder (CVE-2026-79752 / CVE-2026-77635); Query::limit / offset (int tipado). El cakephp/app por defecto no llama a range() con datos de la cadena de consulta. Lo que queda es la API de ventana documentada. No es RCE no autenticado en una aplicación esqueleto. No es una shell.

Restos de pines iguales: collate SQLi, attachment CRLF, cache unserialize.

Cómo lo encontré

Fijé cakephp/cakephp 5.4.2 después de los GHSAs de SQLi en FunctionsBuilder de 2026. Diez búsquedas sobre esa etiqueta. CSRF / FormProtection, LFI en View, XXE en BodyParser, asignación masiva, XSS en helpers y clientIp() sin trustProxy volvieron vacíos en este listón. WindowExpressionTest::testRange todavía afirma:

$w = (new WindowExpression())->range("'1 day'", "'10 days'");

buildOffsetSql nunca vincula un desplazamiento de cadena:

protected function buildOffsetSql(
    ValueBinder $binder,
    ExpressionInterface|string|int|null $offset,
    string $direction,
): string {
    if ($offset === 0) {
        return 'CURRENT ROW';
    }
    if ($offset instanceof ExpressionInterface) {
        $offset = $offset->sql($binder);
    }
    return sprintf('%s %s', $offset ?? 'UNBOUNDED', $direction);
}

$binder no se utiliza a menos que el offset ya sea una ExpressionInterface.

Falsos caminos ya registrados: tratar rows() como el hueco (está tipado como int); afirmar que el cakephp/app estándar expone esto en un formulario público; ejecutar el SQL inyectado en SQLite como oráculo (POC-READY es solo de compilación); una reverse shell. Teatro.

Laboratorio

python3 cakephp-window-sqli-Abraxas-Labs.py

o

cd lab
./run.sh

Apunta solo a http://127.0.0.1:19440. Pequeña app PHP, cakephp/database 5.4.2, SQLite :memory:. GET /?mode=range&start= se pasa como string a range(). GET /?mode=rows&n=3 es el control de tipo int.

SUCCESS cakephp-window-sqli pin=5.4.2 range-raw=yes rows-numeric=yes bound=no quoted=no CAKEPHP-WINDOW-SQLI-WITNESS

IOC compilado en SQL:

SELECT (COUNT(*) OVER (RANGE BETWEEN 1) /* CAKEPHP-WINDOW-SQLI-WITNESS */ -- PRECEDING AND CURRENT ROW)) AS n FROM sqlite_master

Control:

SELECT (COUNT(*) OVER (ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)) AS n FROM sqlite_master

La solución

Vincular los desplazamientos numéricos. Permitir únicamente el tipo de marco (RANGE / ROWS / GROUPS) y la dirección (PRECEDING / FOLLOWING). Para las cadenas de intervalo, entrecomillarlas o exigir ExpressionInterface. Añadir una prueba de que un desplazamiento de range() que no sea int se convierte en un marcador de posición o en un literal entrecomillado, no en SQL sin procesar.

Referencias

  • github.com/cakephp/cakephp etiqueta 5.4.2 (887b641de9f7aba06071f98f17edcbc573cbcf63)
  • WindowExpression.php · AggregateExpression.php
  • Parcheados cercanos: CVE-2026-79752 · CVE-2026-77635
  • Mismo pin: cakephp-collate-sqli · cakephp-attachment-crlf · cakephp-cache-unserialize
  • CWE-89

Licencia

GNU Affero GPL v3.0. Véase LICENSE. Solo para laboratorio en loopback. Sin garantía.

Descargar herramienta