kerberos的基本原理以及SPN掃描的內(nèi)容是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
創(chuàng)新互聯(lián)長期為成百上千家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為黃埔企業(yè)提供專業(yè)的做網(wǎng)站、成都網(wǎng)站設計,黃埔網(wǎng)站改版等技術服務。擁有10余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
Kerberos 是一種由 MIT(麻省理工大學)提出的一種網(wǎng)絡身份驗證協(xié)議。它旨在通過使用密鑰加密技術為客戶端/服務器應用程序提供強身份驗證。
在了解 Kerberos 的過程中,發(fā)現(xiàn)很多網(wǎng)站上的相關文章有一些是機器直接翻譯過來的,也有一些寫的比較優(yōu)秀的文章,但是實操性比較弱,可能第一次了解 Kerberos 的同學會不知道怎么上手。所以本文主要是通過更詳細的實驗結(jié)合原理來說明與 Kerberos 相關的一些攻擊手法。
本文將分為三篇。第一篇也就是這一篇的內(nèi)容主要包括域環(huán)境和 Kerberos 協(xié)議的說明以及 Kerberoasting 的攻擊方式。第二篇主要包括 MS14068 漏洞和 Kerberos 票據(jù)的利用說明。第三篇的內(nèi)容主要說明關于 Kerberos 委派的攻擊方式及原理。
由于 Kerberos 主要是用在域環(huán)境下的身份認證協(xié)議,所以在說之前先說下域環(huán)境的一些概念。首先域的產(chǎn)生是為了解決企業(yè)內(nèi)部的資源管理問題,比如一個公司就可以在網(wǎng)絡中建立一個域環(huán)境,更方便內(nèi)部的資源管理。在一個域中有域控、域管理員、普通用戶、主機等等各種資源。
在下圖中 YUNYING.LAB 為其他兩個域的根域,NEWS.YUNYING.LAB 和 DEV.YUNYING.LAB 均為 YUNYING.LAB 的子域,這三個域組成了一個域樹。子域的概念可以理解為一個集團在不同業(yè)務上分公司,他們有業(yè)務重合的點并且都屬于 YUNYING.LAB 這個根域,但又獨立運作。同樣 TEST.COM 也是一個單獨的域樹,兩個域樹 YUNYING.LAB 和 TEST.COM 組合起來被稱為一個域林。
本文就以根域為 YUNYING.LAB 的這個域來演示,YUNYING.LAB 的域控是 DC.YUNYING.LAB,子域 NEWS.YUNYING.LAB 和 DEV.YUNYING.LAB 的域控分別為 NEWSDC.NEWS.YUNYING.LAB 和 DEVDC.DEV.YUNYING.LAB。
上面說的都是 FQDN(FullyQualified Domain Name) 名稱,也就是全限定域名,是同時包含主機名和域名的名稱。
例:DC.YUNYING.LAB 中 DC 為主機名,域名為 YUNYING.LAB,那他的 FQDN 名稱就是 DC.YUNYING.LAB。
本域中采用的操作系統(tǒng)為 Windows Server 2008 R2+Windows 7。
在 Kerberos 認證中,最主要的問題是如何證明「你是你」的問題,如當一個 Client 去訪問 Server 服務器上的某服務時,Server 如何判斷 Client 是否有權(quán)限來訪問自己主機上的服務,同時保證在這個過程中的通訊內(nèi)容即使被攔截或篡改也不影響通訊的安全性,這正是 Kerberos 解決的問題。在域滲透過程中 Kerberos 協(xié)議的攻防也是很重要的存在。
在 Kerberos 協(xié)議中主要是有三個角色的存在:
1. 訪問服務的 Client;
2. 提供服務的 Server;
3.KDC(Key Distribution Center)密鑰分發(fā)中心。
其中 KDC 服務默認會安裝在一個域的域控中,而 Client 和 Server 為域內(nèi)的用戶或者是服務,如 HTTP 服務,SQL 服務。在 Kerberos 中 Client 是否有權(quán)限訪問 Server 端的服務由 KDC 發(fā)放的票據(jù)來決定。
如果把 Kerberos 中的票據(jù)類比為一張火車票,那么 Client 端就是乘客,Server 端就是火車,而 KDC 就是就是車站的認證系統(tǒng)。如果 Client 端的票據(jù)是合法的(由你本人身份證購買并由你本人持有)同時有訪問 Server 端服務的權(quán)限(車票對應車次正確)那么你才能上車。當然和火車票不一樣的是 Kerberos 中有存在兩張票,而火車票從頭到尾只有一張。
由上圖中可以看到 KDC 又分為兩個部分:
Authentication Server:AS 的作用就是驗證 Client 端的身份(確定你是身份證上的本人),驗證通過就會給一張 TGT(Ticket Granting Ticket)票給 Client。
Ticket Granting Server:TGS 的作用是通過 AS 發(fā)送給 Client 的票(TGT)換取訪問 Server 端的票(上車的票 ST)。ST(ServiceTicket)也有資料稱為 TGS Ticket,為了和 TGS 區(qū)分,在這里就用 ST 來說明。
KDC 服務框架中包含一個 KRBTGT 賬戶,它是在創(chuàng)建域時系統(tǒng)自動創(chuàng)建的一個賬號,你可以暫時理解為他就是一個無法登陸的賬號,在發(fā)放票據(jù)時會使用到它的密碼 HASH 值。
當 Client 想要訪問 Server 上的某個服務時,需要先向 AS 證明自己的身份,然后通過 AS 發(fā)放的 TGT 向 Server 發(fā)起認證請求,這個過程分為三塊:
The Authentication Service Exchange:Client 與 AS 的交互;
The Ticket-Granting Service (TGS) Exchange:Client 與 TGS 的交互;
The Client/Server Authentication Exchange:Client 與 Server 的交互。
(1)TheAuthentication Service Exchange
KRB_AS_REQ
Client->AS:發(fā)送 Authenticator1(Client 密碼加密 TimeStamp)
第一步 Client 先向 KDC 的 AS 發(fā)送 Authenticator1,內(nèi)容為通過 Client 密碼 Hash 加密的時間戳、ClientID、網(wǎng)絡地址、加密類型等內(nèi)容。
KRB_AS_REP
AS-> Client:發(fā)送 Client 密碼加密的 sessionkey-as 和票據(jù) TGT(KRBTGT HASH 加密的 sessionkey-as 和 TimeStamp)
在 KDC 中存儲了域中所有用戶的密碼 HASH,當 AS 接收到 Client 的請求之后會根據(jù) KDC 中存儲的密碼來解密,解密成功并且驗證信息。驗證成功后返回給 Client 由 Client 密碼 HASH 加密的 sessionkey-as 和 TGT(由 KRBTGT HASH 加密的 sessionkey-as 和 TimeStamp 等信息)。
(2)TheTicket-Granting Service (TGS) Exchange
KRB_TGS_REQ
Client ->TGS 發(fā)送 Authenticator2 (sessionkey-as 加密 TimeStamp) 和票據(jù) TGT(KRBTGT HASH 加密的 sessionkey-as 和 TimeStamp)
Client 接收到了加密后的 Sessionkey-as 和 TGT 之后,用自身密碼解密得到 Sessionkey-as,TGT 是由 KDC 密碼加密,Client 無法解密。這時 Client 再用 Sessionkey-as 加密 TimeStamp 和 TGT 一起發(fā)送給 KDC 中的 TGS(TicketGranting Server)票據(jù)授權(quán)服務器換取能夠訪問 Server 的票據(jù)。
KRB_TGS_REP
TGS-> Client 發(fā)送 密文 1(sessionkey-as 加密 sessionkey-tgs) 和 票據(jù) ST(Server 密碼 HASH 加密 sessionkey-tgs)
TGS 收到 Client 發(fā)送過來的 TGT 和 Sessionkey-as 加密的 TimeStamp 之后,首先會檢查自身是否存在 Client 所請求的服務。如果服務存在,則用 KRBTGT 密碼解密 TGT。一般情況下 TGS 會檢查 TGT 中的時間戳查看 TGT 是否過期,且原始地址是否和 TGT 中保存的地址相同。驗證成功之后將用 sessionkey-as 加密的 sessionkey-tgs 和 Server 密碼 HASH 加密的 Sessionkey-tgs 發(fā)送給 Client。
(3)TheClient/Server Authentication Exchange
KRB_AP_REQ
Client ->Server 發(fā)送 Authenticator3(sessionkey-tgs 加密 TimeStamp) 和票據(jù) ST(Server 密碼 HASH 加密 sessionkey-tgs)
Client 收到 sessionkey-as 加密的 sessionkey-tgs 和 Server 密碼 HASH 加密的 sessionkey-tgs 之后用 sessionkey-as 解密得到 sessionkey-tgs,然后把 sessionkey-tgs 加密的 TimeStamp 和 ST 一起發(fā)送給 Server。
KRB_AP_REP
Server-> Client
server 通過自己的密碼解密 ST,得到 sessionkey-tgs, 再用 sessionkey-tgs 解密 Authenticator3 得到 TimeStamp,驗證正確返回驗證成功。
這就是 Kerberos 認證的流程,如果還想知道更詳細的信息可以參考下面鏈接。
https://tools.ietf.org/html/rfc4120.html
在 Kerberos 最初設計的幾個流程里說明了如何證明 Client 是 Client 而不是由其他人來冒充的,但并沒有聲明 Client 有沒有訪問 Server 服務的權(quán)限,因為在域中不同權(quán)限的用戶能夠訪問的資源是有區(qū)別的。
所以微軟為了解決這個問題在實現(xiàn) Kerberos 時加入了 PAC 的概念,PAC 的全稱是 Privilege Attribute Certificate(特權(quán)屬性證書)。可以理解為火車有一等座,也有二等座,而 PAC 就是為了區(qū)別不同權(quán)限的一種方式。
(1)PAC 的實現(xiàn)
當用戶與 KDC 之間完成了認證過程之后,Client 需要訪問 Server 所提供的某項服務時,Server 為了判斷用戶是否具有合法的權(quán)限需要將 Client 的 User SID 等信息傳遞給 KDC,KDC 通過 SID 判斷用戶的用戶組信息,用戶權(quán)限等,進而將結(jié)果返回給 Server,Server 再將此信息與用戶所索取的資源的 ACL 進行比較,最后決定是否給用戶提供相應的服務。
PAC 會在 KRB_AS_REP 中 AS 放在 TGT 里加密發(fā)送給 Client,然后由 Client 轉(zhuǎn)發(fā)給 TGS 來驗證 Client 所請求的服務。
在 PAC 中包含有兩個數(shù)字簽名 PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM,這兩個數(shù)字簽名分別由 Server 端密碼 HASH 和 KDC 的密碼 HASH 加密。
同時 TGS 解密之后驗證簽名是否正確,然后再重新構(gòu)造新的 PAC 放在 ST 里返回給客戶端,客戶端將 ST 發(fā)送給服務端進行驗證。
(2)Server 與 KDC
PAC 可以理解為一串校驗信息,為了防止被偽造和串改,原則上是存放在 TGT 里,并且 TGT 由 KDC hash 加密。同時尾部會有兩個數(shù)字簽名,分別由 KDC 密碼和 server 密碼加密,防止數(shù)字簽名內(nèi)容被篡改。
同時 PAC 指定了固定的 User SID 和 Groups ID,還有其他一些時間等信息,Server 的程序收到 ST 之后解密得到 PAC 會將 PAC 的數(shù)字簽名發(fā)送給 KDC,KDC 再進行校驗然后將結(jié)果已 RPC 返回碼的形式返回給 Server。
服務主體名稱(SPN:ServicePrincipal Names)是服務實例(可以理解為一個服務,比如 HTTP、MSSQL)的唯一標識符。Kerberos 身份驗證使用 SPN 將服務實例與服務登錄帳戶相關聯(lián)。如果在整個林或域中的計算機上安裝多個服務實例,則每個實例都必須具有自己的 SPN。如果客戶端可能使用多個名稱進行身份驗證,則給定服務實例可以具有多個 SPN。SPN 始終包含運行服務實例的主機的名稱,因此服務實例可以為其主機的每個名稱或別名注冊 SPN。
如果用一句話來說明的話就是如果想使用 Kerberos 協(xié)議來認證服務,那么必須正確配置 SPN。
在 SPN 的語法中存在四種元素,兩個必須元素和兩個額外元素,其中
例:
如果我想把域中一臺主機 S2 中的 MSSQL 服務注冊到 SPN 中則可以使用命令:
Setspn-A MSSQLSvc/s2.yunying.lab:1433 tsvc
注冊成功之后可以通過下面兩個命令來查看已經(jīng)注冊的 SPN。
setspn –q */* setspn -T yunying.lab –q */*
SPN 在其注冊的林中必須是唯一的。如果它不唯一,則身份驗證將失敗。
在注冊 SPN 時,可以使用 NetBIOS 名稱,如 s2。也可以使用 FQDN(FullyQualified Domain Name 全限定域名),如 s2.yunying.lab。有可能存在某一種名稱注冊的 SPN 不能成功訪問的情況,如果沒有配置正確可以換一種名稱試一試。
一般情況下基于主機的服務會省略后面兩個組件,格式為
MSSQLSvc/s2.yunying.lab
如果服務使用非默認端口或者此主機存在多個服務實例的情況下,需要包括端口號或服務名:
MSSQLSvc/ s2.yunying.lab:1433
在了解了 Kerberos 和 SPN 之后我們可以通過 SPN 來獲取我們想要的信息,比如想知道域內(nèi)哪些主機安裝了什么服務,我們就不需要再進行批量的網(wǎng)絡端口掃描。在一個大型域中通常會有不止一個的服務注冊 SPN,所以可以通過「SPN 掃描」的方式來查看域內(nèi)的服務。相對于通常的網(wǎng)絡端口掃描的優(yōu)點是不用直接和服務主機建立連接,且隱蔽性更高。
(1) 掃描工具
掃描工具有多種,下面挑選幾種較為常見的工具來說明一下:
powershell 腳本使用之前使用 Import-module 命令先加載。
Discover-PSMSSQLServers:
Discover-PSMSSQLServers 是 Powershell-AD-Recon 工具集中的一個工具,用來查詢已經(jīng)注冊了的 MSSQL 類型的 SPN。
GetUserSPNs:
GetUserSPNs 是 Kerberoast 工具集中的一個 powershell 腳本,用來查詢域內(nèi)注冊的 SPN。
PowerView:
PowerView 是由 Will Schroeder(https://twitter.com/harmj0y)開發(fā)的 Powershell 腳本,在 Powersploit 和 Empire 工具里都有集成,PowerView 相對于上面幾種是根據(jù)不同用戶的 objectsid 來返回,返回的信息更加詳細。
還有一些其他的腳本,使用方法基本類似,可以自己選擇合適的工具使用,本文使用的工具會在文章底部標注下載鏈接。
(2) 原理說明
在 SPN 掃描時我們可以直接通過腳本,或者命令去獲悉內(nèi)網(wǎng)已經(jīng)注冊的 SPN 內(nèi)容。那如果想了解這個過程是如何實現(xiàn)的,就需要提到 LDAP 協(xié)議。
LDAP 協(xié)議全稱是 LightweightDirectory Access Protocol,一般翻譯成輕量目錄訪問協(xié)議。是一種用來查詢與更新 Active Directory 的目錄服務通信協(xié)議。AD 域服務利用 LDAP 命名路徑(LDAP naming path)來表示對象在 AD 內(nèi)的位置,以便用它來訪問 AD 內(nèi)的對象。
LDAP 數(shù)據(jù)的組織方式:
更直觀的說可以把 LDAP 協(xié)議理解為一個關系型數(shù)據(jù)庫,其中存儲了域內(nèi)主機的各種配置信息。
在域控中默認安裝了 ADSI 編輯器,全稱 ActiveDirectory Service Interfaces Editor (ADSI Edit),是一種 LDAP 的編輯器,可以通過在域控中運行 adsiedit.msc 來打開(服務器上都有,但是只有域控中的有整個域內(nèi)的配置信息)。
通過 adsiedit.msc 我們可以修改和編輯 LADP,在 SPN 查詢時實際上就是查詢 LADP 中存儲的內(nèi)容。
比如在我們是實驗環(huán)境域 YUNYING.LAB 中,存在名為 svcserver 的一個 OU(OrganizationUnit,可以理解為一個部門,如開發(fā)部、財務部等等),其中包含了 tsvc 這個用戶,從用戶屬性中可以看到 tsvc 注冊過的 SPN 內(nèi)容。
當我們在一臺主機執(zhí)行
setspn -T yunying.lab -q */*
命令查詢域內(nèi) SPN 時,通過抓包可以看到正是通過 LDAP 協(xié)議向域控中安裝的 LDAP 服務查詢了 SPN 的內(nèi)容。
所以其實那些 Powershell 腳本其實主要就是通過查詢 LDAP 的內(nèi)容并對返回結(jié)果做一個過濾,然后展示出來。
在前面介紹 Kerberos 的認證流程時說到,在 KRB_TGS_REP 中,TGS 會返回給 Client 一張票據(jù) ST,而 ST 是由 Client 請求的 Server 端密碼進行加密的。當 Kerberos 協(xié)議設置票據(jù)為 RC4 方式加密時,我們就可以通過爆破在 Client 端獲取的票據(jù) ST,從而獲得 Server 端的密碼。
下圖為設置 Kerberos 的加密方式,在域中可以在域控的「組策略管理」中進行設置:
設置完成之后運行里輸入「gpupdate」刷新組策略,策略生效。
Kerberoasting 這種攻擊方式最初應該是由 TimMedin(https://twitter.com/TimMedin)提出,下面我們通過實驗來進行演示。
實驗環(huán)境:
域:YUNYING.LAB
域控:WindowsServer 2008 R2 x64(DC)
域內(nèi)主機:Windows7 x64(s1):用戶 ts1
域內(nèi)主機:Windows Server2008 R2 x64(s2):用戶 tsvc
所需工具:
Kerberoast 工具包
Mimikatz
攻擊流程:
一、在域內(nèi)主機 s1 中通過 Kerberoast 中的 GetUserSPNs.ps1 進行 SPN 掃描。
也可以使用 GetUserSPNs.vbs 工具。
二、根據(jù)掃描出的結(jié)果使用微軟提供的類 KerberosRequestorSecurityToken 發(fā)起 kerberos 請求,申請 ST 票據(jù)。
(這個類的詳情可以參考https://docs.microsoft.com/en-us/dotnet/api/system.identitymodel.tokens.kerberosrequestorsecuritytoken?redirectedfrom=MSDN&view=netframework-4.7.2)
PS C:\> Add-Type -AssemblyNameSystem.IdentityModelPS C:\> New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/s2:1433"
可以看到這個過程通過 AS-REQ、AS-REP、TGS-REQ、TGS-REP 這四個認證流程,獲取到 RC4 方式加密的票據(jù)。
三、Kerberos 協(xié)議中請求的票據(jù)會保存在內(nèi)存中,可以通過 klist 命令查看當前會話存儲的 kerberos 票據(jù)。
使用 mimikatz 導出。
使用 kerberoast 工具集中的 tgsrepcrack.py 工具進行離線爆破,成功得到 tsvc 賬號的密碼 admin1234!
實驗環(huán)境:
域:YUNYING.LAB
域控:WindowsServer 2008 R2 x64(DC)
域內(nèi)主機:Windows7 x64(s1):用戶 ts1
域內(nèi)主機:WindowsServer 2008 R2 x64(s2):用戶 tsvc
所需工具:
Invoke-Kerberoast.ps1
HashCat
攻擊流程:
在之前的 Kerberoasting 中需要通過 mimikatz 從內(nèi)存中導出票據(jù),Invoke-Kerberoast 通過提取票據(jù)傳輸時的原始字節(jié),轉(zhuǎn)換成 John the Ripper 或者 HashCat 能夠直接爆破的字符串。
環(huán)境不變,在 s1 主機上使用 Invoke-Kerberoast 腳本 (這里使用的是 Empire 中的 Invoke-Kerberoast.ps1)。
Invoke-kerberoast -outputformat hashcat |fl
這里–outputformat 參數(shù)可以指定輸出的格式,可選 John the Ripper 和 Hashcat 兩種格式,這里以 Hashcat 做演示。
這個腳本申請訪問的是 MSSQLSvc/s2.yunying.lab:1433 這個 SPN。查看數(shù)據(jù)包可以看到 Invoke-Kerberoast 輸出的 Hash 值就是 TGS-REP 中返回的票據(jù)內(nèi)容,然后拼接成了 Hashcat 可以直接爆破的格式(以$krb5tgs$23*開頭的)。
把內(nèi)容保存至文檔,也可以直接重定向到 TXT 文件:
PS C:> Invoke-Kerberoast-Outputformat Hashcat | fl > test1.txt
二、使用 HASHCAT 工具進行破解:
PSC:> hashcat64.exe –m 13100 test1.txt password.list --force
可以看到這里已經(jīng)離線破解成功,輸出了 s2 的密碼 admin1234!。在這里–m 表示選擇不同的加密類型,其中 13100 對應的是 Kerberos 5 TGS-REP 類型的密文。
Hashcat 能爆破的類型非常多,還有 NTLM HASH 等,更多的 Hashcat 的類型可以參考:https://hashcat.net/wiki/doku.php?id=example_hashes
最初進行這個實驗的時候是直接在 GitHub 上搜索的 Invoke-kerberoast,當時下載的是https://github.com/malachitheninja/Invoke-Kerberoast這個地址的,但是下載完之后發(fā)現(xiàn)這個地址的工具并不能正常使用,查看代碼發(fā)現(xiàn)在字符串拼接時格式的問題,輸出的內(nèi)容并不符合 Hashcat 的格式。然后直接使用了 Empire 中的 Invoke-kerberoast.ps1 腳本(下載地址: https://github.com/EmpireProject/Empire)。下面就拿這個腳本來說明。
在 Invoke-kerberoast 中通過兩個關鍵函數(shù)看腳本執(zhí)行的主要流程,一個是 function Invoke-Kerberoast {} 一個是 functionGet-DomainSPNTicket {}。
首先在 Invoke-Kerberoast 函數(shù)中通過腳本中的函數(shù) Get-DomainUser 查詢組內(nèi)所有用戶 LDAP 庫中存儲的內(nèi)容,并去除 krbtgt 之后通過管道符傳給 Get-DomainSPNTicket。
Get-DomainUser 輸出的值(-erroraction"Silentlycontinue"消除 powershell 中的紅字告警,也可以直接去掉):
函數(shù) Get-DomainSPNTicket 在接收到 Get-DomainUser 的輸出結(jié)果后提取 SPN(ServicePrincipalName)字段的值,然后取其中的第一個賦值給變量 UserSPN。我們在代碼中添加 echo 語句,然后再執(zhí)行可以看到本次的結(jié)果選取了 SPN 列表中的第一條 MSSQLSvc/s2:SQLEXPRESS。
通過 KerberosRequestorSecurityToken 類的 GetRequest() 函數(shù)發(fā)起 kerberos 請求。隨后通過匹配返回值,提取票據(jù)內(nèi)容。
將提取的票據(jù)的值組合成 Hashcat 要求的格式之后賦值給變量 HashFormat,也就是最終我們可以用 Hashcat 或者 John theRipper 來爆破的值。
同樣,上圖框中的變量$Etype 的值是 23,實際上就是 RC4 加密算法的代號。
總結(jié)下來 Kerberoasting 的本質(zhì)是通過破解在 Kerberos 認證流程中的 KRB_TGS_REP 這個過程中 TGS 返回給 Client 的票據(jù)內(nèi)容來進行密碼的獲取,并且這種方式是離線爆破,過程較為隱蔽。
關于kerberos的基本原理以及SPN掃描的內(nèi)容是什么問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關知識。