Arp Spoofing in Flask with Bearer Tokens
Arp Spoofing in Flask with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Arp spoofing is a Layer 2 network attack where an attacker sends falsified Address Resolution Protocol messages to associate their MAC address with the IP address of a legitimate host, typically the default gateway. In a Flask application that uses Bearer Tokens for API authentication, arp spoofing can expose tokens in transit even when TLS is used in some deployment topologies, or it can facilitate session hijacking when the token is passed over a compromised local network. The combination is risky because Flask routes often validate Bearer Tokens but rely on the assumption that the network path between the client and server is trustworthy. If an attacker successfully spoofs ARP entries on that local segment, they can intercept, observe, or modify HTTP requests before they reach Flask, potentially capturing Authorization headers that contain Bearer Tokens.
Consider a Flask API that accepts requests like this:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/api/me")
def me():
auth = request.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
return jsonify({"error": "missing bearer token"}), 401
token = auth.split(" ", 1)[1]
# token validation logic here
return jsonify({"ok": True})
An attacker performing arp spoofing on the same LAN can position themselves as a man-in-the-middle on the host’s network path. If the client sends an HTTPS request to the Flask endpoint but the attacker’s ARP spoofing causes traffic to route through them, the attacker can terminate the client’s TLS connection (SSL stripping) or simply observe traffic on a non-encrypted segment. Even if TLS is enforced end-to-end, in environments where TLS inspection appliances or misconfigured proxies exist, arp spoofing can expose tokens to an entity that can intercept and relay requests. The Flask app itself may never detect the spoofing because the token arrives intact, making the attack particularly dangerous for token-based authentication schemes.
Additionally, if the Flask service communicates with other internal services using Bearer Tokens extracted from incoming requests (token propagation), arp spoofing on the internal network can expose those tokens to lateral movement. Since the attack targets the network layer, it complements application-layer authentication mechanisms without directly breaking cryptography, highlighting the importance of treating the network as hostile even when tokens are transmitted over TLS.
Bearer Tokens-Specific Remediation in Flask — concrete code fixes
Remediation focuses on ensuring tokens are never exposed on the wire and that Flask enforces strict transport security. First, always serve Flask over TLS using a trusted certificate. In production, place Flask behind a reverse proxy (like Nginx or a load balancer) that terminates TLS and forwards requests to Flask over a private, trusted network. Second, avoid propagating tokens across internal services; validate once and use opaque references or session identifiers instead of passing raw Bearer Tokens internally.
Enforce HTTPS in Flask so that any non-TLS request is rejected:
from flask import Flask, request, jsonify
from flask_talisman import talisman
app = Flask(__name__)
talisman(app, force_https=True)
@app.route("/api/me")
def me():
auth = request.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
return jsonify({"error": "missing bearer token"}), 401
token = auth.split(" ", 1)[1]
# validate token
return jsonify({"ok": True})
Use strict host and referrer policies via Talisman to reduce exposure in browser contexts:
talisman(app, content_security_policy={"default-src": ["'self'"]}, force_https=True, frameguard=True)
When validating Bearer Tokens, prefer constant-time comparison to avoid timing attacks and avoid logging tokens:
import hmac
from flask import Flask, request, jsonify
app = Flask(__name__)
SECRET_TOKEN = "example-secure-token"
@app.route("/api/validate")
def validate():
auth = request.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
return jsonify({"error": "invalid"}), 401
token = auth.split(" ", 1)[1]
# Use hmac.compare_digest for constant-time checks
if not hmac.compare_digest(token, SECRET_TOKEN):
return jsonify({"error": "invalid"}), 401
return jsonify({"ok": True})
For token propagation scenarios, do not forward the original Authorization header to downstream services. Instead, exchange the token for a scoped session or use an internal service mesh that manages identity separately:
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/api/resource")
def resource():
auth = request.headers.get("Authorization", "")
if not auth.startswith("Bearer "):
return jsonify({"error": "missing bearer token"}), 401
token = auth.split(" ", 1)[1]
# Validate token locally first
if not validate_token(token):
return jsonify({"error": "invalid"}), 401
# Do NOT forward the Authorization header blindly
headers = {"X-Internal-User": get_user_id(token)}
resp = requests.get("http://internal-service/data", headers=headers, timeout=2)
return jsonify(resp.json())
Finally, complement these code-level fixes with network-level protections. Use VLANs, firewalls, and host-based ARP monitoring to detect and prevent arp spoofing. While Flask and Bearer Tokens are not inherently vulnerable, the combination with an untrusted network increases risk; defense in depth across network and application layers is essential.