理解LDAP與LDAP注入


理解LDAP與LDAP注入

0x01 LDAP簡介

查閱了一些網上的資料,讀了好久還是覺得理解起來很困難,感覺還是不夠干,之后看到的一個博客http://www.chinaunix.net/old_jh/49/593660.html的,覺得寫的相當不錯,摘錄了些也說說自己的理解吧,有錯誤的希望大家指正。
LDAP,輕量目錄訪問協議

|dn :一條記錄的位置|
|dc :一條記錄所屬區域|
|ou :一條記錄所屬組織|
|cn/uid:一條記錄的名字/ID|

此處我更喜歡把LDAP和 數據庫類比起來,我是直接把LDAP看成是一個主要用於查詢的數據庫。數據庫用“表”來存數據,LDAP用“樹”來存數據。數據庫主要是三個DB,TABLE,ROW來定位一條記錄,而LDAP首先要說明是哪一棵樹dc,然后是從樹根到目的所經過的所有“分叉”, ou(group),最后就是目標的名字,例如UID等等。
具體到如何定義如下:

dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=waibo,dc=com
其中樹根是dc=waibo,dc=com,分叉ou=bei,ou=xi,ou=dong,目標cn=honglv

注意要把“cn=stan,ou=linux,ou=computer,dc=ourschool,dc=org”看成是一個整體,它只是屬性dn的值

具體的一條記錄如下:

dn:cn=stan,ou=linux,ou=computer,dc=ourschool,dc=org
objectClass:organizationalPerson
cn:stan
cn:小刀
sn:小刀
description:a good boy

(保存成LDIF文件,可以導入到LDAP數據庫中)

關於安裝配置LDAP,貼一個網址
http://www.mandrakesecure.net/en/docs/ldap-auth.php

0x02 LDAP基本語法

  • =(等於)
    查找“名“屬性為“John”的所有對象,可以使用:
(givenName=John) 

  這會返回“名”屬性為“John”的所有對象。圓括號是必需的,以便強調 LDAP 語句的開始和結束。

  • &(邏輯與)
    如果具有多個條件並且希望全部條件都得到滿足,則可使用此語法。例如,如果希望查找居住在 Dallas 並且“名”為“John”的所有人員,可以使用:
(&(givenName=John)(l=Dallas))

請注意,每個參數都被屬於其自己的圓括號括起來。整個 LDAP 語句必須包括在一對主圓括號中。操作符 & 表明,只有每個參數都為真,才會將此篩選條件應用到要查詢的對象。

  • !(邏輯非)
    此操作符用來排除具有特定屬性的對象。假定您需要查找“名”為“John”的對象以外的所有對象。則應使用如下語句:
(!givenName=John)

此語句將查找“名”不為“John”的所有對象。請注意:! 操作符緊鄰參數的前面,並且位於參數的圓括號內。由於本語句只有一個參數,因此使用圓括號將其括起以示說明

  • *(通配符)

可使用通配符表示值可以等於任何值。使用它的情況可能是:您希望查找具有職務頭銜的所有對象。為此,可以使用:

(title=*)

這會返回“title”屬性包含內容的所有對象。另一個例子是:您知道某個對象的“名”屬性的開頭兩個字母是“Jo”。那么,可以使用如下語法進行查找:

(givenName=Jo*)

這會返回“名”以“Jo”開頭的所有對象。

高級用法eg:

您需要一個篩選條件,用來查找居住在 Dallas 或 Austin,並且名為“John”的所有對象。使用的語法應當是:

(&(givenName=John)(|(l=Dallas)(l=Austin)))

0x03 LDAP注入

LDAP注入攻擊和SQL注入攻擊相似,因此接下來的想法是利用用戶引入的參數生成LDAP查詢。一個安全的Web應用在構造和將查詢發送給服務器前應該凈化用戶傳入的參數。在有漏洞的環境中,這些參數沒有得到合適的過濾,因而攻擊者可以注入任意惡意代碼。
使用得最廣泛的LDAP:ADAM和OpenLDAP,下面的結論將會致代碼注入:

3.1 引入

(attribute=value)

如果過濾器用於構造查詢單缺少邏輯操作符,如value)(injected_filter ,瞬間導致產生了兩個過濾器,

(attribute=value)(injected\_filter)

通常,在OpenLDAP實施中,第二個過濾器會被忽略,只有第一個會被執行。
而在ADAM中,有兩個過濾器的查詢是不被允許的,因而這個注入毫無用處。

(|(attribute=value)(second_filter)) or (&(attribute=value)(second_filter))

如果第一個用於構造查詢的過濾器有邏輯操作符,形如value)(injected_filter)的注入會變成如下過濾器:

(&(attribute=value)(injected_filter)) (second_filter)。

雖然過濾器語法上並不正確,OpenLDAP還是會從左到右進行處理,忽略第一個過濾器閉合后的任何字符。

