【安全科普】AD域安全協(xié)議(四)RPC

如駕駛需要遵守交通規(guī)則一般,在網(wǎng)絡(luò)中活動(dòng)的事務(wù),也需要遵守相應(yīng)的規(guī)則,這套“規(guī)則”的具體實(shí)現(xiàn),則通過網(wǎng)絡(luò)上的“協(xié)議”,并且,在不同的應(yīng)用環(huán)境下,有不同的協(xié)議規(guī)范。
AD域中特色功能的實(shí)現(xiàn),主要依賴的協(xié)議有Kerberos、ntlm、ldap、rpc、smb,本次科普系列,我們?yōu)榇蠹以敿?xì)介紹這幾項(xiàng)協(xié)議,幫助大家梳理。

RPC協(xié)議主要用來進(jìn)行遠(yuǎn)程過程調(diào)用,用一句話來概括,就是允許用戶程序調(diào)用服務(wù)器上的函數(shù)進(jìn)行計(jì)算,由此實(shí)現(xiàn)兩者交互。
早先的企業(yè)環(huán)境中,所有的服務(wù)都在一臺(tái)主機(jī)上,就會(huì)導(dǎo)致服務(wù)器負(fù)荷過重,無法保證業(yè)務(wù)的正常運(yùn)作。正因如此,后來企業(yè)就更換了一種思路,將不同服務(wù)分開,分別存放在不同主機(jī)上,暫時(shí)解決了負(fù)荷問題。但是久而久之,這樣的方式也開始顯現(xiàn)弊端,比如當(dāng)用戶需要使用不同服務(wù)器上的服務(wù)協(xié)作來完成任務(wù)時(shí),服務(wù)與服務(wù)之間該如何交互?
這就是RPC要解決的問題,簡(jiǎn)言之,RPC可以允許一臺(tái)機(jī)器上的程序調(diào)用另一臺(tái)機(jī)器上的函數(shù),通過各計(jì)算機(jī)協(xié)作進(jìn)行計(jì)算,以保證用戶任務(wù)順利完成
接下來我們?cè)敿?xì)說說RPC的原理。
# RPC原理 #
同AD域內(nèi)的大多數(shù)協(xié)議一樣,RPC也采用的是請(qǐng)求響應(yīng)模式。通常的請(qǐng)求響應(yīng),只需要客戶端和服務(wù)器直接做交互就行了,但在RPC中,增加了兩個(gè)處理過程,即客戶端存根和服務(wù)器存根。
此存根的作用為:當(dāng)客戶端想調(diào)用服務(wù)器上的某函數(shù)時(shí),需要把客戶端的參數(shù)提供給服務(wù)器。而為了保證參數(shù)的保密、完整、可用和響應(yīng)的高效性,客戶端需要對(duì)傳輸過程做些特殊處理,包括將數(shù)據(jù)序列化、封裝數(shù)據(jù)、尋址、傳遞數(shù)據(jù)等。
如果這一系列復(fù)雜行為都由客戶端來操作,將會(huì)耗時(shí)耗力,所以RPC就建立了一個(gè)存根,讓它來協(xié)調(diào)管理這些過程,減輕客戶端負(fù)擔(dān)。
在存根的作用下,客戶端將參數(shù)遞交給它,后續(xù)只需要等待接收服務(wù)器返回的數(shù)據(jù)就行了。因此,用戶其實(shí)是感受不到這個(gè)跟服務(wù)器交互的過程的,這一切似乎都像在本機(jī)上完成的一樣。

以上內(nèi)容,我們提到存根的一個(gè)重要作用——序列化。
所以,什么是序列化?
客戶端把參數(shù)交給存根后,如果存根直接將參數(shù)交給服務(wù)器,當(dāng)服務(wù)器的系統(tǒng)與客戶端不一樣時(shí),服務(wù)器就不能解析該參數(shù),也無法調(diào)用相應(yīng)函數(shù),等于客戶端也就得不到正確的返回結(jié)果。
為了讓服務(wù)器能正確解析客戶端的參數(shù),我們就需要將參數(shù)轉(zhuǎn)化成服務(wù)器能理解的方式。
在RPC中,客戶端存根就把要傳遞的數(shù)據(jù)信息序列化成二進(jìn)制,以方便服務(wù)器識(shí)別并處理。
這里的數(shù)據(jù)信息不單包括參數(shù),還有要調(diào)用的函數(shù)ID??蛻舳舜娓鶎⑺鼈兘y(tǒng)一序列化成二進(jìn)制后,打包遞交給傳輸層。

