App-V Applications and the CVE-2021-44228 Apache Log4j Exploit

$packageRoot = Get-AppvClientConfiguration | where Name -eq PackageInstallationRoot | Select -ExpandProperty Value
$packageRoot = [System.Environment]::ExpandEnvironmentVariables($packageRoot)

$jarFiles = gci ($packageRoot) -rec -force -filter *.jar -ea 0 | where Name -like "*log4j*" | select -ExpandProperty FullName

foreach ($jarfile in $jarFiles) {
    $PackageId = $jarfile -replace "$packageRoot\",""
    $PackageId = $PackageId.split("\")[0] 

    $packageName = Get-AppvClientPackage -all | Where-Object PackageId -eq "$PackageId" | Select -ExpandProperty Name
    
    write-host $packageName
    write-host $jarfile

}

One of our clients asked us to review their App-V applications and the CVE-2021-44228 Apache Log4j exploit.  Specifically to report on all the jar files in App-V packages that contain the vulnerable JndiLookup.class.

Since App-V 5 applications are compressed into an .appv file, we needed a way of extracting them so we could scan for vulnerabilities.  There were two approaches we could take – one being to extract the contents to disk (since they’re essentially based on the PKZip compression standard) and scan them.  But this might include packages that are not published and have been retired.

The other way, which we chose, was to use an App-V administrator account to find all the ‘Published’ applications, add/mount them to the filesystem and then scan them for the CVE-2021-44228 Apache Log4j exploit.

We did this on a virtual machine, so the first task was to expand the virtual disk large enough to mount all of the packages!  Note that you’ll also need PowerShell remoting enabled.  Then, we opened up a Powershell prompt as an App-V admin account and ran the following (you’ll need to update the value of $appVWin10Server):

#name of App-V server
$appVWin10Server = "xxxxx"

#retrieve all published apps
$getPackages = {
            $packageUrls = Get-AppvServerPackage | where Enabled -eq $true | select -ExpandProperty PackageUrl
            return $packageUrls
} 
$allPackageUrls = Invoke-Command -ComputerName $appVWin10Server -ScriptBlock $getPackages

#add/mount each published app
foreach($packageUrl in $allPackageUrls) {
    Add-AppvClientPackage -Path $packageUrl | Mount-AppvClientPackage
}

#get the package root (where all the packages have been mounted to)
$packageRoot = Get-AppvClientConfiguration | where Name -eq PackageInstallationRoot | Select -ExpandProperty Value
$packageRoot = [System.Environment]::ExpandEnvironmentVariables($packageRoot)

#scan mounted packages for JAR file(s) containing the vulnerability
$jarFiles = (gci ($packageRoot) -rec -force -filter *.jar -ea 0 | foreach { try { select-string "JndiLookup.class" $_ -ea 0 } catch {}} | select -exp Path -first 1)

foreach ($jarfile in $jarFiles) {    
    $PackageId = $jarfile -replace "$packageRoot\",""
    $PackageId = $PackageId.split("\")[0] 

    $packageName = Get-AppvClientPackage -all | Where-Object PackageId -eq "$PackageId" | Select -ExpandProperty Name
    
    write-host $packageName
    write-host $jarfile

}

It’s also worth mentioning that, once you’ve mounted your App-V apps above, you can also just scan for instances of ‘log4j’ like so:

$packageRoot = Get-AppvClientConfiguration | where Name -eq PackageInstallationRoot | Select -ExpandProperty Value
$packageRoot = [System.Environment]::ExpandEnvironmentVariables($packageRoot)

$jarFiles = gci ($packageRoot) -rec -force -filter *.jar -ea 0 | where Name -like "*log4j*" | select -ExpandProperty FullName

foreach ($jarfile in $jarFiles) {
    $PackageId = $jarfile -replace "$packageRoot\",""
    $PackageId = $PackageId.split("\")[0] 

    $packageName = Get-AppvClientPackage -all | Where-Object PackageId -eq "$PackageId" | Select -ExpandProperty Name
    
    write-host $packageName
    write-host $jarfile

}

These scripts have been rustled up rather hastily, so feedback is always welcome!  Of course, you can also scan the whole system with the following one-liner:

(gci ("c:\") -rec -force -filter *.jar -ea 0 | foreach { try { select-string "JndiLookup.class" $_ -ea 0 } catch {}} | select -exp Path -first 1)