但是有的瀏覽器會進行檢查,檢查過濾器是否正確,這種情況下value)(injected_filter))(&(1=0,於是就出現了下述payload

(&(attribute=value)(injected_filter))(&(1=0)(second_filter))

既然第二個過濾器會被LDAP服務器忽略,有些部分便不允許有兩個過濾器的查詢。這種情況下,只能構建一個特殊的注入以獲得單個過濾器的LDAP查詢,如value)(injected_filter得到

(&(attribute=value)(injected_filter)(second_filter))

3.2 AND注入

這種情況,應用會構造由”&”操作符和用戶引入的的參數組成的正常查詢在LDAP目錄中搜索,例如:

(&(parameter1=value1)(parameter2=value2))

這里Value1和value2是在LDAP目錄中搜索的值,攻擊者可以注入代碼,維持正確的過濾器結構但能使用查詢實現他自己的目標。

3.2.1 繞過訪問控制

一個登陸頁有兩個文本框用於輸入用戶名和密碼,過濾器如下:

(&(USER=Uname)(PASSWORD=Pwd)) 

如果攻擊者輸入一個有效地用戶名,如r00tgrok,然后再這個名字后面注入恰當的語句,password檢查就會被繞過。輸入Uname=slisberger)(&)),得到如下

(&(USER= slisberger)(&)(PASSWORD=Pwd))

LDAP服務器只處理第一個過濾器,即僅查詢(&(USER=slidberger)(&))得到了處理。這個查詢永真,故成功繞過

3.2.2 權限提升

現假設下面的查詢會向用戶列舉出所有可見的低安全等級文檔:

(&(directory=document)(security_level=low)) 

這里第一個參數document是用戶入口,low是第二個參數的值。如果攻擊者想列舉出所有可見的高安全等級的文檔,他可以利用如下的注入:document)(security_level=*))(&(directory=documents
得到

(&(directory=documents)(security_level=*))(&(direcroty=documents)(security_level=low))

LDAP服務器僅會處理第一個過濾器而忽略第二個,因而只有下面的查詢會被處理:

(&(directory=documents)(security_level=*))

結果就是,所有安全等級的可用文檔都會列舉給攻擊者

3.3 OR注入

這種情況,應用會構造由”|”操作符和用戶引入的的參數組成的正常查詢在LDAP目錄中搜索,例如:

(|(parameter1=value1)(parameter2=value2))

這里Value1和value2是在LDAP目錄中搜索的值,攻擊者可以注入代碼,維持正確的過濾器結構但能使用查詢實現他自己的目標。

具體的注入方式和AND差不太多,不予詳述。

3.4 LDAP盲注

3.4.1 AND盲注

假設一個Web應用想從一個LDAP目錄列出所有可用的Epson打印機,錯誤信息不會返回,應用發送如下的過濾器:

(&(objectClass=printer)(type=Epson*))

正確的過濾器為:

(&(objectClass=printer)(type=Epson*))

而當注入)(objectClass=))(&(objectClass=void時得到

(&(objectClass=*)(objectClass=*))(&(objectClass=void)(type=Epson*))

執行第一個,過濾器objectClass=*總是返回一個對象。當圖標被顯示時響應為真,否則為假。
這樣我們就可以猜第二個括號的objectclass字段有些什么內容了。
LDAP盲注技術讓攻擊者使用基於TRUE/FALSE的技術訪問所有的信息。

3.4.2 OR盲注

這種情況下,用於推測想要的信息的邏輯與AND是相反的,因為使用的是OR邏輯操作符。同樣不予詳述。

3.4.3 盲注深入

攻擊者可以使用字母、數字搜索提取屬性的值,這個想法的關鍵在於將一個復雜的值轉化為TRUE/FALSE列表。這個機制,通常稱為booleanization,大意是二值化吧,圖十二概括了該機制,可用於不同的方式。
假設攻擊者想知道department屬性的值,處理如下:

(&(idprinter=HPLaserJet2100)(department=a*))(object=printer))
(&(idprinter=HPLaserJet2100)(department=f*))(object=printer))
(&(idprinter=HPLaserJet2100)(department=fa*))(object=printer))

如此根據返回的不同結果猜解是否正確,和MYSQL盲注類似。
同樣,攻擊者可以使用字符集削減技術減少獲得信息所需的請求數,為完成這一點,他使用通配符測試給定的字符在值中是否為anywhere

(&(idprinter=HPLaserJet2100)(department=*b*))(object=printer))
(&(idprinter=HPLaserJet2100)(department=*n*))(object=printer))

這樣子可以看department中是否有b和n,巧用可以加速猜解過程,當然一般肯定都是寫腳本猜解

0x04 防御LDAP注入

總而言之,我們看到圓括號、星號、邏輯操作符、關系運操作符在應用層都必須過濾。
無論什么時候,只要可能,構造LDAP搜索過濾器的值在發送給LDAP服務器查詢之前都要用應用層有效地值列表來核對。正則表達式替換掉就可以了。

0x05 參考

http://drops.wooyun.org/tips/967
http://www.chinaunix.net/old_jh/49/593660.html
http://blog.sina.com.cn/s/blog_6151984a0100ey3z.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM