Forum Discussion

Pretzel's avatar
Pretzel
Icon for Neophyte rankNeophyte
6 months ago

PowerShell Datasource with NonAdmin Collector

Hey

can some maybe explain to me what i'm doing wrong. We recently change all our Collector to Non-Admins.

We have the Windows Certificates Datasource in place and if i understand correct the Datasource uses PowerShell to trigger Invoke Command from Collector to get Data from Target.

I took this PS Template to to build my own Test Datasource. When i test the script against a targetserver i get this message. (I also get the Values from Target Server in stdOutput)

Changing ExecutionPolicy on Collector for LocalMachine to Unrestricted didnt change anything

Set-ExecutionPolicy : Access to the registry key
'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' is denied. To change the execution
policy for the default (LocalMachine) scope, start Windows PowerShell with the "Run as administrator" option. To
change the execution policy for the current user, run "Set-ExecutionPolicy -Scope CurrentUser".
At line:1 char:1
+ Set-ExecutionPolicy RemoteSigned
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyComma
nd

What i dont understand is why my Datasource is running into this Error while the WinCert Datasource isnt eventhough they use the same Invoke Commands. I do have diffrent commands in the script block but this should make any diffrence.

 

 

 
  • It looks like something is attempting to use the Set-ExecutionPolicy command. Running that command requires running as Administrator and it looks like whatever is failing is not running as admin. You may need to determine what is attempting to run that.

    If the DataSource itself has that command, you may need to remove it, if the DataSource is no longer running as administrator. You shouldn't need, nor want to, to run that command in a DataSource.

    If it's the collector software attempting to use that command, that might be a bug in the collector or your not using a collector version that supports non-admin use. I would verify you have the latest collector version (perhaps even try the latest EA version).

  • Anonymous's avatar
    Anonymous

    They could be using different credentials. There are two ways LM can authenticate in Windows: 1) Integrated 2) discrete.

    For integrated authentication, the collector uses the credentials used to run the service. If those creds (which can be explicitly defined as a username or could be system) don't have access to the target, it'll fail. 

    For discrete auth, this uses wmi.user and wmi.pass properties defined on the resource in LM.

    Most of the logicmodules built by LM automatically detect which auth method to use. Yours may not. So they could be using different creds.

    Not running as admin on a Windows collector should be a careful decision for this very reason. In our case, unless we ran it as admin, we'd have to specify admin creds on every target server, which is just as much a security concern as running the service with the admin creds. Since they are equally as risky, but both the nature of monitoring in Windows, we choose to just run the service with domain admin creds. In actuality, we run most as system, but give that system admin access. This means there's no password to be hacked because it's not a user account but a computer object in the domain that is granted access.

  • I'm using wmi.user and wmi.pass properties, the properties are set on the server object and has the rights on the target server but is non admin on collector.

    If I have not overlooked anything then there should be nothing in the powershell script that triggers Set-ExecutionPolicy.

    I have also run the code once on the collector under the non admin service user and get no error. I have also tested signing. I can't explain what is causing this.

    This is my test datasource (i need to change my return to int)

    # Clears the CLI of any text
    Clear-Host
    # Clears memory of all previous variables
    Remove-Variable * -ErrorAction SilentlyContinue
    #------------------------------------------------------------------------------------------------------------
    # Initialize Variables
    $TargetHostName = '##SYSTEM.SYSNAME##' + '.' + '##SYSTEM.DOMAIN##'
    $CollectorHostName = $env:computername
    $TargetUserName = '##wmi.user##'
    $TargetPassword = '##wmi.pass##'
    $DebugMode = $false
    
    $ScriptBlock = {
        param (
            [bool]$Debug
        )
        # Get pagefile information
        $pageFileInfo = Get-CimInstance -Class Win32_PageFileUsage | Select-Object *
        $CompSysResults = Get-CimInstance win32_computersystem -Namespace 'root\cimv2'
    
        # Initialize variables
        $pageFileDrive = ""
        $isOnC = $false
        $isAuto = $false
        $otherFilesExist = $false
    
        if ($pageFileInfo) {
            $pageFilePath = $pageFileInfo.Name
            $pageFileDrive = Split-Path -Path $pageFilePath -Qualifier
    
            # Check if pagefile is on C: drive
            $isOnC = $pageFileDrive -eq "C:"
    
            # Check if pagefile size is set to auto
            $isAuto = $CompSysResults.AutomaticManagedPagefile
    
            # Output results
            Write-Host "PageFileDrive=$pageFileDrive"
            Write-Host "IsOnCDrive=$isOnC"
            Write-Host "IsAutoManaged=$isAuto"
    
            # Check for other files/folders on pagefile drive
            if ($pageFileDrive -eq "D:") {
                $otherItems = Get-ChildItem -Path $pageFileDrive -Force | Where-Object { $_.FullName -ne $pageFilePath }
                $otherFilesExist = $otherItems.Count -gt 0
                Write-Host "OtherFilesExist=$otherFilesExist"
            }
    
        }
    }
    
    
    if ($TargetHostName -eq $CollectorHostName)
    {
        Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList @($DebugMode,$Instance)
    }
    else
    {
        #If WMI creds undefined - invoke remote command without creds, if not - create credential object and use it for authorization
        if (($TargetUserName -Match "wmi.user" -and $TargetPassword -Match "wmi.pass") -or 
            ($TargetUserName -eq "" -and $TargetPassword -eq ""))
        {
            Invoke-Command -ComputerName $TargetHostName -ScriptBlock $ScriptBlock -ArgumentList @($DebugMode,$Instance)
        }
        else
        {
            $TargetCredentials = New-Object System.Management.Automation.PSCredential ($TargetUserName, $(ConvertTo-SecureString $TargetPassword -AsPlainText -Force))
            Invoke-Command -ComputerName $TargetHostName -ScriptBlock $ScriptBlock -Credential $TargetCredentials -ArgumentList @($DebugMode,$Instance)
        }
    }
    
    Exit 0

     

     

     

    and this is code from Windows Certificate Datasource and its running without error. If i past the code into my newly created datasource i also get an error for ExecutionPolicy. So if there is not command inside that is triggering ExecutionPolicy this should be a bug?

     

    $Instance = '##WILDVALUE##'
    $TargetHostName = '##SYSTEM.SYSNAME##' + '.' + '##SYSTEM.DOMAIN##'
    $CollectorHostName = $env:computername
    $TargetUserName = '##wmi.user##'
    $TargetPassword = '##wmi.pass##'
    $DebugMode = $false
    
    $ScriptBlock = {
        param (
            [bool]$Debug,
            [String]$SerialNumber
        )
        
        if ($Cert = Get-ChildItem -Path cert:LocalMachine -Recurse | Where-Object { $_.SerialNumber -eq $SerialNumber } | Sort-Object -Unique) {
            $TimeSpan = New-TimeSpan -Start (Get-Date) -End $Cert.NotAfter
            $DaysLeft = $TimeSpan.Days
            Write-Host "DaysLeft=$DaysLeft"
        }
    }
    
    if ($TargetHostName -eq $CollectorHostName)
    {
        Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList @($DebugMode,$Instance)
    }
    else
    {
        #If WMI creds undefined - invoke remote command without creds, if not - create credential object and use it for authorization
        if (($TargetUserName -Match "wmi.user" -and $TargetPassword -Match "wmi.pass") -or 
            ($TargetUserName -eq "" -and $TargetPassword -eq ""))
        {
            Invoke-Command -ComputerName $TargetHostName -ScriptBlock $ScriptBlock -ArgumentList @($DebugMode,$Instance)
        }
        else
        {
            $TargetCredentials = New-Object System.Management.Automation.PSCredential ($TargetUserName, $(ConvertTo-SecureString $TargetPassword -AsPlainText -Force))
            Invoke-Command -ComputerName $TargetHostName -ScriptBlock $ScriptBlock -Credential $TargetCredentials -ArgumentList @($DebugMode,$Instance)
        }
    }
    
    Exit 0

     

    • Mike_Moniz's avatar
      Mike_Moniz
      Icon for Professor rankProfessor

      Outside of the code above what is different from two DataSources? Is one Batch while the other is Script for example? Does once have ActiveDiscovery and the other doesn't? etc. Perhaps even export both and compare the raw JSON.

      Might want to work out a bare min replication. For example, do you see the same error even if the script is literally just "Exit 0" and nothing else? Might need to work with LM support to look at your specific situation.