Lion Cipher Lab
Exploit and fix LDAP injection in your own lab
- AppSec / DevSecOps
- Advanced
- ~90 min
- Free · no account required
Why it matters
Directories are still the beating heart of enterprise identity: logins, address books, group lookups and 'who is my manager' pages very often run an LDAP search behind the scenes, and a huge number of them were built years ago by pasting the username straight into a filter string. That single habit is LDAP injection, and it hands an attacker exactly what SQL injection does — authentication bypass and data theft — against the one system that authenticates everyone. Learning to see the filter being rewritten, and to shut it with escaping and a proper bind flow, protects the crown-jewel service…
What you'll learn
- explaining LDAP injection as SEARCH-FILTER injection: an app pastes user input into an LDAP filter string like (&(uid=USER)(userPassword=PASS)) and the attacker's filter metacharacters (* ( ) & | !) rewrite the query
- reading LDAP search-filter syntax (RFC 4515): prefix boolean operators (&)(|)(!), equality (attr=value), the * wildcard, and the absolute-true (&) / absolute-false (|) filters (RFC 4526)
- building a deliberately vulnerable directory login on your own machine with Python, Flask, the ldap3 library and a throwaway OpenLDAP container
- bypassing authentication with a wildcard payload (username * / password *) and with an injected absolute-true filter, without knowing any real credentials
- writing a blind boolean extraction script that recovers a secret directory attribute one character at a time through substring filters like (description=S*), (description=Se*), using only the app's found / not-found response as an oracle
- understanding why userPassword hashes are NOT substring-extractable this way, and choosing a realistic readable attribute as the exfil target instead
- building a LAYERED defense: escape every assertion value per RFC 4515 (\2a \28 \29 \5c \00), stop embedding the password in the filter by switching to a bind-then-search flow, and connect with a least-privilege service account
- judging WHY blocklisting the '*' character is a fragile fix and escaping at the trust boundary plus a bind-based auth flow is the durable one
Steps in this lab
- What LDAP injection actually is (one breath)
- When you'd reach for this — and when NOT to
- Stand up a throwaway directory
- Build the vulnerable login (the bug in 3 lines)
- Attack 1 — bypass the login with a wildcard, then an absolute-true filter
- Attack 2 — steal a secret attribute, one character at a time (blind)
- The judgment: why blocklisting '*' is the wrong instinct
- Fix it — escape, bind-then-search, least privilege
- The way a pro leaves it — and where LDAP injection still bites