Evil MSI. A story about vulnerabilities in MSI Files

CICADA8
9 min readAug 30, 2024

--

Hello everybody, my name is Michael Zhmailo and I am a penetration testing expert in the MTS Innovation Center CICADA8 team.

You have probably come across MSI files quite often. They are used by software manufacturers to provide their programs. This format is more convenient than the standard EXE format for the following reasons:

  • Ability to restore, install certain components
  • Data storage in well-structured tables that can be easily accessed via APIs
  • Easy distribution via SCCM, WEB endpoints

There may be various vulnerabilities inside MSI files, most of which will lead to privilege escalation. These include both logical vulnerabilities: DLL/TypeLib/COM/Exe File/Script/etc hijacking, PATH Abusing, and vulnerabilities of the MSI file format itself: Custom Actions Abuse, abandoned credentials, privileged child processes.

You may have read about vulnerabilities in MSI files before:

These are great articles if you are just getting familiar with finding vulnerabilities inside MSI files. Our article can also serve as a great starting point for learning more about this topic. In addition, we have developed a tool called MyMSIAnalyzer that will make it easier to find vulnerabilities inside MSI files. You should read this article if you want to learn more about the insides of the MSI format and how the tool works.

MSI File Format

The MSI format itself is somewhat similar to SQL databases. Inside the MSI file there are tables with various data. There is a relationship between the tables. And this table is analyzed and used while installing MSI file.

MSI File Format

I note that there are a lot of tables. We are interested in only a few of them. The full list of tables is described here.

  • Component Table — a special table inside which resources used by the application (images, shortcuts, icons, etc.) are located;
  • Each resource is associated with a specific functionality. Therefore, there is a Feature Table, which is linked to the Components Table through the FeatureComponents Table;
  • File Table — a table that specifies which files should be installed on the system;
  • Directory Table — table that contains information about the folder structure of the program to be installed;
  • Installation Actions — table that contains actions to be performed during MSI file installation (create a shortcut, create a registry key, write a value);
  • Custom Actions — actions that need to be performed during the installation process, however, they cannot be performed through Windows Installer API, so third-party programs, DLL files, cmd commands are used.

Collecting MSI files for analysis

Manually

The easiest way to locate all MSI files is to look in the C:\Windows\Installer folder. Here you will definitely find all MSI files of programs installed on your computer.

Folder Contents #1
Folder Contents #2

Inside the folder you can find MSI files and other folders. Other folders often store various resources that the MSI file needs. Their name is GUID. This GUID can be seen in the IdentifiyingNumber field of the installed software product.

You can examine the installed programs and make a mapping using these commands:

wmic product get identifyingnumber,name,vendor,version
List of the installed products

You can also use Powershell and add a filter by software.

Get-WmiObject -class Win32_Product | ? { $_.Name -like "*Office*" } | select IdentifyingNumber,Name

Tools

Of course, it is more convenient to use automated tools to gather information and MSI files itself.

PS> Invoke-CMLootInventory -SCCMHost sccm01.domain.local -Outfile sccmfiles.txt

PS> Invoke-CMLootDownload -InventoryFile .\sccmfiles.txt -Extension msi

Web

You can find files for analysis on the internet as well. For example, you can use Google Dorks:

ext:msi "download"

Or use special resources with a list of MSI files:

Searching for vulnerabilities

Abandoned credentials

It’s the simplest option. Inside MSI files, it is possible to find leftover passwords, API keys, endpoints and other data that may be of interest to us as attackers.

We have dedicated a CredFinder class in MyMSIAnalyzer for credential discovery. Searching for credentials works to the point of simplicity. It checks all properties of the MSI file and tries to find sensitive information by keywords.

CredFinder.cs

Since MSI format is close to SQL format, you can get all properties with one query. However, if you need a portable option or don’t know how to compile CSharp projects yet, you can use a Powershell script with same logic:

$installerPath = "C:\Windows\Installer"
$package = New-Object -ComObject WindowsInstaller.Installer

function AnalyzeMsiFile {
param (
[string]$msiPath
)
try {
$database = $package.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $package, @($msiPath, 0))
$view = $database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $database, @("SELECT * FROM Property"))

$view.Execute()
while ($record = $view.Fetch()) {
$property = $record.StringData(1)
$value = $record.StringData(2)
if ($property -match "USERNAME|PASSWORD|USER|PASS") {
Write-Host "File: $msiPath, Property: $property, Value: $value"
}
}
} catch {
Write-Host "Error processing file: $msiPath" -ForegroundColor Red
}
}

Get-ChildItem -Path $installerPath -Filter *.msi -Recurse | ForEach-Object {
AnalyzeMsiFile $_.FullName
}

Behavioral analysis

MSI Repair Mode

Of course, inside MSI credentials can be found quite rarely. Most often only when analyzing MSI files that were stolen from SCCM. So if we are looking for a privilege escalation vector, we need to analyze the behavior of the MSI file.

And here we need to familiarize ourselves with an unusual functionality: the MSI file repair mechanism.

MSI’s repair mechanism allows a Windows system to reinstall either the entire product or individual components of the product. In effect, fix the program if something went wrong during use or installation.

