---
description: 'From http://hacking-printers.net/wiki/index.php/Accounting_bypass'
---

# Accounting bypass

## **Introduction**

**Printing without permission** can itself be a security risk or breach of company policy. In environments where print jobs are charged for, an inside attacker has a motivation to bypass the accounting system. Furthermore, being able to ‘print’ is a precondition for most attacks against network printers.

There are two major approaches when it comes to print job accounting: Either **let the printer handle it directly or use a print server in between**. The first approach is vendor-specific, usually involves some kind of special ‘printer driver’ and is not further discussed here. The other approach involves a separate print server – usually a software implementation like [CUPS](https://en.wikipedia.org/wiki/CUPS) or [LPRng](https://en.wikipedia.org/wiki/LPRng) – to handle the accounting and is quite common in companies and institutions. The print server may speak LPD, IPP or further printing protocols and forwards jobs to the actual printer. **It is important to note that direct network access to the printer must be restricted**, otherwise an attacker can **easily bypass the print server** and its accounting mechanisms. This means filtering access to typical and atypical ports \(LPD, IPP, raw, HTTP, SMB, FTP, SNMP\).

There are basically two approaches to circumvent the print job accounting systems: either **impersonate another user or manipulate the counter** of printed pages. In the following both options are discussed for LPRng \(v3.8.B\) and CUPS \(v2.1.4\) installations which are popular open-source printing systems used in academic and corporate environments. A comparison of the security features of both systems is given below.

| Printing system | Protocol | Encryption | Authentication | Page counter |
| :--- | :--- | :--- | :--- | :--- |
| **LPRng** | LPD | SSL/TLS | Kerberos, PGP | hardware |
| **CUPS** | IPP | SSL/TLS | Kerberos, HTTP | software |

## Authentication bypasses

LPRng and CUPS both offer SSL based channel encryption and secure authentication schemes like [Kerberos](https://en.wikipedia.org/wiki/Kerberos_%28protocol%29), [PGP](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) signed print jobs or HTTP [basic](https://en.wikipedia.org/wiki/Basic_access_authentication)/[digest](https://en.wikipedia.org/wiki/Digest_access_authentication) authentication. If **configured properly** and in case the attacker cannot access the printer directly she will be **not be able to impersonate other users**. Those security features however are **optional and rarely applied** in the real-world print servers. Instead, the **usernames given as LPD \(LPRng\) or IPP \(CUPS\) parameters are logged and accounted for** – which can be set to arbitrary values by the client side. The reasons for this is a simple cost-benefit consideration in most institutions**: Kerberos needs a special setup** on every client and **HTTP** authentication **requires** users to enter a **password** whenever they want to print something while the costs of a few unaccounted printouts are bearable.

You can **verify proper authentication** trying to print with a **custom username** like this:

```text
lp -U nobody test.ps
```

## Page counter manipulation

### Hardware page counters

For correct accounting the **number of printed pages must be determined** by the printing system which is not a trivial task. The authors of **LPRng** _make the assumption that the printer has some sort of non-volatile page counter mechanism that is reliable and impervious to power on/off cycles_. Such **hardware page counters** are supported by most printers and **read** by LPRng **using PJL after** every **print** job. **HP** has even documented a feature to **write** to the **page counter** variable by setting the printer into service mode. This way, the **page counter** of the _HP LaserJet 1200, HP LaserJet 4200N_ and _HP LaserJet 4250N_ **can be manipulated** within a print job. At the end of the document to be printed and separated by the [UEL](./#uel), the counter simply has to be reset to its original value \(for example, `2342`\):

```text
\x1b%-12345X@PJL JOB
This page was printed for free
\x1b%-12345X@PJL EOJ
\x1b%-12345X@PJL JOB
@PJL SET SERVICEMODE=HPBOISEID
@PJL SET PAGES=2342
\x1b%-12345X@PJL EOJ
```

An attacker might set a negative number of printed pages. Note that resetting the device to [Factory defaults](factory-defaults.md) also **resets the page counter to zero on some** of the tested devices.  
Lowering the page counter can also be used to **sell a printer above its price** as it can be compared to the odometer when buying a second-hand car. It is however worth emphasising that **resetting the page counter is not necessarily for malicious purposes**: It is a well-known business model to sell overpriced ink for low-cost inkjet devices and block third-party refill kits by refusing to print after a certain number of pages – to handle such unethical practices it is absolutely legitimate to reset the page counter.

On older HP laserjets the `pagecount`command of [PRET](https://github.com/RUB-NDS/PRET) can be used to easily set hardware pagecounters:

```text
./pret.py -q printer pjl
Connection to printer established

Welcome to the pret shell. Type help or ? to list commands.
printer:/> pagecount 10
Old pagecounter: 53214
New pagecounter: 10
```

### Software page counters

**CUPS** uses **software page counters** which have been implemented for all major page description languages. For PostScript, an easy way to bypass accounting is to check if the PageCount system parameter exists – which will return false when interpreted in CUPS/Ghostscript – before actually printing the document as shown below.

```text
currentsystemparams (PageCount) known {
  <@\textit{[...] code which is only executed on a printer device [...]}@>
} if
```

This way, the accounting software used by CUPS renders a different document than the printer. **CUPS only accounts for one page** – which seems to be a **hardcoded minimum** – while the **real** print job can contain **hundreds** **of pages**. Note that using the IPP ‘raw’ queue/option is mandatory, otherwise CUPS parses the code with a PostScript-to-PostScript filter \(Ghostscript's ps2write\) before it reaches the page counter.

**How to test for this attack?**

**Wrap** an arbitrary **multi-page PostScript document** in the **code above** and print. Then go to [`http://printserver:631/jobs?which_jobs=all`](http://printserver:631/jobs?which_jobs=all) and check CUPS's page counter for this print job. Note that have to establish a raw queue. This is, a queue where the filtering system is not involved and the print job goes directly to a printer. For CUPS, this is done by setting the content type to `application/vnd.cups-raw`. If your system is already configured to use the print server to be tested, simply use:

```text
lp -o raw test.ps
```

