Missing Tls in Express with Hmac Signatures
Missing Tls in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Transport Layer Security (TLS) ensures confidentiality and integrity in transit between clients and an Express server. When TLS is missing, all HTTP traffic is sent in cleartext. This becomes especially critical when the application uses Hmac Signatures for request authentication. An Hmac Signature is typically computed over selected headers, a timestamp, and a payload, then sent in a custom header (e.g., X-API-Signature). Without TLS, an on-path attacker can observe the plaintext HTTP request, capture the signature, and replay it to forge authenticated requests. Even if the signature includes a timestamp intended to mitigate replay, the lack of TLS allows interception and reuse before expiry. Additionally, secret keys used to generate Hmac Signatures may be inadvertently exposed through logs, error messages, or referrer headers when TLS is absent, further weakening authentication. This combination is common in internal services or staging environments that mistakenly assume network obscurity provides sufficient protection. Attack patterns include session replay, credential theft via eavesdropping, and privilege escalation when the compromised signature grants elevated permissions.
Hmac Signatures-Specific Remediation in Express — concrete code fixes
To securely use Hmac Signatures in Express, enforce TLS and implement signature verification correctly. Below is an example Express server that uses HTTPS with a self-signed certificate for development and validates Hmac signatures on each request.
const https = require('https');
const fs = require('fs');
const crypto = require('crypto');
const express = require('express');
const app = express();
// Middleware to verify Hmac signature
function verifyHmac(req, res, next) {
const receivedSignature = req.headers['x-api-signature'];
const timestamp = req.headers['x-timestamp'];
const apiSecret = process.env.API_SECRET; // stored securely
if (!receivedSignature || !timestamp) {
return res.status(401).json({ error: 'Missing signature or timestamp' });
}
// Prevent replay attacks: reject if older than 5 minutes
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
return res.status(401).json({ error: 'Request expired' });
}
const payload = JSON.stringify(req.body);
const computed = crypto
.createHmac('sha256', apiSecret)
.update(timestamp + payload)
.digest('hex');
// Use timing-safe compare
if (!crypto.timingSafeEqual(Buffer.from(receivedSignature), Buffer.from(computed))) {
return res.status(401).json({ error: 'Invalid signature' });
}
return next();
}
app.use(express.json());
app.use(verifyHmac);
app.get('/api/resource', (req, res) => {
res.json({ data: 'secure data' });
});
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert')
};
https.createServer(options, app).listen(443, () => {
console.log('HTTPS server running on port 443');
});
Key points:
- Always serve endpoints over HTTPS using valid certificates. For local development, generate a self-signed certificate or use a trusted CA.
- Include a timestamp or nonce in the signed string and enforce a short validity window to mitigate replay.
- Use
crypto.timingSafeEqualto compare signatures to prevent timing attacks. - Keep the secret key in environment variables and rotate it periodically.
- Do not include sensitive data in URLs or logs; prefer POST with a body covered by the Hmac.
For production, use certificates from a recognized certificate authority and consider automating renewal. middleBrick can scan your Express endpoints to detect missing TLS and weak Hmac implementations, providing findings with severity ratings and remediation guidance in the Dashboard or via the CLI (middlebrick scan <url>). The Pro plan enables continuous monitoring so future regressions are caught early, and the GitHub Action can fail builds if a scan drops below your chosen threshold.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |