Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Powershell: Delete class from JAR file with invoke-command

I am trying to remove vulnerable classes from the log4j jar file with powershell.
I am able to remove the file using the script locally on the server, however, I want to remove the class from many paths on many servers and trying to use invoke-command.

The script can open and read the JAR file but doesnt seem to action the delete() method. Is there a way to get powershell to delete the class "remotely"?

Here is my script:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

$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

>Solution :

You need to explicitly call Dispose() on the containing archive to persist the updates to the file on disk:

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

By placing the call to $zip.Dispose() inside a finally block, we ensure that it’s always disposed regardless of whether an exception was thrown in the preceding try block.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading