<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    由淺入深理解Kerberos協議

    VSole2022-04-29 14:47:40

    本文是很久之前做的筆記,今天有空又梳理了一下,分享出來。如果有錯誤或疏漏,歡迎留言指出。

    Kerberos是一種基于票據的、集中式的網絡認證協議,適用于C/S模型,由MIT開發和實現(http://web.mit.edu/kerberos/dist/)。

    這里所謂的認證,就是保證使用票據(Ticket)的用戶必須是票據中指定的用戶。

    簡單回憶一下,密碼學涉及機密性、完整性、認證性(實體認證+消息認證)、可用性、不可否認性。kerberos認證主要為了實現認證性中的實體認證。當然,每次交互發送的消息都會包含checksum,并被對稱加密(也可以配置為非對稱加密),保證了完整性和機密性。

    1. Kerberos認證

    Kerberos提供了單點登錄(SSO,Single Sign-On)機制,對于每個會話只需向服務進行一次自我驗證,即可自動保護該會話過程中所有后續事務的安全。

    整個認證過程涉及3方(所以以三頭犬命名~):客戶端、KDC、服務端(或者說應用服務器AP,比如web服務器)。

    密鑰分發中心KDC (Key Distribution Center)是 Kerberos 的核心組件,默認安裝在域控里,由兩個服務組成:

    AS(Authentication Server),負責用戶信息認證,給客戶端提供TGT(Ticket Granting Tickets,即黃金票據);

    TGS(Ticket Granting Server),向客戶端提供ST(Service Ticket,即白銀票據)和Session Key(服務會話密鑰)。

    還有一個概念叫principal,代表一個用戶唯一的身份,由三部分組成:

    primary,主名稱;

    instance(可選),實例,有則說明是服務主體;

    realm,域。

    以starr/admin@FOOBAR.COM這個kerberos主體為例,

    starr-->primary

    admin-->instance

    FOOBAR.COM-->realm

    完整的認證流程,有客戶端與AS, TGS, AP的3次交互,每次交互,響應包都會包含兩條信息,一條可以用本地密鑰解密,另一條需要轉發。

    1.1 認證流程v1.0


     

    AS_REQ請求內容如下:

    AS_REQ =
        principal_client    // 我是誰
        + principal_server    // AP id, 又叫SPN,service principal name,標識客戶端要訪問的服務
        + nonce             // 隨機數,用來匹配響應
        + Authenticator = encrypt(    // 可譯作[認證因子]
                key=hashUser,     // 用戶的NTLM hash,后續所提到作密鑰的hash都是指NTLM hash
                TimeStamp        // 加密的時間戳,防御重放攻擊,一般5min有效期
            )
    

    這里省略了客戶端主機名、加密類型、隨機數(匹配請求和響應)等信息。

    密鑰所使用的NTLM Hash是Windows的一種基于MD4算法的散列加密算法,前身是LM Hash(LAN Manager Hash)。

    AS收到請求后,會從活動目錄查詢此用戶信息,之后返回的AS_REP響應內容如下:

    AS_REP =
        T1 = encrypt(            //客戶端收到后可以解密
                key = hashUser,        // 使用用戶hash作為加密密鑰
                content = principal_server    // AP id
                    + SessionKeyAP    //用戶與服務的會話密鑰,即Service Session Key
                    + nonce        // 隨機數
            )
        +T2 = encrypt(
                key = hashAP,        // 用AP的hash作為密鑰,轉發給AP后可以解密
                content = principal_client    // 客戶端ID
                    + SessionKeyAP    // 同一個會話密鑰也要轉發給AP
            )
    

    每個域控都有一個 krbtgt賬戶,創建域控時自動生成。

    之所以KDC能用客戶端、服務端的密鑰hash加密數據包,顧名思義,是因為密鑰分發中心(KDC)有所有principal的密鑰hash。AS收到請求后也會用用戶的hash來解密認證因子獲取時間戳,確認請求沒有過期。

    客戶端收到AS的響應后,從AS_REP.T1解密出自己與服務的會話密鑰,并轉發AS_REP.T2給服務, 作為認證:

    AP_REQ =
        T2    // 轉發給AP解密
        + Authenticator =              // 新的認證因子
            encrypt(
                key = SessionKeyAP,  // 客戶端從AS_REP.T1解密出來的會話密鑰
                content = TimeStamp           // AP用來判斷是否過期,默認有效期也是5min
                    + T2_checksum           // 校驗T2完整性
            )
    

    AP用自己的hash解密AP_REQ.T2后,至少要確認以下幾件事:

    (1)用T2.SessionKeyAP會話密鑰解密AP_REQ.Authenticator;

    (2)讀取T2.principal_client,可以理解成KDC說“此人已在我這里認證通過”,需要驗證發送方是否為此人;

    (3)讀取Authenticator.T2_checksum,檢查T2是否被篡改;

    (4)讀取Authenticator.TimeStamp,檢查是否過期。

    到這里已經可以看出,AP不是通過與KDC交互來完成認證,而是通過解密客戶端的請求來進行認證。

    密碼學的認證問題和現實生活中很多場景都非常相似,比如像質檢這樣的第三方權威機構,通過給貨物貼上有類似“檢驗通過”字樣的、高度防偽的標識,來發揮作用。

    AP認證完成后,會發送enc(SessionKeyAP, TimeStamp)作為AP_REP通知客戶端認證完成。這一步是可選的,雙向認證時才會有。

    那么v1.0現在存在的缺陷是什么呢?試想如果要訪問幾個服務,那么客戶端就要多次訪問AS來重復認證,頻繁傳輸用戶的密鑰會增加被竊聽的風險,既不合理也不安全。

    如果使用長時間不變的值作密鑰,比如這里的用戶口令hash,那就可能在某一天被破解,是不安全的,使用臨時密鑰才是正解。

    1.2 認證流程v2.0

    v1.0 域控已經配備了AS,現在要加上TGS,構成完整的KDC。

    可以理解成在景區買那種聯票,用身份證在AS完成身份證明,有效期內去TGS取票口出示聯票,就能取出景區門票(應該還算恰當吧~),這樣就省去了多次認證。

    注意AS和TGS都在域控服務器上,所以流程仍然涉及三方(下面的圖沒有體現出來):

    AS_REQ相比v1.0, 把principal_server換成了tgs,即principal_tgs,也就是用來告訴AS,我要去找TGS服務取票。

    當然AS_REP響應也有了變化(請看注釋部分):

    AS_REP =
        T1 = encrypt(
                key = hashUser,
                content = principal_tgs    // tgs id,告知去哪領票
                    + SessionKeyTGS        // 用戶與TGS的會話密鑰,即Login Session Key
                    + nonce
                    + TGTExpirationTime // TGT默認有效期8小時
            )
        +TGT = encrypt(                // 帶著它去領票
                key = hashKrbtgt ,    // 密鑰用krbtgt賬戶的hash,TGS可以解密
                content = SessionKeyTGS    // 同一個會話密鑰也要轉發給TGS   
                    + principal_client
                    + TGTExpirationTime       
                    + enc(key = hashKrbtgt, PAC)    // pac被krbtgt_hash密鑰加密了兩次,v3.0再提它
            )
    

    客戶端收到響應后,解密AS_REP.T1,并緩存Login Session Key和TGT(統稱為憑證,credentials)。

    這里我將T2改名為TGT,也就是黃金票據。

    然后客戶端向TGS發出請求。再次強調,每次交互,都會收到兩條信息,一條(T1)可以用本地密鑰解密,另一條(TGT)需要轉發。

    TGS_REQ = 
        principal_client
        + principal_server        // AP id,告知TGS我要訪問哪個服務
        + TGT                    // 轉發給TGS解密
        + nonce
        + Authenticator =          // TGS解密TGT后再解密這個認證因子
             encrypt(
                 key = SessionKeyTGS,    // 客戶端從T1解密出來的會話密鑰
                content = TimeStamp        // 驗證TGT是否過期,防止重放
                    + TGT_checksum        // 驗證TGT是否被篡改
             )
    

    這里之所以TGT能被TGS解密,是因為TGS和AS在同一服務器上,數據庫中有Krbtgt用戶的hash,即TGT的加密密鑰。

    TGS用hashKrbtgt解密TGT后,同樣要確認以下幾件事:

    (1)用TGT.SessionKeyTGS解密Authenticator;

    (2)讀取TGT.principal_client,驗證發送方是否為此人;

    (3)讀取Authenticator.TGT_checksum,檢查TGT是否被篡改;

    (4)讀取Authenticator.TimeStamp,檢查是否過期。

    認證完成就到了TGS發放ST(Service/Silver Ticket,即白銀票據)一步了:

    TGS_REP =
        T3 = encrypt(
            key = SessionKeyTGS,    // 客戶端可以用login session key解密
            content = principal_server
                + SessionKeyAP        //  客戶端與AP的會話密鑰, 即Service Session Key
                + nonce
                + STExpirationTime
        )
           + ST= encrypt(        // 白銀票據
            key = hashAP,     //  AP可以解密
            content = SessionKeyAP
                + principal_client
                + enc(key = hashKrbtgt, PAC)    // 源于TGT
                + STExpirationTime
        )
    

    客戶端再次收到兩條信息,一條(T3)用收到AS_REP時緩存的SessionKeyTGS解密,于是得到了與AP的會話密鑰,另一條(ST)轉發給AP:

    AP_REQ =
        ST                                // 轉發白銀票據, 由AP解密
        + Authenticator =                 
             encrypt(
                 key = SessionKeyAP,
                content = principal_client
                    + TimeStamp               // 驗證ST是否過期,防止重放
                    + TGT_checksum        // 驗證ST是否被篡改
             )
    

    AP用自己的hash解密ST后,取出SessionKeyAP,驗收發送方、checksum和時間戳(和TGS_REQ那一步一樣)。認證通過后返給客戶端AP_REP, 告知可以開始愉快地交流了。

    1、2兩步發生在用戶首次登錄時,3、4發生在請求訪問新的服務時。

    1.3 認證流程v3.0(完整)

    KDC(AS+TGS)的角色常常由DC擔任, 現在上圖把AS和TGS合并為DC,簡單提一下AP和DC的交互。

    到第5步,客戶端已經證明自己是自己了,v1.0部分也提到,AP不是通過與KDC交互來完成認證,但AP為了確認憑客戶端的身份,是否有權限訪問服務,就需要向KDC確認。

    再看一下ST的內容,里面有被krbtgt hash加密過的PAC(Privilege Attribute Certificate),即特權訪問證書,包含了當前用戶的SID,用戶組,UNC路徑等信息。它會作為token保留在客戶端與AP的會話中,而AP就是把PAC信息發給KDC來確認的,而KDC會將確認結果通過RPC返回給AP。

    有些服務并沒有驗證PAC這一步。

    2. 抓包

    2.1 環境

    • Windows 2012 R2, 域內IP 192.168.1.1
    • Windows 7 x86 pro, 域內IP 192.168.1.2

    域名:foobar.domain

    域環境的搭建此處就省略了。看下win7上的環境:

    C:\Users\foo>ipconfig /all
     
    Windows IP 配置
     
       主機名  . . . . . . . . . . . . . : win7
       主 DNS 后綴 . . . . . . . . . . . : foobar.domain
       節點類型  . . . . . . . . . . . . : 混合
       IP 路由已啟用 . . . . . . . . . . : 否
       WINS 代理已啟用 . . . . . . . . . : 否
       DNS 后綴搜索列表  . . . . . . . . : foobar.domain
                                           localdomain
    ...
    以太網適配器 本地連接:
       ...
       IPv4 地址 . . . . . . . . . . . . : 192.168.1.2(首選)
       子網掩碼  . . . . . . . . . . . . : 255.255.255.0
       ...
       DNS 服務器  . . . . . . . . . . . : 192.168.1.1
    ...
    C:\Users\foo>whoami
    foobar\foo
    

    Win2012:

    C:\Windows\System32>ipconfig
     
    Windows IP 配置
     
    以太網適配器 Ethernet0:
       ...
       IPv4 地址 . . . . . . . . . . . . : 192.168.1.1
       子網掩碼  . . . . . . . . . . . . : 255.255.255.0
       ...
    

    在win2012上安裝好wireshark,監聽Ethernet0網卡。Win7登錄foo用戶(如已登錄,注銷即可),win2012那邊就會抓到包,停止抓包,過濾條件填kerberos即可。

    PS:真實數據包的結構與上面的偽代碼有差異。

    2.2 與AS的交互

    先看AS請求:

    再看下req-body:

    然后看下響應,先看黃金票據:

    其中,etype加密類型是根據請求包里支持的加密類型來選擇的。

    在ticket下面的enc-part就是用用戶foo的hash加密的與TGS的會話密鑰、隨機數、有效期等信息。

    而上面的padata,類型變成了pA-ETYPE-INFO2,在RFC4120里有詳細描述:

    When the AS server is to include pre-authentication data in a KRB-ERROR or in an AS-REP, it MUST use PA-ETYPE-INFO2, not PA-ETYPE-INFO.

    沒有細究,就不截圖了。

    另外可以記一下,在傳輸層,目標端口是88,就不截圖了。

    2.3 與TGS的交互

    客戶端發出的tgs請求包:

    客戶端收到的tgs的響應包:

    2.4 與AP的交互

    在wireshark列表里是看不見ap-req, ap-rep兩個包的,因為這個交互過程集成在與服務的第一次請求中。為了查看ap-req, 不需要改變wireshark的過濾器,只需要在列表中找一個不是KRB5協議的數據包,里面就會有ap-req和ap-rep。

    比如,DCERPC協議包中的目錄訪問服務:

    響應: 

    這些服務,在前面的tgs-req包的sname字段中都是可以找到的。

    對LDAP協議不太了解,不知道為什么DCERPC和LDAP兩種包里都會有LDAP服務的請求和響應,如果有哪位 師傅知道,歡迎留言賜教。

    其它的,還有SMB協議中的cifs服務請求與響應:

    3. Kerberos一些攻擊方式

    很多攻擊方式我本人其實還沒有實踐過,只是簡單梳理一下。

    3.1 AS-REQ階段

    三種手法:PTH, 用戶枚舉,密碼噴灑。

    PTH

    首先是HASH傳遞攻擊(Pass The Hash, PTH),捕獲用戶的密碼hash來做身份驗證,獲取TGT,橫向訪問其它主機。

    場景:內網滲透中要橫向移動,但獲取不到明文口令。

    域內用戶枚舉及密碼噴灑

    和web爆破原理類似,根據響應包返回碼來判斷是否爆破成功:

    登錄一個不存在的域用戶:

    登錄密碼錯誤:

    當然域策略可以設置密碼嘗試次數,超過則鎖定賬戶。

    針對SPN,也可以枚舉一下,看看目標域有哪些服務。

    3.2 AS-REP階段

    黃金票據

    針對黃金票據的攻擊發生在這一階段。

    因為TGT黃金票據是由krbtgt用戶的hash加密的,所以如果我們獲取了這個hash,就可以用mimikatz偽造任意TGT。

    總共需要以下信息:

    • 要偽造的域用戶(名稱、hash),一般是域管理員;
    • 域名;
    • 域的SID;
    • krbtgt用戶的hash。

    黃金、白銀票據主要為了維持權限,尤其是黃金票據,是后門的萬能鑰匙。

    注意不是為了提權或者橫移。因為如v3.0中AP與DC的交互部分所說,權限是目標賬戶本身、或者所在用戶組決定的。

    此類攻擊方法被稱為票據傳遞攻擊(Pass the Ticket,PtT)。

    AS-REP Roasting

    在剛剛抓的AS-REQ數據包(https://bbs.pediy.com/thread-272145.htm)中,可以看到padata(Pre-Authentication Data)預認證數據,里面包含的數據也可以稱為authenticator,包括加密的時間戳,以及啟動PAC請求。

    其中PAC并不是kerberos本身支持的,而是微軟的擴展,相關漏洞有2014年的MS14-068(CVE-2014-6324)域控提權漏洞(https://docs.microsoft.com/zh-cn/security-updates/Securitybulletins/2014/ms14-068)。

    如果關閉某個用戶的預認證后,AS-REQ.padata就不會有加密的時間戳了,而且即使輸入密碼錯誤,也能收到as-rep:

     

    于是,就可以用Rubeus和hashcat工具進行離線爆破了。

    MS14-068提權漏洞

    漏洞位于 kdcsvc.dll ,允許經過身份驗證的用戶在其獲得的 TGT 中插入任意的 PAC。

    3.3 TGS-REP階段

    Kerberoasting

    域上的任何經過身份驗證的用戶,只要TGT沒問題,就能夠從TGS處根據SPN請求ST,然后進行暴力破解。

    SPN格式:SERVICE/host.name。可以用Windows自帶的SetSPN.exe查詢SPN, 命令為setspn -Q */*。

    之后,可以用mimikatz指定服務目標、導出ST,用tgsrepcrack破解,相關工具有很多。

    白銀票據

    TGS生成的ST雖然只能訪問特定的服務,但不依賴KDC,所以相比偽造黃金票據動靜更小。

    ST用AP的hash加密,如果獲取了這個hash,就可以偽造ST,進而跳過KDC的認證,直接和AP通信。

    總共需要以下信息:

    • 域用戶名稱、hash;
    • 域名;
    • 域的SID;
    • 目標AP的服務名、ntlm hash等。

    其實這也屬于票據傳遞攻擊。

    需要注意,偽造的ST是不帶kdc簽名的,所以如果目標要驗證簽名(也就是V3.0所說的AP與KDC的交互),那就GG了。

    也可以嘗試碰撞一下AP的hash來破解ST,成功率較小(所以更別提破解TGT了)。

    3.4 委派

    英文delegation。

    假設用戶A訪問服務B,請求服務的資源C,但是服務B沒有資源C,那么服務B就需要以用戶A的身份去訪問另外一臺機器去獲取資源C,再響應到用戶A。

    如果服務B的服務賬戶開啟了非約束委派,那么當用戶A訪問服務B的時候,用戶A的TGT會被發送給服務B,服務B就能夠以用戶A的身份去訪問用戶A能夠訪問的任意服務。

    setspn工具可以設置服務賬戶。

    如果我們已經拿到管理員的TGT(PTT),使用mimikatz導入后就可以實現對非約束委派的攻擊。

    Windows2003引入了約束委派,以及兩個Kerberos擴展協議S4u2self和S4u2Proxy:

    S4U2self(service for user to self)使服務B可以代表用戶A向KDC請求一個可轉發的ST;

    S4U2proxy(service for user to proxy)使服務B可以通過可轉發的ST代表用戶A訪問請求目標服務的ST,而不能訪問其它服務。

    這個過程共申請了兩個ST。

    Mimikatz的作者還提供了一個工具叫kekeo,它可以先發起一次AS-REQ請求tgt,再發起兩次TGS-REQ請求兩個ST,那么用mimikatz導入目標ST后就可以實現對約束委派的攻擊。

    4. 參考文章

    Kerberos Protocol Extensions | Microsoft Docs

    https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/2a32282e-dd48-4ad9-a542-609804b02cc9

    Kerberos協議探索系列

    https://www.anquanke.com/post/id/171552

    RFC 4120 - The Kerberos Network Authentication Service (V5) (ietf.org)

    https://datatracker.ietf.org/doc/html/rfc4120/

    Pre-authentication Data | Microsoft Docs

    https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/ae60c948-fda8-45c2-b1d1-a71b484dd1f7

    淺析 Kerberos 認證過程以及黃金票據和白銀票據 | K0rz3n's Blog

    https://bbs.pediy.com/thread-272145.htm

    一文搞定Kerberos - 知乎 (zhihu.com)

    https://zhuanlan.zhihu.com/p/266491528

    內網滲透測試:Kerberos 協議& Kerberos 認證原理 - FreeBuf網絡安全行業門戶

    https://www.freebuf.com/articles/network/273725.html

    Kerberos: An Authentication Service for Computer Networks (isi.edu)

    http://gost.isi.edu/publications/kerberos-neuman-tso.htm

    Windows協議學習-Kerberos協議(上)_白帽子技術/思路_i春秋社區-分享你的技術,為安全加點溫度. (ichunqiu.com)

    https://bbs.ichunqiu.com/thread-61557-1-1.html

    Kerberos從0到1 - 知乎 (zhihu.com)

    https://zhuanlan.zhihu.com/p/420834577

    Kerberos協議探索系列之委派篇 - FreeBuf網絡安全行業門戶

    https://www.freebuf.com/articles/system/198381.html

    kerberostgs
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    kerberos協議從0到1
    2021-10-12 14:26:38
    krbtgt用戶,是系統在創建域時自動生成的一個帳號,其作用是密鑰分發中心的服務賬號,其密碼是系統隨機生成的,無法登錄主機
    RiskySPN是一系列功能強大的PowerShell腳本集合,可以幫助廣大研究人員檢測和濫用跟SPN(服務主體名稱)相關的賬戶。除此之外,該工具不僅可以幫助藍隊研究人員識別存在安全風險的SPN,還可以幫助紅隊研究人員利用Kerberos和活動目錄來實現權限提升。
    kerberos委派詳解
    2021-10-08 14:49:15
    委派域委派是指,將域內用戶的權限委派給服務賬號,使得服務賬號能以用戶權限開展域內活動。服務賬號,域內用戶的一種類型,服務器運行服務時所用的賬號,將服務運行起來并加入域。例如MSSQL Server在安裝時,會在域內自動注冊服務賬號'SqlServiceAccount',這類賬號不能用于交互式登錄。
    攻擊者在獲取到域控權限后,可以利用約束委派或者基于資源的約束委派實現后門,以實現達到維持權限的目的。基于AD Event日志監視對特定 Active Directory 屬性的修改,從而發現可疑的域委派后門。設置約束委派setspn -U -A cifs/test test
    網上已經有很多表哥寫了關于域委派的文章,這里基于自己的理解大概寫了關于委派的認證和利用過程
    本文記錄了一次針對具有二層內網的域環境進行滲透測試的過程,文中涉及了內網域滲透的基本方法、思路和技巧。交替使用了msf、CobaltStrike、frp、chisel、SharpSQLTools等工具,最后通過約束委派拿下了域控。其間運用了很多小工具,文章較長,下面開始此次滲透長途之旅。看到了weblogic的版本,查找下exp,順手先來一波smb信息收集。
    記一次內網靶場學習
    2021-12-15 15:56:44
    記一次內網靶場學習
    list 列舉出當前會話的所有緩存憑證,tgt列出當前會話的tgt信息。
    但由于Msg B是使用 TGS密鑰 加密的,Client無法對其解密。AS響應的消息中有一條是屬于Client的,但另外一條卻屬于TGS
    Kerberos認證介紹Kerberos是一種計算機網絡授權協議,用來在非安全網絡中,對個人通信以安全的手段進行身份認證。這個詞又指麻省理工學院為這個協議開發的一套計算機軟件。而已有了金票后,就跳過AS驗證,不用驗證賬戶和密碼,所以也不擔心域管密碼修改。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类