Bugzilla – Bug 1221671
AUDIT-TRACKER: ipp-usb: review systemd service and udev rules
Last modified: 2024-04-11 14:11:34 UTC
ipp-usb provides a new systemd service and new udev rules where that service (triggered by udev) can expose locally connected USB printers (and MFPs) on the network. There is a OBS submitrequest for the ipp-usb package: https://build.opensuse.org/request/show/1157901 The ipp-usb package upstream is https://github.com/OpenPrinting/ipp-usb Its author is Alexander Pevzner https://github.com/alexpevzner He provides binaries via his OBS home project home:pzz for various distributions. The above submitrequest comes from a different OBS home project home:rrahl0
Thank you for bringing this issue to our attention. I will work on this.
Thank you for bringing this to our attention. As long as the is not autostarted we don't formally require a review of it. Attaching printers that aren't designed for network access to the network by design sounds risky and should likely be something that is restricted to trusted local networks (if these still exist anywhere). We will have a look into the package but it might take a bit due to other tasks.
Making locally connected USB printers (possibly) accessible via network is risky, cf. the section "It is crucial to limit access to network printer devices to trusted users" in https://en.opensuse.org/SDB:CUPS_and_SANE_Firewall_settings because making a USB printer accessible via network means also making CUPS and a whole lot of various CUPS helper software (cups-filters, Ghostscript, ...) accessible via network, cf. the section "It is crucial to limit access to CUPS to trusted users" in https://en.opensuse.org/SDB:CUPS_and_SANE_Firewall_settings Related to that https://github.com/OpenPrinting/ipp-usb reads (excerpts): ----------------------------------------------------------- Avahi Notes (exposing printer to localhost) IPP-over-USB normally exposes printer to localhost only, hence it requires DNS-SD announces to work for localhost. ... The third method is simple to do, just replace 'interface = loopback' with 'interface = all' in the ipp-usb.conf file, but this has the disadvantage of exposing your local USB-connected printer to the entire local network, which can be an unwanted side effect, especially in a big corporative network. ----------------------------------------------------------- At least to me this does not look as if security concerns are sufficiently considered (not just some "disadvantage"). To me it more looks as if unexpected printing output from others in a big corporate network is the biggest concern which may cause privacy issues for those who (accidentally) print on such an (unintendedly) exposed local USB printer, see also the parts about "print job phishing" in https://en.opensuse.org/SDB:CUPS_and_SANE_Firewall_settings
Reassigned to security-team for now as I am still busy with existing tasks.
I'll look into this.
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.
Switching this to a tracker bug. If you still need anything from us please ask. Otherwise I am also fine with closing it.
Closing as fixed and publishing.
I forwarded the findings here in comment #6 to upstream via https://github.com/OpenPrinting/ipp-usb/issues/78