HIGH man in the middlejwt tokens

Man In The Middle with Jwt Tokens

How Man‑in‑the‑Middle Attacks Target JWT‑Based APIs

A man‑in‑the‑middle (MITM) attacker can read, modify, or replay traffic between a client and an API when the communication channel is not protected by strong transport security. When JSON Web Tokens (JWT) are used for authentication, the token itself becomes a high‑value target because it carries the claims that authorize access.

Typical MITM scenarios that affect JWTs include:

  • Token interception over unencrypted HTTP: If the API endpoint is reachable via plain HTTP, an attacker on the same network can capture the Authorization: Bearer header and reuse the token.
  • Downgrade to weak TLS or cipher suites: An attacker who can force a TLS downgrade (e.g., via SSLStrip) may decrypt the traffic, expose the JWT, and then alter claims such as sub or role before re‑signing it with a known key (if the server accepts the none algorithm or a weak secret).
  • Cookie‑based token theft: When JWTs are stored in cookies without the Secure and HttpOnly flags, a MITM can read or modify the cookie via JavaScript injection or network sniffing.
  • Replay attacks: Even if the token is signed, a captured JWT can be replayed within its validity window if the server does not enforce token binding, nonce, or one‑time use mechanisms.

These attacks map to OWASP API Security Top 10 items such as API1:2023 Broken Object Level Authorization (when token claims are tampered) and API2:2023 Broken Authentication (when transport protection is missing). Real‑world examples include CVE‑2016‑10555 (the “alg:none” JWT vulnerability) and CVE‑2018‑0114 (JWT tampering via weak key exposure).

Detecting MITM Weaknesses in JWT Tokens with middleBrick

middleBrick performs unauthenticated, black‑box scanning of the API surface and includes checks that reveal MITM‑related problems specific to JWT usage.

When you submit a URL, the scanner:

  • Verifies that the endpoint is only reachable over HTTPS; any HTTP response triggers a finding under the "Encryption" category with severity high.
  • Checks TLS configuration (protocol versions, cipher suites) and flags weak or deprecated settings (e.g., TLS 1.0, RC4) as medium‑severity findings.
  • Inspects HTTP response headers for missing security flags such as Strict-Transport-Security (HSTS) and reports them as medium findings.
  • Examines the Authorization: Bearer header (or cookie) in the response to see if a JWT is returned over an insecure channel; if so, it raises a high‑severity "Data Exposure" finding.
  • Attempts to replay a captured JWT (without altering it) to test whether the server accepts it after a short delay; successful replay yields a "Business Logic" finding related to missing replay protection.
  • For endpoints that advertise JWT support via an OpenAPI/Swagger spec, middleBrick cross‑references the spec’s security schemes with the actual runtime behavior, flagging mismatches (e.g., spec declares Bearer but the API accepts tokens over HTTP).

These checks appear in the dashboard as individual findings with remediation guidance. The CLI and GitHub Action expose the same results: middlebrick scan https://api.example.com returns a JSON payload that includes a "findings" array where each object contains category, severity, description, and remediation fields. In a CI pipeline, you can fail the build if any finding with severity ≥ high is present.

Remediating MITM Risks in JWT Implementations

Fixing MITM exposure for JWT‑based APIs relies on transport hardening and proper token handling. Below are concrete, language‑agnostic steps followed by code snippets for Node.js/Express.

1. Enforce HTTPS everywhere

  • Redirect all HTTP requests to HTTPS (status 301).
  • Enable HTTP Strict Transport Security (HSTS) with a sufficiently long max-age and the includeSubDomains flag.

2. Protect token storage

  • If using cookies, set Secure, HttpOnly, and SameSite=Strict (or Lax) attributes.
  • Prefer short‑lived access tokens (e.g., 5‑15 minutes) and refresh‑token rotation.

3. Validate JWTs strictly

  • Never accept the none algorithm; explicitly require HS256, RS256, or ES256.
  • Verify the iss (issuer), aud (audience), and exp (expiration) claims.
  • Consider using a token‑binding mechanism (e.g., binding the JWT to a TLS client certificate) to thwart replay.

Example: Node.js/Express middleware that enforces HTTPS, sets secure cookie flags, and verifies a JWT

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// 1. Force HTTPS (behind a proxy that sets X-Forwarded-Proto)
app.use((req, res, next) => {
  if (req.headers['x-forwarded-proto'] !== 'https') {
    return res.redirect(301, `https://${req.get('Host')}${req.originalUrl}`);
  }
  next();
});

// 2. HSTS header
app.use((req, res, next) => {
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  next();
});

// 3. JWT verification middleware
function authenticateToken(req, res, next) {
  const auth = req.headers['authorization'];
  if (!auth || !auth.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing token' });
  }
  const token = auth.slice(7);
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET, {
      algorithms: ['HS256'], // explicitly reject 'none'
      audience: 'my-api',
      issuer: 'my-auth-server',
    });
    req.user = payload; // attach claims to request
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

app.get('/api/data', authenticateToken, (req, res) => {
  res.json({ message: 'Protected data', user: req.user });
});

// 4. Set secure cookie when issuing a token (login endpoint)
app.post('/login', (req, res) => {
  // ... validate credentials ...
  const token = jwt.sign({ sub: userId, role: 'user' }, process.env.JWT_SECRET, {
    expiresIn: '15m',
    audience: 'my-api',
    issuer: 'my-auth-server'
  });
  res.cookie('token', token, {
    httpOnly: true,
    secure: true,   // only sent over HTTPS
    sameSite: 'strict',
    maxAge: 15 * 60 * 1000 // 15 minutes
  }).json({ success: true });
});

app.listen(3000, () => console.log('API listening on :3000'));

When you run middlebrick scan https://your-api.example.com after applying these controls, the scanner should report no high‑severity findings under the Encryption, Data Exposure, or Authentication categories.

Frequently Asked Questions

Does middleBrick can decrypt TLS traffic to inspect JWTs inside the scan?
No. middleBrick performs unauthenticated black‑box testing from the outside; it does not break or decrypt TLS. It only observes what is transmitted over the network and flags missing or weak transport protections.
If my API accepts JWTs in the Authorization header, will middleBrick still detect a missing HSTS header?
Yes. The scanner checks response headers for Strict-Transport-Security regardless of the authentication method. A missing HSTS header is reported as a medium‑severity finding under the Encryption category.