HIGH ldap injectionfastapibasic auth

Ldap Injection in Fastapi with Basic Auth

Ldap Injection in Fastapi with Basic Auth — 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 application that uses HTTP Basic Auth, developers sometimes build LDAP filter strings by directly embedding the username or password from the Authorization header. This pattern is common in legacy integrations where authentication is delegated to an LDAP directory (such as OpenLDAP or Active Directory).

Consider a scenario where FastAPI extracts the username from Basic Auth and constructs an LDAP filter like (&(uid={username})(objectClass=person)). If the username is not sanitized, an attacker can supply values such as admin)(&(objectClass=*) to alter the filter logic. This can bypass intended access controls, expose other users' entries, or disclose sensitive attributes. The vulnerability is not in LDAP itself but in how the application builds the query string.

In FastAPI, Basic Auth is typically handled via dependencies that decode the header and provide a username and password. If the application then passes these values into an LDAP search filter without escaping special characters (e.g., asterisk, parentheses, backslash), the LDAP server may interpret them as control characters. This can lead to authentication bypass or unauthorized data retrieval, depending on the server configuration and access control lists.

Another risk vector involves account enumeration. An attacker can send specially crafted usernames that cause different LDAP responses based on existence, such as using *(objectClass=*) or malformed filters, to infer valid usernames. Because FastAPI applications often expose minimal error details, attackers may rely on timing differences or response codes to refine injection attempts.

To detect such issues, middleBrick scans unauthenticated attack surfaces and includes LDAP-related behaviors among its 12 security checks. The tool examines how authentication inputs are used, highlighting cases where credentials or identifiers are reflected into directory queries without proper safeguards.

Basic Auth-Specific Remediation in Fastapi — concrete code fixes

Remediation focuses on avoiding string concatenation for LDAP filters and using parameterized APIs or strict escaping. Never build LDAP queries by interpolating user input. Instead, use an LDAP library that supports safe filter construction, or apply rigorous escaping for reserved characters.

Below is a secure FastAPI example using HTTP Basic Auth that avoids injection by not incorporating credentials into LDAP filters. Authentication is performed against a directory using a bind DN that is derived from a trusted mapping, not from raw user input used in queries.

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import ldap3

app = FastAPI()
security = HTTPBasic()

# Trusted mapping from provided username to a safe bind DN
def get_bind_dn(username: str) -> str:
    # Example mapping; in production, validate against an allowlist or directory
    allowed = {"alice": "uid=alice,ou=people,dc=example,dc=com",
               "bob": "uid=bob,ou=people,dc=example,dc=com"}
    return allowed.get(username)

def ldap_authenticate(credentials: HTTPBasicCredentials = Depends(security)):
    username = credentials.username
    password = credentials.password
    bind_dn = get_bind_dn(username)
    if not bind_dn:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid credentials",
            headers={"WWW-Authenticate": "Basic"}
        )
    server = ldap3.Server("ldap://ldap.example.com")
    connection = ldap3.Connection(server, user=bind_dn, password=password)
    if not connection.bind():
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid credentials"
        )
    return username

@app.get("/secure")
def secure_endpoint(username: str = Depends(ldap_authenticate)):
    return {"message": f"Authenticated as {username}"}

If you must construct search filters, use an escaping function for LDAP special characters. For example, Python's ldap3.utils.conv.escape_filter_chars can safely encode values before inclusion.

from ldap3.utils.conv import escape_filter_chars
username_escaped = escape_filter_chars(user_input)
filter_str = f"(&(uid={username_escaped})(objectClass=person))"

Additionally, enforce strong input validation (e.g., allowlist usernames), avoid returning detailed LDAP errors to clients, and monitor for unusual filter patterns. middleBrick’s LLM/AI Security checks include prompt injection and jailbreak tests, but for API endpoints, its Authentication and BOLA/IDOR checks help surface improper use of credentials in directory queries.

Frequently Asked Questions

Can middleBrick detect LDAP injection in my FastAPI endpoints?
Yes. middleBrick scans unauthenticated attack surfaces and includes checks related to authentication and authorization, flagging patterns where credentials or identifiers are improperly used in directory queries.
Does middleBrick fix LDAP injection vulnerabilities automatically?
No. middleBrick detects and reports findings with remediation guidance. It does not fix, patch, or block issues. Developers should apply secure coding practices, such as using parameterized filters and proper escaping.