Powershell:使用调用命令从 JAR 文件中删除 class

Powershell: Delete class from JAR file with invoke-command

我正在尝试使用 powershell 从 log4j jar 文件中删除易受攻击的 classes。 我可以在服务器本地使用脚本删除文件,但是,我想从许多服务器上的许多路径中删除 class 并尝试使用 invoke-command.

该脚本可以打开并读取 JAR 文件,但似乎无法执行 delete() 方法。有没有办法让 powershell “远程”删除 class?

这是我的脚本:

$servers = @(
    "server"
)
$class_to_delete = "JMSSink"
$unable_to_connect = @()
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.Filesystem
write-host "`nTesting connection to:" -ForegroundColor Yellow
$servers | ForEach-Object {Write-Host "$_"}
$servers | ForEach-Object {
    $server = $_
    try {
        write-host "`nTesting $($server)"
        Invoke-Command -ComputerName $server -ScriptBlock {
            Write-Host "Connection successful to $($env:computername)" -ForegroundColor Green
        } -ErrorAction Stop
    } catch {
        write-host "`nConnection failed to $($server)"
        $unable_to_connect += $server
    }
}
Write-Host "`nStarting script to remove $($class_to_delete) class from log4j" -ForegroundColor Yellow
$objects_skipped = @()
$servers | ForEach-Object {
    $server_node = $_
    write-host "`nPut in the file paths for $($server_node)" -ForegroundColor Yellow
    $file_locations = (@(While($l=(Read-Host).Trim()){$l}) -join("`n"))
    $file_locations | Out-File C:\temp\output.txt  #Change this path to the temp folder and file on the server you execute from
    $file_objects = Get-Content -Path C:\temp\output.txt #Change this path to the temp folder and file on the server you execute from
    $stats_x = foreach ($file_object in $file_objects) {
        $stats = Invoke-Command -ComputerName $server_node -ScriptBlock {
            Write-Host "`nStarting on $($env:COMPUTERNAME)"
            $class = $using:class_to_delete
            Add-Type -AssemblyName System.IO.Compression
            Add-Type -AssemblyName System.IO.Compression.Filesystem
            $ful_path = $using:file_object
            $fn = Resolve-Path $ful_path
            try {
                $zip = [System.io.Compression.ZipFile]::Open("$fn", "Read")
                Write-Host "Backing up $($fn) to $($fn).bak"
                $zip.Dispose()
                Copy-Item "$fn" "$($fn).bak"
                $zip = [System.io.Compression.ZipFile]::Open($fn, "Update")
                $files = $zip.Entries | Where-Object  { $_.name -eq "$($class).class" }
                if (!$files) {
                    write-host "`nNo $($class) class found on $($env:COMPUTERNAME) for path: $($ful_path)"
                    $files.dispose()
                    $not_found = @()
                    $not_found += New-Object -TypeName PSObject -Property @{
                        Server = $env:COMPUTERNAME;
                        Path   = $ful_path;
                        Result = "$($class) class NOT FOUND"
                    }
                    Write-Output $not_found
                } else {
                    foreach ($file in $files) {
                        write-host "`n$($class) class found on $($env:COMPUTERNAME) for path: $($ful_path)"
                        write-host "`nDeleting file $($file)" -ForegroundColor Green
                        #delete class
                        $file.delete()
                        #check if class was successfully deleted
                        $confirm_delete = $zip.Entries | Where-Object { $_.name -eq "$($class).class" }
                        write-host $confirm_delete
                        if ($confirm_delete.name -match "$class.class") {
                            $deleted_status = "$($class) !!NOT REMOVED!!"
                        } else {
                            $deleted_status = "$($class) REMOVED"
                        }
                        $Output = @()
                        $Output += New-Object -TypeName PSObject -Property @{
                            Server = $env:COMPUTERNAME;
                            Path   = $ful_path;
                            Result = $deleted_status
                        }
                        Write-Output $Output
                    }
                }
            } catch {
                Write-Host "Cannot open $($ful_path) as a Zip File. $($Error[0])"
            }
        }
        Write-Output $stats
    }
    $objects_skipped += $stats_x
}
#result
write-host "`nEnd result"
$objects_skipped | select Server,Result,Path | ft -AutoSize

您需要在包含的存档上显式调用 Dispose() 以将更新保存到磁盘上的文件:

# this goes immediately after the `catch` block:
finally {
  if($zip -is [IDisposable]){ $zip.Dispose() }
}

通过将对 $zip.Dispose() 的调用放置在 finally 块中,我们确保无论在前面的 try 块中是否抛出异常,它总是被释放。