mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-26 04:53:39 +00:00
79 lines
6.9 KiB
Markdown
79 lines
6.9 KiB
Markdown
---
|
||
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\_\(protocol\)), [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:
|
||
|
||
```
|
||
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`):
|
||
|
||
```
|
||
\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:
|
||
|
||
```
|
||
./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.
|
||
|
||
```
|
||
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:
|
||
|
||
```
|
||
lp -o raw test.ps
|
||
```
|