傳輸層使用TCP協(xié)議,所以RPC中,上層傳遞下來的二進(jìn)制信息需要進(jìn)一步封裝在TCP包中,尋址后發(fā)送給相應(yīng)的服務(wù)器。
可都封裝好了,為什么要有尋址這一步驟呢?
簡(jiǎn)而言之,尋址的重要作用就是找到該函數(shù)對(duì)應(yīng)的服務(wù)器地址。但是企業(yè)環(huán)境中,各服務(wù)分散在不同的服務(wù)器上,如果都由客戶端來“記憶”,將導(dǎo)致巨大的資源浪費(fèi)。為了方便查詢分散的服務(wù)地址,RPC中會(huì)將所有服務(wù)和對(duì)應(yīng)地址都集中在一起,這個(gè)集中了所有服務(wù)地址的機(jī)器就是注冊(cè)中心。
通過注冊(cè)中心,客戶端和服務(wù)器可以更方便地交互。
對(duì)服務(wù)器來說,它每增加或注銷一項(xiàng)服務(wù)就通知注冊(cè)中心進(jìn)行更改,而不必一一告知客戶端。對(duì)客戶端來說,它也不必記住每一項(xiàng)服務(wù)所在地址,也不用管服務(wù)地址是否有變化。只需要在申請(qǐng)服務(wù)時(shí),從注冊(cè)中心查找到服務(wù)地址,向該地址發(fā)送數(shù)據(jù)包就行了。也就是說服務(wù)端的變化對(duì)客戶端幾乎沒有影響。

數(shù)據(jù)包傳遞到服務(wù)器后,先由傳輸層對(duì)其解析,得到序列化過的二進(jìn)制包。
要把這個(gè)二進(jìn)制包轉(zhuǎn)化成服務(wù)器能理解的數(shù)據(jù)格式,就需要與序列化相對(duì)的反序列化。
通常在服務(wù)器上,同樣擁有一個(gè)服務(wù)端存根,它和客戶端存根的作用一樣,用來管理RPC過程中的大部分事務(wù),反序列化也由它來完成。
在這里,服務(wù)端存根對(duì)二進(jìn)制包反序列化,得到參數(shù)和要調(diào)用的函數(shù)ID,然后遞交給服務(wù)器。服務(wù)器計(jì)算后得到結(jié)果,返回給客戶端。

RPC中,結(jié)果返回時(shí),同樣需要服務(wù)端存根來對(duì)其進(jìn)行序列化后傳輸,客戶端收到響應(yīng)數(shù)據(jù)包后由客戶端存根再次對(duì)其反序列化,得到結(jié)果。
這樣,在RPC協(xié)議規(guī)范下,客戶端就成功調(diào)用了服務(wù)端的函數(shù)來完成計(jì)算。
# 結(jié)語 #
相比于HTTP等傳輸協(xié)議,RPC將數(shù)據(jù)序列化成二進(jìn)制,直接在傳輸層上與服務(wù)端交互,極大地提高了傳輸效率。并且使用存根來管理RPC的底層過程,讓客戶端和服務(wù)端的交互變得透明,從而為用戶提供了方便。
不過,拋開傳輸效率的便利,RPC中同樣也存在很多安全威脅,比如Zerologon(CVE-2020-1472)、Printnightmare(CVE-2021-34527)等,攻擊者利用這些漏洞,可以直接通過RPC協(xié)議連接服務(wù)器,并向其發(fā)送惡意代碼,從而獲取控制目標(biāo)服務(wù)器的權(quán)限,這也是使用協(xié)議時(shí)要提防的一個(gè)方向。
以上就是RPC協(xié)議的全部?jī)?nèi)容,下一篇文章中,我們將繼續(xù)為大家介紹SMB協(xié)議。
了解更多AD域協(xié)議相關(guān),歡迎關(guān)注中安網(wǎng)星
