OpenPrinting / ipp-usb

ipp-usb -- HTTP reverse proxy, backed by IPP-over-USB connection to device
BSD 2-Clause "Simplified" License
129 stars 11 forks source link

FYI: Security review of ipp-usb by SUSE #78

Closed jsmeix closed 2 months ago

jsmeix commented 2 months ago

This is only to have you informed.

At SUSE we did a security review of ipp-usb https://bugzilla.opensuse.org/show_bug.cgi?id=1221671

Here a copy of the findings, see https://bugzilla.opensuse.org/show_bug.cgi?id=1221671#c6

Matthias Gerstner 2024-04-04 13:18:56 UTC 

I finished looking into the package.
It's about 10.000 lines of Golang.
The code mostly looks well organized and readable.
Interestingly the systemd service is kind of autostarted
via the udev rules that are shipped.
As soon a compatible printer device is plugged in,
the service starts via udev.

Authorization and Networking
============================

The major pain point is the networking / authorization model.
By default the service only listens on localhost.
For localhost there also exists a simple authentication
scheme based on user ids and groups.
This is configured via /etc/ipp-usb/ipp-usb.conf.
The owner of a localhost TCP connection is determined
via special Linux TCP diagnostic socket APIs.
A bit overkill IMHO (maybe it could have been done
via a UNIX domain socket in some way), but okay.

If the daemon is allowed to listen on all interfaces then,
the printer becomes available over http://
in the local network.
If authentication is configured then requests can be sent
from remote but all such requests will be rejected,
because they cannot be authorized.
This means a networked printer is only accessible,
if authentication is disabled.
This seems a bit strange at first,
but in fact is consistent on a logical level
and does not leave a false impression on admins
(I configured authentication, thus it is safe).
It would be even better not to listed on the network
at all though, if authentication is enabled.

Not only that remote connections cannot be authorized,
but there is also no support for SSL encryption
and thus also not for any kind of integrity.
So print jobs sent over the network
will leak to observers of network traffic.
The data can also be manipulated.
Thus using ipp-usb on the network is absolutely something
that must limited to completely trusted, small networks.

The package is still okay for Factory in my opinion,
because the network access is disabled by default,
and even if it is enabled, then the firewall will
still prevent access by default.
Thus if somebody enables this on both ends,
then they hopefully really know what they're doing.
It's also unlikely that this happens in a mobile setup,
e.g. if somebody uses this at home with their laptop
and takes the laptop to work, then the printer
will likely not be taken along to work,
i.e. ipp-usb will not be running in the work scenario.

Local UNIX Domain Socket
========================

The ipp-usb daemon also serves a local UNIX domain socket
in /var/ipp-usb/ctrl.
This socket is world accessible.
An HTTP listener is attached to this socket.
But it only supports GET requests for the /status URL,
everything else is rejected.
The /status GET only returns some text describing
the current runtime status.
So it is uncritical for local security.

Session Handling limited to 1000 IDs
====================================

For some reason the session IDs on HTTP and USB level
are limited to 1000 distinct IDs:

https://github.com/OpenPrinting/ipp-usb/blob/0.9.25/usbtransport.go#L412

https://github.com/OpenPrinting/ipp-usb/blob/0.9.25/http.go#L84

So the session numbers are limited and predictable.
When using unencrypted HTTP this could make spoofing easier.
But since we don't have any networking security anyway,
I don't think it's a problem, just a curiosity.

Hardening Suggestion
====================

The ipp-usb service currently runs with full root privileges.
This seems a bit much for what is does.
On the networking side it only listens on ports > 1024
by default, so this doesn't require special permissions.
The only interesting bit is the access to the USB devices
via libusb.

A hardening could be to install udev rules
that grant access to ipp-usb for matching USB devices,
either via a group assignment, or an ACL entry.
Then ipp-usb could run with lowered privileges,
greatly reducing attack surface.
Maybe this is something you can approach upstream with.
alexpevzner commented 2 months ago

Hi @jsmeix,

thank you for review!

I would convert it from "issue" into "discussion", so it may stay open forever and there will be no need to somehow "fix" it and close.