Ldap Injection in Fastapi with Hmac Signatures
Ldap Injection in Fastapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability
LDAP Injection occurs when user-controlled input is concatenated into an LDAP query without proper validation or escaping. In a FastAPI service that uses HMAC signatures to authenticate requests, an attacker can exploit injection points separately from the signature verification logic. The signature may validate the integrity of parameters, but if the application later uses those parameters in an LDAP filter or DN construction, the signature does not prevent malicious payloads from being interpreted as LDAP syntax.
Consider a FastAPI endpoint that accepts a username and uses HMAC-signed tokens to verify request authenticity. The developer may assume that because the request is signed, the input is safe. However, if the username is passed directly into an LDAP search filter like (uid={username}), an attacker can provide admin)(objectClass=person) as the username, breaking the filter structure and potentially exposing additional entries. The HMAC verification passes, but the LDAP query is manipulated, leading to unauthorized data retrieval or authentication bypass.
This combination is dangerous because HMAC signatures protect against tampering of known parameters, but they do not sanitize or validate the semantic meaning of those parameters. An attacker may also exploit special LDAP characters such as asterisk (*), parentheses, and backslashes to perform wildcard searches or inject crafted filters. If the FastAPI application uses a library that does not properly escape these characters, the LDAP server may interpret the input as intended by the attacker. The signature mechanism operates at the HTTP layer, while LDAP injection operates at the directory access layer; both can be present simultaneously without conflict, increasing risk.
Real-world impact includes unauthorized reading of directory entries, potential enumeration of usernames, and in some configurations, authentication as another user if the LDAP filter is used for binding. This maps to the BOLA/IDOR and Input Validation checks in middleBrick, which would flag such patterns during a scan. The scanner does not assume the presence of LDAP, but when an endpoint accepts directory queries, unsanitized input combined with signed requests can lead to severe access control issues.
Hmac Signatures-Specific Remediation in Fastapi — concrete code fixes
To secure a FastAPI endpoint using HMAC signatures while preventing LDAP injection, you must treat signed parameters as untrusted for directory queries. Use strict allow-lists for input formats and always escape special characters before incorporating them into LDAP filters. Below is a complete, working FastAPI example that demonstrates secure handling with HMAC verification and safe LDAP query construction.
import hmac
import hashlib
from fastapi import FastAPI, Header, HTTPException, Depends
from pydantic import BaseModel
import re
app = FastAPI()
# Shared secret stored securely, e.g., from environment variable
SECRET_KEY = b'super-secret-key-change-in-production'
def verify_hmac(payload: bytes, signature: str) -> bool:
computed = hmac.new(SECRET_KEY, payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, signature)
def validate_username(username: str) -> bool:
# Allow only alphanumeric and limited safe characters
return re.fullmatch(r'[a-zA-Z0-9._-]{1,64}', username) is not None
async def get_hmac_signature(x_signature: str = Header(...)) -> str:
return x_signature
@app.post('/search-user')
def search_user(username: str, signature: str = Depends(get_hmac_signature)):
if not validate_username(username):
raise HTTPException(status_code=400, detail='Invalid username format')
payload = username.encode('utf-8')
if not verify_hmac(payload, signature):
raise HTTPException(status_code=401, detail='Invalid signature')
# Safe LDAP query construction: escape special characters
safe_username = username.replace('\\', '\\\\').replace('(', '\\(').replace(')', '\\)').replace('*', '\\*')
ldap_filter = f'(uid={safe_username})'
# Here you would pass ldap_filter to your LDAP library
return {'filter': ldap_filter, 'status': 'safe'}
Key points in this remediation:
- Input validation uses a strict regular expression to allow only expected characters and length limits.
- HMAC verification uses
hmac.compare_digestto prevent timing attacks. - LDAP special characters are escaped before constructing the filter, neutralizing injection attempts while preserving legitimate usernames.
- The signature is computed over the raw username bytes, ensuring that any modification invalidates verification.
For production, store SECRET_KEY in a secure secret manager and rotate keys periodically. Combine this approach with middleware that rejects requests containing suspicious LDAP syntax to add defense in depth. middleBrick scans would detect missing validation or weak escaping patterns and map findings to relevant frameworks such as OWASP API Top 10 and PCI-DSS.