This functionality is most conveniently utilized using the CLI tool msiexec.

In addition, MSI Custom Actions, which were created by the developer of the MSI file, are invoked in recovery mode. Here too, there may be a vulnerability. If Custom Actions or the entire MSI file is misconfigured, the recovery process is performed on behalf of the NT AUTHORITY\SYSTEM user, which allows us to escalate privileges.

For example, if the developer has set Custom Actions to run cmd.exe, then during a normal installation cmd.exe will be run as the current user, but during recovery it will be run as the system user.

Also through Custom Actions can run some graphical applications on behalf of the system, from which you can make an analog of Kiosk Bypass, get out to explorer.exe and run cmd.exe from it. cmd.exe will be launched on behalf of the system.

GUI in custom actions abuse
Abuse example in Internet Explorer installer

How to detect it?

Let’s start by checking the entire MSI file. There are only two things we need to monitor:
- Presence of a GUI interface, if we want to promote via explorer.exe escape
- The name of the user on whose behalf the MSI file is run in recovery mode, if we want to examine the file for other vulnerabilities, such as DLL Hijacking

The easiest way to detect such MSI files is to use the GuiFinder tool:

.\GuiFinder.exe --folder C:\Temp

If you find yourself running from the NT AUTHORITY\System and the presence of a graphical interface, you can attempt to perform an escape from the environment as described above.

What about custom actions?

Custom Actions can also be executed on behalf of the NT AUTHORITY\SYSTEM. To do so, they must be configured with the Impersonate=“no” option. For example, as here

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{12345678-9259-4E29-91EA-8F8646930000}" Language="1033" Manufacturer="YourCompany" Name="HelloInstaller" UpgradeCode="{12345678-9259-4E29-91EA-8F8646930001}" Version="1.0.0.0">
<Package Comments="This installer database contains the logic and data required to install HelloInstaller." Compressed="yes" Description="HelloInstaller" InstallerVersion="200" Languages="1033" Manufacturer="YourCompany" Platform="x86" ReadOnly="no" />

<CustomAction Id="SetRunCommand" Property="RunCommand" Value="[%USERPROFILE]\test.exe" Execute="immediate" />
<CustomAction Id="RunCommand" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="commit" Return="ignore" Impersonate="no" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="HelloInstaller" ShortName="krp6fjyg">
<Component Id="ApplicationShortcut" Guid="{12345678-9259-4E29-91EA-8F8646930002}" KeyPath="yes">
<CreateFolder Directory="INSTALLFOLDER" />
</Component>
</Directory>
</Directory>
</Directory>
<Property Id="ALLUSERS" Value="1" />
<Feature Id="ProductFeature" Level="1" Title="Main Feature">
<ComponentRef Id="ApplicationShortcut" />
</Feature>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." Schedule="afterInstallValidate" />

<InstallExecuteSequence>
<Custom Action="SetRunCommand" After="InstallInitialize">1</Custom>
<Custom Action="RunCommand" After="SetRunCommand">1</Custom>
</InstallExecuteSequence>
</Product>
</Wix>

This will cause Custom Actions to be run on behalf of the NT AUTHORITY\SYSTEM. We created a ActionAnalyzer class to analyze Custom Actions.

First, we also highlighted keywords whose presence within Custom Actions will result in privilege escalation. After all, it will be easy to abuse this functionality.

Interesting Keywords

The tool then checks that Custom Actions will in principle be called. To do this, they must be in the call sequence between InstallExecuteSequence and InstallFinalize.

Getting sequence indexes

The validation of these indices is done a little later. After getting the indexes, we extract all Custom Actions and check for the most important parameter Impersonate: NO

CustomAction flags analyzing

After making sure that the Custom Action is executed on behalf of the system and is within the correct action sequence, a keyword check is performed

Keyword checking

Lets run the tool.

Example output

The tool will then bring up some interesting CustomActions. And you can start finding ways to abuse them. For example, perform DLL Sideloading, launch a file from User Writable Paths, find another vulnerability. I encourage you to study this article and this. It covers the most common ways to abuse CustomActions.

You can learn how to use our tool and hone your skills on the following vulnerabilities:

  • CVE-2023–26077 (MSI Installer DLL Hijacking)
  • CVE-2023–21800 (Symlink Abuse)
  • CVE-2023–26078 (Escape to cmd.exe)

Custom Actions Overwriting

There is an even more interesting vector. We can find a CustomAction that runs on behalf of the system. However, we may not be able to abuse it. In that case, we can try to overwrite it! If the permissions on the MSI file allow, of course. In some cases, administrators override the default DACL, which will result in elevated privileges.

To find this vector, we created a Writer class.

Output example

Diff

MSI files both contain vulnerabilities and fixes them! So we needed a convenient way to implement diff of two files to analyze patches.

The simplest way is to use msidiff, its syntax is self-explanatory

Diff example

Conclusion

MSI files are used quite often in the Windows infrastructure. Often an improper approach to developing or deploying such files will lead to the possibility of privilege escalation on the host.

--

--

CICADA8

CICADA8 is a vulnerability management service with real-time cyber threat tracking capabilities. https://futurecrew.tech/cicada8