-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFind-Log4jFile.ps1
More file actions
153 lines (129 loc) · 4.66 KB
/
Copy pathFind-Log4jFile.ps1
File metadata and controls
153 lines (129 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<#
.SYNOPSIS
Durchsucht Datentraeger nach log4j-Bibliotheken mit der
JndiLookup-Klasse - auch in verschachtelten Archiven.
.DESCRIPTION
Sucht nach JAR- und WAR-Dateien und prueft deren Inhalt auf
JndiLookup.class, also den fuer Log4Shell (CVE-2021-44228)
ausschlaggebenden Bestandteil. Archive werden ueber 7-Zip geoeffnet, auch
ineinander geschachtelte.
Allow- und Denylist erlauben es, bekannte und gepruefte Fundstellen bei
Wiederholungslaeufen auszublenden. Mit -Loeschen wird die betroffene
Klasse aus dem Archiv entfernt - der von Apache empfohlene Notbehelf,
wenn ein Update nicht moeglich ist.
.NOTES
Braucht 7z.exe; erwartet wird sie neben dem Skript ($PSScriptRoot).
-Loeschen veraendert Archive an Ort und Stelle. Vorher sichern und mit
der Anwendung testen - manche Programme pruefen ihre JAR-Dateien auf
Unversehrtheit.
#>
param (
[string]$Suchmuster = "*jndilookup.class*",
[string]$AusgabePfad = "C:\install\log4j_$($env:COMPUTERNAME).txt",
[string]$PfadZu7z = "$PSScriptRoot\7z.exe",
[switch]$Loeschen,
[string[]]$Allowlist = @(),
[string[]]$Denylist = @()
)
function Invoke-ExternalCommand {
param (
[string]$Title,
[string]$Path,
[string]$Arguments
)
try {
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $Path
$psi.Arguments = $Arguments
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.StandardOutputEncoding = [System.Text.Encoding]::GetEncoding(1252)
$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $psi
$null = $proc.Start()
$stdout = $proc.StandardOutput.ReadToEnd()
$stderr = $proc.StandardError.ReadToEnd()
$proc.WaitForExit()
[pscustomobject]@{
Title = $Title
StdOut = $stdout
StdErr = $stderr
ExitCode = $proc.ExitCode
}
}
catch {
Write-Warning "Fehler bei Befehl $Title $_"
return $null
}
}
function Test-JarDatei {
param (
[System.IO.FileInfo]$JarDatei,
[string]$Suchmuster
)
$cmdResult = Invoke-ExternalCommand -Title "Scan: $($JarDatei.FullName)" `
-Path $PfadZu7z -Arguments "l `"$($JarDatei.FullName)`""
if ($null -eq $cmdResult) { return }
$foundItems = $cmdResult.StdOut -split "`n" | Where-Object { $_ -like $Suchmuster }
if ($foundItems) {
$Treffer = $foundItems | ForEach-Object {
($_ -split "\s+")[-1]
}
return [pscustomobject]@{
Computername = $env:COMPUTERNAME
Datei = $JarDatei.FullName
Fundstellen = $Treffer -join ", "
}
}
}
function Test-InList {
param (
[string]$Pfad,
[string[]]$Liste
)
foreach ($item in $Liste) {
if ($Pfad -like $item) { return $true }
}
return $false
}
# Vorbereitungen
if (-not (Test-Path -Path $PfadZu7z)) {
Write-Error "7z.exe nicht gefunden unter $PfadZu7z"
exit 1
}
if (Test-Path $AusgabePfad) {
Remove-Item $AusgabePfad -Force
}
Write-Host "Starte Log4j-Suchlauf auf $env:COMPUTERNAME..."
# Laufwerke durchgehen
$Laufwerke = [System.IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Fixed' } | Select-Object -ExpandProperty Name
foreach ($Laufwerk in $Laufwerke) {
try {
Get-ChildItem -Path $Laufwerk -Include '*.jar', '*.war' -File -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object {
$pfad = $_.FullName
if ($Denylist.Count -gt 0 -and (Test-InList -Pfad $pfad -Liste $Denylist)) { return }
if ($Allowlist.Count -gt 0 -and -not (Test-InList -Pfad $pfad -Liste $Allowlist)) { return }
Write-Host "Untersuche: $pfad"
$ergebnis = Test-JarDatei -JarDatei $_ -Suchmuster $Suchmuster
if ($ergebnis) {
$text = "$($ergebnis.Computername)`t$($ergebnis.Datei)`t$($ergebnis.Fundstellen)"
Add-Content -Path $AusgabePfad -Value $text
Write-Host "Gefunden: $text" -ForegroundColor Red
if ($Loeschen) {
try {
Remove-Item -Path $_.FullName -Force
Write-Host "Datei gelöscht: $pfad" -ForegroundColor Yellow
}
catch {
Write-Warning "Fehler beim Löschen: $pfad - $_"
}
}
}
}
}
catch {
Write-Warning "Fehler beim Scannen von $Laufwerk $_"
}
}
Write-Host "Scan abgeschlossen. Ergebnisse: $AusgabePfad"