Summary
A client that connects to cupsd but sends slow messages, e.g. only one byte per second, delays cupsd as a whole, such that it becomes unusable by other clients.
Details
Johannes Meixner (@jsmeix) and Paul Zirnik (@pzirnik, who did the main technical research through code analysis of cupsd) discovered that one client that connects to cupsd but sends slow messages - e.g. only one byte per second, by using
while true ; do echo -n "D" ; sleep 1 ; done | netcat localhost 631,
for example, delays cupsd such that it becomes unusable by other clients, who can also be running the following in parallel:
while true ; do date ; time lpstat -p ; sleep 1 ; done.
The character sent by the "slow client" (D, from the example), determines whether or not TLS is used by cupsd.
With characters DGHOPT, no TLS is used. So with character X, TLS is used by cupsd and, in that case,
time while true ; do echo -n "X" ; sleep 1 ; done | netcat localhost 631
aborts after 6 seconds because of a failed TLS handshake.
One can increase the sleep delay up to less than 10 seconds because there is a 10 seconds timeout in cupsd, so, for
time while true ; do echo -n "X" ; sleep 9 ; done | netcat localhost 631
6 * 9 = 54 seconds are needed to abort because of a failed TLS handshake.
According to Paul Zirnik's code analysis of cupsd, it seems like the main reason behind this is that cupsd reads whole lines, meaning it won't drop the slow client until it gets one line (and because cupsd is single-threaded, one client that misbehaves ends up affecting cupds as a whole). Therefore, an offhanded idea how this issue might be solved is to let cupsd read client input byte by byte, but it is not certain whether that would really solve the issue, nor if that could bring any negative side effects, nor if it could be implemented with reasonable effort.
PoC
Run while true ; do echo -n "D" ; sleep 1 ; done | netcat localhost 631 to simulate the client slowing down the system, while running while true ; do date ; time lpstat -p ; sleep 1 ; done in parallel, to simulate other clients.
Impact
It is possible for a malicious actor to purposefully cause a DoS in a system by exploiting this cupsd issue, but only when the admin of the system violates crucial conditions regarding how printing services are meant to be used, by exposing his printing services to non-trusted users (see for example, https://en.opensuse.org/SDB:CUPS_and_SANE_Firewall_settings#It_is_crucial_to_limit_access_to_CUPS_to_trusted_users, where access limitation is suggested when using cups).
By default cupsd does "only listen for connections from the local machine" (excerpt from default /etc/cups/cupsd.conf), so by default cupsd is not exposed to non-trusted users. This means that a generic vulnerability in a system, one that leads to cupsd being accessible to non-trusted users, is a prerequisite for a remote DoS attack.
That being said, the main concern here ends up being not so much a malicious DoS attack from arbitrary remote hosts "out there on the Internet", but rather a situation where a trusted client accidentally misbehaves and ends up making the whole cupds process useless.
Summary
A client that connects to cupsd but sends slow messages, e.g. only one byte per second, delays cupsd as a whole, such that it becomes unusable by other clients.
Details
Johannes Meixner (@jsmeix) and Paul Zirnik (@pzirnik, who did the main technical research through code analysis of cupsd) discovered that one client that connects to cupsd but sends slow messages - e.g. only one byte per second, by using
while true ; do echo -n "D" ; sleep 1 ; done | netcat localhost 631,for example, delays cupsd such that it becomes unusable by other clients, who can also be running the following in parallel:
while true ; do date ; time lpstat -p ; sleep 1 ; done.The character sent by the "slow client" (
D, from the example), determines whether or not TLS is used by cupsd.With characters
DGHOPT, no TLS is used. So with characterX, TLS is used by cupsd and, in that case,time while true ; do echo -n "X" ; sleep 1 ; done | netcat localhost 631aborts after 6 seconds because of a failed TLS handshake.
One can increase the
sleepdelay up to less than 10 seconds because there is a 10 seconds timeout in cupsd, so, fortime while true ; do echo -n "X" ; sleep 9 ; done | netcat localhost 6316 * 9 = 54 seconds are needed to abort because of a failed TLS handshake.
According to Paul Zirnik's code analysis of cupsd, it seems like the main reason behind this is that cupsd reads whole lines, meaning it won't drop the slow client until it gets one line (and because cupsd is single-threaded, one client that misbehaves ends up affecting cupds as a whole). Therefore, an offhanded idea how this issue might be solved is to let cupsd read client input byte by byte, but it is not certain whether that would really solve the issue, nor if that could bring any negative side effects, nor if it could be implemented with reasonable effort.
PoC
Run
while true ; do echo -n "D" ; sleep 1 ; done | netcat localhost 631to simulate the client slowing down the system, while runningwhile true ; do date ; time lpstat -p ; sleep 1 ; donein parallel, to simulate other clients.Impact
It is possible for a malicious actor to purposefully cause a DoS in a system by exploiting this cupsd issue, but only when the admin of the system violates crucial conditions regarding how printing services are meant to be used, by exposing his printing services to non-trusted users (see for example, https://en.opensuse.org/SDB:CUPS_and_SANE_Firewall_settings#It_is_crucial_to_limit_access_to_CUPS_to_trusted_users, where access limitation is suggested when using cups).
By default cupsd does "only listen for connections from the local machine" (excerpt from default /etc/cups/cupsd.conf), so by default cupsd is not exposed to non-trusted users. This means that a generic vulnerability in a system, one that leads to cupsd being accessible to non-trusted users, is a prerequisite for a remote DoS attack.
That being said, the main concern here ends up being not so much a malicious DoS attack from arbitrary remote hosts "out there on the Internet", but rather a situation where a trusted client accidentally misbehaves and ends up making the whole cupds process useless.