What is LDAP Injection in Symfony and How Can You Prevent It?
LDAP injection in Symfony is a serious security flaw where unvalidated user inputs are directly included in Lightweight Directory Access Protocol (LDAP) queries, allowing attackers to manipulate authentication or directory lookups. This vulnerability can lead to unauthorized access, data exposure, and full system compromise. Symfony applications using manual LDAP queries or misconfigured components are especially at risk. Developers can prevent LDAP injection by properly escaping inputs using Ldap::escape() and configuring Symfony's built-in LDAP firewall. This guide helps Symfony developers detect, test, and fix LDAP injection vulnerabilities effectively.
Table of Contents
- What Is LDAP Injection?
- Why Symfony Apps Are at Risk
- Detection and Assessment Workflow
- Secure Coding in Symfony
- Testing Mitigations
- CI/CD Integration
- Common Pitfalls
- Key Takeaways
- Frequently Asked Questions (FAQs)
Lightweight Directory Access Protocol (LDAP) is widely used for user authentication and directory look‑ups in enterprise PHP applications. When a Symfony app interpolates unsanitized user input into LDAP queries, attackers can manipulate those queries — retrieving unauthorized data, bypassing logins, or escalating privileges. This in‑depth guide explains what LDAP injection is, how to spot it in Symfony projects, and how to remediate it with secure coding practices.
What Is LDAP Injection?
LDAP injection occurs when untrusted input is concatenated into an LDAP search or bind request without proper escaping. Much like SQL injection, the attacker adds special LDAP filter characters (e.g., *
, )(
, |
) to modify logic, extract sensitive directory entries, or force unconditional authentication.
Attack Example (unsafe pseudo‑code)
// Vulnerable login controller
$uid = $_POST['username'];
$pass = $_POST['password'];
$dn = "uid=$uid,ou=users,dc=example,dc=com";
$bound = $ldap->bind($dn, $pass); // Injection risk
If $uid
= *)(|(uid=*))
, the final DN becomes:
uid=*)(|(uid=*)),ou=users,dc=example,dc=com
The LDAP server interprets (|(uid=*)))
as a wildcard OR filter, effectively allowing any user to authenticate.
Why Symfony Apps Are at Risk
-
Custom authentication logic – Many teams bypass Symfony’s LDAP component and hand‑roll DN strings.
-
Legacy code – Older bundles or libraries may pre‑date modern escaping helpers.
-
Misconfigured firewalls – If LDAPS (SSL/TLS) is not enforced, traffic can be intercepted and tampered.
Detection and Assessment Workflow
Phase | Tool / Method | What to Look For |
---|---|---|
Static Review | grep -R "ldap_bind" src/ |
Concatenation of variables into DN or filter strings. |
Dynamic Testing | Burp Suite → Intruder | Payloads: *)(uid=*)) , `*)( |
Automated Scans | PHPStan + php-security-audit | Detects dangerous LDAP APIs without escaping. |
Unit Tests | PHPUnit w/ malicious inputs | Verify that injected characters are escaped or rejected. |
Indicators of Vulnerability
-
String interpolation like
"uid=".$username
-
Filters without
ldap_escape()
-
Missing Symfony
Ldap::escape()
helper
Secure Coding in Symfony
1. Use Symfony’s LDAP Component
use Symfony\Component\Ldap\Ldap;
use Symfony\Component\Ldap\Exception\LdapException;
$ldap = Ldap::create('ext_ldap', ['host' => 'ldaps://ldap.example.com']);
$client = $ldap->bind($serviceAccountDn, $servicePassword);
// SAFE: Escape both filter and DN parts
$filter = sprintf('(uid=%s)', Ldap::escape($uid, '', Ldap::ESCAPE_FILTER));
$entries = $ldap->query('ou=users,dc=example,dc=com', $filter)->execute();
2. Always Escape DN Parts
$dn = sprintf(
'uid=%s,ou=users,dc=example,dc=com',
Ldap::escape($uid, '', Ldap::ESCAPE_DN)
);
3. Leverage Symfony Security Bundle
Instead of manual binds:
# config/packages/security.yaml
security:
providers:
ldap:
service: Symfony\Component\Ldap\Ldap
base_dn: 'ou=users,dc=example,dc=com'
search_dn: '%env(LDAP_SEARCH_DN)%'
search_password: '%env(LDAP_SEARCH_PASSWORD)%'
default_roles: ROLE_USER
uid_key: uid
firewalls:
main:
pattern: ^/
ldap: true
The firewall handles escaping internally.
4. Harden Server & Connection
-
Enforce LDAPS (
ldaps://
or StartTLS). -
Restrict application account to read only scope.
-
Configure account‑lockout and audit logging for failed binds.
Testing Mitigations
-
Re‑run Burp Intruder with payloads after fixes; expect no unauthorized results.
-
Add unit tests:
public function testUidEscaping()
{
$escaped = Ldap::escape('*)(uid=*))', '', Ldap::ESCAPE_FILTER);
$this->assertStringNotContainsString(')(uid=', $escaped);
}
-
Use OpenLDAP slapd test container to mimic directory and ensure queries behave safely.
CI/CD Integration
-
Composer Audit for outdated LDAP packages.
-
PHPStan level 8 with custom rule for unescaped LDAP usage.
-
GitHub Actions: trigger penetration‑style job (
docker run ldap-inject-test
).
Common Pitfalls
Pitfall | Fix |
---|---|
Using addslashes() instead of Ldap::escape() |
Always use framework‑provided escape logic. |
Hard‑coding service account with write rights | Limit to least privilege. |
Ignoring bind result codes | Validate bind returns LDAP_SUCCESS (0) only. |
Storing raw LDAP errors in logs (info leak) | Sanitize or mask error details. |
Key Takeaways
-
LDAP injection exploits string concatenation in LDAP filtros/DNs.
-
Symfony provides
Ldap::escape()
and a secure LDAP firewall — use them. -
Detect issues via static analysis, Burp payloads, and unit tests.
-
LDAPS + least privilege + logging complete a defense‑in‑depth strategy.
By following this guide, you’ll fortify your Symfony applications against LDAP injection attacks, comply with modern security standards, and protect your user directory from unauthorized tampering.
Happy (secure) coding!
FAQs
What is LDAP injection in Symfony?
LDAP injection in Symfony is a security flaw where untrusted user input is inserted into LDAP queries without proper escaping, allowing attackers to manipulate or bypass authentication.
How does LDAP injection work?
It works by injecting special LDAP characters like *
, )(
, or |
into query filters or distinguished names, altering the logic of the LDAP search or bind.
Can LDAP injection lead to account compromise?
Yes, it can let attackers log in without valid credentials, retrieve unauthorized data, or escalate access privileges.
What components in Symfony are vulnerable?
Any code that directly interpolates user input into LDAP filter strings or DN strings without using Ldap::escape()
is vulnerable.
What is Ldap::escape()
in Symfony?
It’s a built-in method in Symfony's LDAP component that safely escapes user inputs for LDAP filters and DNs to prevent injection.
How can I prevent LDAP injection in Symfony apps?
Use Ldap::escape()
for all user inputs in LDAP queries and configure Symfony’s LDAP firewall for secure authentication.
What does a typical LDAP injection payload look like?
Examples include *)(uid=*))
or *)(|(objectClass=*))
, which trick the server into broad or unintended matches.
How do I detect LDAP injection?
Use static code review tools, dynamic testing (like Burp Suite), and input fuzzing to find unsafe LDAP interpolations.
Can Symfony’s security.yaml handle LDAP securely?
Yes, when properly configured, Symfony’s security component securely handles LDAP binds and escapes inputs automatically.
Is it safe to use addslashes()
to prevent LDAP injection?
No, addslashes()
is not sufficient for LDAP. Always use Ldap::escape()
with the correct escape type (FILTER or DN).
What are common signs of LDAP injection in logs?
Failed binds with malformed DN strings or unexpected wildcard search behavior are red flags.
Can LDAP injection be exploited remotely?
Yes, if user-controlled inputs are directly involved in bind or search requests, it can be remotely exploitable.
What are .desktop files mentioned in other Linux attacks?
.desktop files are launcher files used in Linux GUI systems; attackers sometimes weaponize them, unrelated to LDAP injection.
What tools help test LDAP injection?
Burp Suite, OWASP ZAP, and custom Python scripts using ldap3
can simulate LDAP injection scenarios.
Can Symfony applications using legacy LDAP libraries be vulnerable?
Yes, older libraries or custom authentication layers often lack built-in escaping and are at high risk.
Should we use LDAPS to enhance security?
Yes, LDAPS (LDAP over SSL) prevents man-in-the-middle attacks and ensures secure LDAP communication.
What is the difference between LDAP filter injection and DN injection?
Filter injection alters search logic; DN injection alters authentication path (e.g., bind DN).
Can Symfony escape both filter and DN parts?
Yes, using Ldap::escape($input, '', Ldap::ESCAPE_FILTER)
and Ldap::ESCAPE_DN
for their respective contexts.
Is there a Symfony bundle for LDAP security?
Symfony provides native support for LDAP in the Security bundle; additional community bundles also exist.
Are Symfony’s latest versions more secure against LDAP injection?
Yes, they include Ldap::escape()
and encourage safe practices, but developers must use them correctly.
Can LDAP injection be prevented via WAF?
A Web Application Firewall (WAF) can detect basic patterns but should not replace proper escaping and input validation.
How to log LDAP injection attempts?
Log malformed queries and failed authentication attempts with correlation to user input.
Can Symfony security logs help detect LDAP attacks?
Yes, if properly configured, logs can reveal repeated bind failures or suspicious query patterns.
What Symfony version added Ldap::escape()
?
The escape method has been available in Symfony LDAP since version 4.4+, providing filter and DN escaping options.
What happens if Ldap::escape()
is not used?
User inputs may alter LDAP logic, leading to unauthorized access or bypassed authentication.
Should I use environment variables in LDAP config?
Yes, to safely store credentials like bind DN and password without exposing them in code.
How to test if Ldap::escape()
is working?
Run a unit test with known injection payloads and verify they are properly encoded/escaped.
What is the risk rating of LDAP injection?
LDAP injection is classified as high-risk, especially in authentication paths.
Can LDAP injection be combined with privilege escalation?
Yes, attackers may query admin accounts or abuse search filters to retrieve privileged info.
What compliance mandates require LDAP injection protection?
Frameworks like OWASP, ISO 27001, and GDPR emphasize input validation and secure authentication paths.