#1102033 cups-bsd: /usr/bin/lpr confused by filenames starting with '-' (causes hang or unexpected file creation)

Package:
cups-bsd
Source:
cups-bsd
Description:
Common UNIX Printing System(tm) - BSD commands
Submitter:
Dave Goel
Date:
2025-04-04 03:27:03 UTC
Severity:
normal
#1102033#5
Date:
2025-04-04 03:22:01 UTC
From:
To:

Hi  -

I found some problems with /usr/bin/lpr on my Debian Bookworm system. It
seems to act strangely when it deals with filenames that happen to start
with a dash (-), especially -o or -P.

PROBLEM 1: lpr can hang (freeze) when processing arguments like "-o..." /
"-P..."

If lpr is run in a way where it gets a single argument like "-bakery.pdf",
or "-oSomeFile.txt" or "-PMyPrinter", instead of treating it as a filename,
it seems to get confused. Using strace, I saw that lpr stops, waiting
forever to read from standard input (read(0)). Since nothing is usually
typed in at that point, the command just hangs.





PROBLEM 2: In fact, it tries to parse the filenames as options! Which in
principle, can lead to a wider  attack vector, as follows.

(In principle) Scripts using lpr's documented behavior can be tricked into
creating unwanted files, or sending things to wrong printers -

Someone might write a script that uses lpr based on how they think it works
from documentation. This can go wrong because lpr gets confused by those
filenames starting with -.

Let's imagine a "smart" script like this that runs once a day,
(smart_print.sh), maybe used by cron. This version always pipes a default
message to lpr, but it expects lpr to ignore that pipe if filename
arguments are given, and instead, prints "nothing incoming".

The idea is that your script, wihin its core, tries to "abuse" the
documented feature of lpr.
Wherein, if no files were actually found, it would default to printing,
"nothing_incoming", once a day.


lpr_files=()
for file_path in "${incoming_files[@]}"; do
    # Use basename to remove directory prefix
    filename=$(basename "$file_path")
    lpr_files+=("$filename")
done
echo "nothing_incoming" | /usr/bin/lpr "${lpr_files[@]}"


Files are uploaded by users in incoming/

An attacker could upload an empty file called "-PPDF"
Your script would now, create a PDF file on your linux machine with the
contents "nothing_incoming"


Let's demo that the script that uses this logic (based on lpr's own
documentation) will acutally make a un unintended filename on your system -

# --- How to Reproduce Problem 2 (Script Subversion) ---
#    - Ensure you have a 'PDF' printer queue using cups-pdf saving to ~/PDF/
#    - Create the PDF output directory if it doesn't exist
mkdir -p ~/PDF
#    - Create the single "maliciously" named file the script would find
#      (Content doesn't matter, using touch is simplest)
touch -- "-PPDF"
echo "Setup complete. File '-PPDF' created."

# 2. Simulate the script executing its core command:
#    (Script finds "-PPDF", prepares it as argument, runs echo | lpr arg)
echo; echo "*** Simulating script running: echo '...' | lpr '-PPDF' ***"
echo "nothing_incoming" | /usr/bin/lpr "-PPDF"
echo "Command finished."

Now, you will find a new file in your ~/PDF/ that you never intended to
create!