Arp Spoofing in Strapi with Bearer Tokens
Arp Spoofing in Strapi with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Arp spoofing is a link-layer attack where an attacker sends falsified Address Resolution Protocol messages onto a local network to associate their MAC address with the IP address of a legitimate host, such as a Strapi server or a client that communicates with it. When this happens on the same broadcast domain (for example, an internal or Wi‑Fi network), traffic that should go to the Strapi host is instead delivered to the attacker. If the client authenticates with a Bearer token in an Authorization header, the attacker can intercept those requests and capture or alter them before the legitimate server processes them.
In Strapi, Bearer tokens are often used for admin authentication and for API access when using JWTs or opaque tokens passed via the Authorization header. Consider a typical request from a JavaScript client:
fetch('http://strapi.example.com/api/articles', {
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
}
});
If an attacker successfully performs arp spoofing on the network path between the client and Strapi, they can act as a man-in-the-middle and observe these Authorization headers. The token itself is not inherently insecure, but its exposure and potential replay or modification depend on transport protections. Without encryption in transit, intercepted Bearer tokens can be reused while valid, enabling session hijacking. Moreover, if the attacker also tampers with requests (for example, changing the target ID in an API call), they may exploit Insecure Direct Object References (IDOR) or BOLA-style logic that Strapi exposes when authorization checks are misaligned with object ownership. Strapi’s security therefore depends not only on token handling but also on ensuring that all token-bearing traffic traverses an encrypted channel and that endpoints enforce proper ownership checks.
Even when Strapi validates a Bearer token, arp spoofing shifts the threat to the network path. Attackers can capture token values, inject additional requests, or modify payloads if TLS is not properly enforced on the server and clients. Common misconfigurations include allowing HTTP fallback, not enforcing HSTS, or serving APIs on mixed-content endpoints. Compounded by weak network segmentation, these conditions make it easier for arp spoofing to compromise authentication based on Bearer tokens. The risk is not in the token format itself, but in the combination of token usage, lack of mandatory encryption, and insufficient runtime validation of object-level permissions.
Bearer Tokens-Specific Remediation in Strapi — concrete code fixes
Remediation centers on ensuring that Bearer tokens are never exposed on insecure channels and that Strapi endpoints validate both token validity and resource ownership. The primary network-level fix is to enforce HTTPS for all Strapi communications, including admin and API routes. Use a trusted certificate and configure your reverse proxy or load balancer to redirect HTTP to HTTPS. In Strapi, you can set the server URL and enforce secure cookies and HSTS via the admin panel under Settings → Advanced → Security. Complement this with code-level checks in Strapi controllers and policies to verify that the authenticated user is authorized for the specific resource being accessed.
For token usage, prefer short-lived JWTs or opaque tokens stored securely by clients (e.g., HttpOnly cookies with Secure and SameSite attributes) rather than embedding them in URLs where they might leak in logs or Referrer headers. When validating tokens, avoid custom logic that bypasses proper scope or role checks. Below is a minimal Strapi policy that ensures the requesting user can only access articles they own, mitigating BOLA/IDOR even if network-layer protections are bypassed:
// src/policies/ownership.js
'use strict';
module.exports = async (ctx, next) => {
const user = ctx.state.user; // set by authentication strapi plugin
if (!user) {
ctx.unauthorized('Unauthenticated');
return;
}
const entryId = ctx.params.id;
const article = await strapi.entityService.findOne('api::article.article', entryId);
if (!article) {
ctx.notFound();
return;
}
if (String(article.author) !== String(user.id)) {
ctx.forbidden('You cannot access this resource');
return;
}
await next();
};
module.exports.policy = {
handlers: {
async find(ctx) {
const user = ctx.state.user;
if (!user) return ctx.unauthorized('Unauthenticated');
return strapi.entityService.findMany('api::article.article', {
filters: { author: user.id },
});
},
async findOne(ctx) {
const user = ctx.state.user;
if (!user) return ctx.unauthorized('Unauthenticated');
const article = await strapi.entityService.findOne('api::article.article', ctx.params.id);
if (!article) return ctx.notFound();
if (String(article.author) !== String(user.id)) return ctx.forbidden('Forbidden');
return article;
},
},
};
On the client side, ensure Bearer tokens are attached only over HTTPS and are not persisted in insecure storage. Example of a secure fetch with token in Authorization header over HTTPS:
fetch('https://strapi.example.com/api/articles', {
method: 'GET',
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
'Content-Type': 'application/json',
},
}).then(res => res.json()).then(data => console.log(data));
For environments where multiple clients connect, consider adding a site-wide security header policy via Strapi’s configurations to tighten transport security and reduce the impact of potential misconfigurations that could weaken defenses against network-based attacks like arp spoofing.