Bugzilla – Bug 1086936
VUL-0: CVE-2018-1106: PackageKit: regular users can install and downgrade arbitrary (signed) packages without admin authorization
Last modified: 2019-07-19 14:37:02 UTC
During an audit of PackageKit polkit rules for bug 993505 I uncovered a security flaw. The issue is not public yet. I just sent the following advisory to the upstream maintainer: Regular users can install arbitrary (signed) packages without entering valid admin authorization. In file src/pk-transaction.c in the function pk_transaction_authorize_actions_finished_cb() there is some logic starting in line 2352 /* did not auth */ that causes a transaction to continue, even if the authorization failed. This is true in the following conditions: - polkit action org.freedesktop.packagekit.package-install was requested - the PK_TRANSACTION_FLAG_ENUM_ALLOW_REINSTALL flag is present Both conditions can be controlled by the unprivileged client. There seems to be no code in place that actually checks whether a "reinstall" is actually happening, therefore an unauthorized client can install any packages from file. This is an example reproducer that utilizes the 'pkcon' tool on openSUSE Leap 42.3 via SSH remote login (i.e. no a local X session), polkit actions for PackageKit are all set to 'auth_admin': ``` $ pkcon --only-download install $PACKAGE $ pkcon install-local --allow-reinstall /var/cache/zypp/packages/repo-oss/suse/x86_64/${PACKAGE}*.rpm [...] Proceed with changes? [N/y] y [...] ==== AUTHENTICATING FOR org.freedesktop.packagekit.package-install === [press ctrl-c or enter an invalid password] ``` Only RPMs considered correctly signed by the backend can be installed this way. So there is no immediate local root exploit. But it gives a large attack surface to increase probability to gain root. For example older packages (with known security issues) that are validly signed can be installed this way. I did not find a way to install arbitrary RPMs yet. Other backends than zypper seem to be affected just as well, but I have not tried to reproduce the issue on other distros yet. The issue was introduced via git commit: f176976e24e8c17b80eff222572275517c16bdad Probably affected versions: >= 1.0.10 up until current 1.1.9
The found issue allows to circumvent our polkit rules which are set to auth_admin for both standard and restrictive polkit profiles. Affected codestreams are SLE-12-SP2 and Factory.
The patch from attachment 764947 [details] should fix this issue by sacrificing the whole "allow reinstallation of packages w/o authorization" idea. This idea was a bad one to begin with I think. I recommended the following to the upstream maintainer: > I would also not recommend to allow regular users to reinstall packages > without authentication by default, because RPMs contain scriptlets for > pre- and postinstallation and might trigger reloads or even restarts of > daemons. This could open up DoS vectors or in case of bad RPM scriptlet > implementations even worse security flaws, at the disposal of a regular > user.
So upstream does not consider this a problem at all. "Works as designed". Installing arbitrary signed packages is not a security concern in their view. This leaves us with the following issues: A) it is still possible to *downgrade* packages without authentication and this could be an individual bug in the zypper backend of PackageKit. The backend needs to identify when a downgrade is happening and reject it if the action/flag for downgrading is not set. This needs to be dealt with. B) I disagree with the general security assessment provided by upstream. Upstream allows regular users to install arbitrary signed packages without authentication by default. That's okay if they want to, but currently there seems to be no way to configure a more conservative setting. And I would not want this to be the "secure" default in SUSE distributions. According to upstream, PackageKit is in "maintenance only" mode and since they don't seem to consider this bug severe they don't seem to want to provide a patch from their side. So we would need to do something. Could our PackageKit maintainers comment on this and propose a solution?
I have just posted the following message on the linux-distros mailing list. Currently operating with a 2 week embargo. Hello list, following is an analysis of PackageKit and the discussion of a number of vulnerabilities that I found to be exploitable in its context. I intend to make this information available to the general public in two weeks on 2018-04-23 16:00 CEST. Please assign CVEs as you see fit. PackageKit is a software suite designed to allow easy software installation and maintenance for end-users across distributions. It abstracts the various package management software found in today's Linux distributions and provides a unified interface for graphical user interface programs to interact with the package management. PackageKit's main component is a daemon `packagekitd` which implements a D-Bus interface. Clients can retrieve information about installed packages and can request package management actions to be performed. A backend within `packagekitd` translates the abstract PackageKit commands into actual package management commands. Backends exist for all major Linux package management systems like zypper, yum, apt and others. PackageKit is enabled by default on most if not all major Linux distributions when a fully integrated desktop environment like GNOME or KDE is installed. For the purposes of this analysis I looked into openSUSE Leap 42.3, Debian 9 Strech, Ubuntu 17.10, CentOS 7.4.1708 and Fedora 27 which covers the major backends zypper, apt, yum and dnf. I will leave out the version numbers for the rest of this analysis for brevity. There exist a number of additional backends that I did not look into. Upstream repository: https://github.com/hughsie/PackageKit.git Upstream website: https://www.freedesktop.org/software/PackageKit/ PackageKit uses the polkit permissions framework to authorize individual operations. It has been a code review of the implementation of these polkit actions within PackageKit that led me to the findings discussed in this analysis. One important decision that upstream made is that it is deemed safe that regular users can install validly signed packages in the system without requiring administrator authentication. The motivation for this seems to be improved usability for end users. This is also documented here: https://github.com/hughsie/PackageKit/blob/master/policy/org.freedesktop.packagekit.policy.in#L33 > - Normal users do not need authentication to install signed packages > from signed repositories, as this cannot exploit a system. > - Paranoid users (or parents!) can change this to 'auth_admin' or > 'auth_admin_keep'. The related polkit action is named `org.freedesktop.packagekit.package-install`. The Linux distributions considered in this analysis ship a polkit policy file that requires `auth_admin` or `auth_admin_keep` for the installation of signed packages as well. However, there is also a custom polkit rule shipped by PackageKit that allows local users in an active session and that are members of the group `wheel` to install signed packages without admin authorization: https://github.com/hughsie/PackageKit/blob/master/policy/org.freedesktop.packagekit.rules This rule file is installed on openSUSE, Fedora and CentOS unmodified. Ubuntu and Debian ship a different rule file that does not allow this. During my code review I found a section of code that indicated that regardless of what the polkit configuration consists of it is always possible to install signed packages without any form of authentication. The relevant code location is here: https://github.com/hughsie/PackageKit/blob/master/src/pk-transaction.c#L2354 If reinstallation of packages is allowed, then an authentication attempt is made by `packagekitd` but the outcome is ignored. The flag `PK_TRANSACTION_FLAG_ENUM_ALLOW_REINSTALL` is under user control, however. There is currently no way to avoid this loophole in PackageKit by means of configuration files. PackageKit comes with a command line utility called `pkcon` that can be used to perform PackageKit operations. There are two general possibilities how to install packages: - `pkcon install [options] <package>` installs a package from the configured package manager system repositories by name. - `pkcon install-local [options] <package>` installs a package from a user supplied package manager archive file (e.g. rpm or deb archive). The reinstall loophole can be used interactively like this: ``` $ pkcon install --only-download zsh $ pkcon install-local --allow-reinstall /var/cache/yum/x86_64/7/base/packages/zsh-5.0.2-28.el7.x86_64.rpm ``` The second `pkcon` call will trigger the authentication dialog, but even if the password is wrong or the dialog is canceled, the installation of the package will continue. The only distribution I looked into that does not allow this is Fedora which seems to use the dnf backend instead of the yum backend. The current Fedora release can therefore be considered not affected by the issues discussed in this analysis. Even though installation of signed packages by regular users is considered safe by upstream, it should not be possible to downgrade existing packages. A separate polkit action `org.freedesktop.packagekit.package-downgrade` should be triggered in this case. The individual PackageKit backends are responsible to implement this logic, however. It turned out that not every backend implements this correctly. Using the above approach with `pkcon install-local --allow-reinstall` it is possible to downgrade even important system packages without entering the administrator password in the following cases: - apt backend (tested on Ubuntu, Debian) - zypp backend (tested on openSUSE) Only the yum and dnf backends (tested on CentOS, Fedora) implement the downgrade protection correctly. Using this possiblity a regular user can downgrade packages to vulnerable versions that open up further attack vectors for gaining privileges. I have attached a number of proof of concept scripts that demonstrate this: - `pk_downgrade_debian_bash.py`: this downgrades bash on Debian 9 Stretch to an old one that is still vulnerable to "Shell Shock". - `pk_downgrade_opensuse_systemd.py`: This downgrades systemd on openSUSE version 228 that is vulnerable to CVE-2016-10156. This one is accompanied by `opensuse_exploit_systemd.py` to complete the root exploit. This is not a 100 % root exploit, it requires some extra opportunity that requires systemd to create a new timer stamp file in /var/lib/systemd/timers. Even if a user is not able to downgrade existing packages without administrator privileges there is still a security issue to consider. A regular user can install local package files downloaded from the Internet that carry a valid signature. When the package in question is not installed yet in the system then this does not count as a downgrade but as a fresh installation. This opens a surprisingly large action space to regular users: - tools for constructing exploits can be easily obtained from the system repositories or the Internet. - outdated software with known bugs can be installed in some circumstances. On some distributions year old packages with valid signatures can be installed this way. - packages can contain scriptlets for performing runtime package setup. These scriptlets may provide additional attack surface when they can be triggered at the discretion of regular users. I have attached two further PoC scripts that demonstrate some of these points: - `pk_root_debian_ntfs3g.py`: This installs an old ntfs-3g package on Debian that is vulnerable to CVE-2017-0358 and exploits it. This variant works only if the `fuse` kernel module is not yet loaded. - `pk_root_ubuntu_firejail.py`: This installs an old firejail package on Ubuntu that is vulnerable to CVE-2017-5180 and exploits it. On CentOS I have been able to construct an attack (no PoC) using CentOS 7.0 packages for abrt 2.1.11-12.el7 which is vulnerable to CVE-2015-1862. This only worked if abrt was not yet installed, however (and it is installed by default). There may be systems out there that fulfill this condition though. These PoCs also show that all necessary tools like compiler, kernel headers etc. can be easily installed to construct the attack. My tests showed that on Ubuntu packages dating back to at least 2012 can be installed as signed packages. On Debian packages dating back to 2001 can be installed. But this may also be due to the issue described in the following section 6). On CentOS 7.4 any packages dating back to CentOS 7.0 can be installed as signed packages. On openSUSE Leap 42.3 packages from openSUSE 11.4 dating from the year 2012 can be installed as signed packages. On Fedora (27) only packages for the same major/minor version can be installed. There exist probably other attacks that can be constructed by installing outdated packages this way. I followed the track of the user supplied archive paths passed to `packagekitd` to find out how the user owned archives are handled by the daemon. It turned out that the common `packagekitd` code takes no precautions to copy the file into a safe space that is no longer accessible by the client. This is the job of the backends. The zypp and yum backends do this and copy the file over into a temporary directory owned by root. They subsequently build a local RPM repository from the copied RPM file and operate on it. The apt backend, however, does not do this. The path passed from the client is passed unmodified into the libapt-pkg code. I am not sure whether the libapt-pkg code is prepared to process a file under user control. My worry was and is that there could be race condition involved that would allow the user to replace all or part of the supplied deb archive by something malicious after the signature verification passed. I also found that the client side code makes some effort to sanitize archive paths in `pk_client_convert_real_paths()`: https://github.com/hughsie/PackageKit/blob/master/lib/packagekit-glib2/pk-client.c#L308 The daemon code itself performs no such sanitization, however. I have not found any actual attack vectors based on this yet. But it is possible to pass symlink paths and relative paths to the daemon and the daemon passes it to its backends. I am just adding this to the report for completeness, maybe someone else is interested in this and finds out more. While I looked into the situation described in 6) I encountered an even worse condition in the apt backend: It seems to be possible to install modified deb packages without admin authentication. This is demonstrated in the attached PoC `pk_apt_install_modified.py`. This PoC works on Debian and Ubuntu. It downloads a validly signed package, injects a setuid-root binary, installs it and runs it to gain root privileges. I have not further analyzed where this security leak originates, because I am not familiar with the libapt-pkg code and I need the help of the community to identify possible further security issues involved. The basic issue described in 3) that allows to circumvent the polkit configuration was introduced via git commit: f176976e24e8c17b80eff222572275517c16bdad and affected versions include >= 1.0.10 up until current 1.1.9. The missing downgrade protection described in 4) has probably been always present in the affected backends but I did not check up on it. The issue of installing new signed packages without admin authorization as described in 5) is by PackageKit design and exploitability depends on the distribution's configuration and on the existence of issue 3). Since I don't know what exactly the problem is that causes modified packages to be installed in the apt backend as described in 7) I can't make any statements here at the moment. My personal recommendation to prevent the issues described in 3), 4) and 5) is to not allow regular users to perform any of the involved actions without admin authentication. To achieve this there must be no code in place that circumvents the polkit configuration. The upstream polkit rules file that allows active local users in the group wheel to install packages without authentication should be dropped. I do not have any suggested patch at the moment, except removing the piece of code that ignores the failed polkit authorization. According to upstream this will "break deployed software". They suggested the following instead: > I guess you could argue that we should call `pk_transaction_role_to_actions()` > and add `PK_TRANSACTION_FLAG_ENUM_ALLOW_REINSTALL`, then re-do the polkit auth > aysnc call, and that's probably the proper way to fix the case where the > distro has changed the default or the system has been locked down by an > admin somehow. If that's what you want to do that's fine, but you'd probably > have to write the patch as PackageKit is basically in maintenance mode now. Regarding the issue described in 4) the backends should additionally correctly implement the detection of downgrades and call the appropriate polkit actions. Regarding the issue described in 7) I have not enough insight to give any recommendation (except of course, not to allow installation of untrusted packages without at least asking for authorization for org.freedesktop.packagekit.package-install-untrusted). The discussed PackageKit backends may be used by other distributions than considered in this report. These distributions should be identified and checked at well. Also the less widespread backends that have not been considered in this analysis should be checked for their behaviour and affectedness.
In attachment 766474 [details] and attachment 766475 [details] you can find PoCs that demonstrate how to downgrade systemd to the vulnerable version 228 on openSUSE Leap 42.3 (same should work similarly on SLE with PackageKit installed). The second script can be used to exploit the vulnerability once systemd has created one of the vulnerable timer files. I hope this makes the severity of the issue more obvious. For our SUSE integration of PackageKit I am suggesting the following: - removal of /usr/share/polkit-1/rules.d/org.freedesktop.packagekit.rules or replacement by something that doesn't allow any regular user to install packages without admin authorization. - the zypp backend in PackageKit needs to be fixed to recognize package downgrades and prevent them or relay to the appropriate polkit action (org.freedesktop.packagekit.package-downgrade) for proper authentication. Some of our people like dimstar, Michael Andres and coolo have been working on it in the past so those are possible candidates. - Installation of packages without admin authentication (especially those from files!) should really be prevented (except maybe for the 'easy' polkit profile). This could also be done in the zypp backend, maybe there is also an approach in the generic packagekitd code as has been outlined by upstream.
(In reply to Matthias Gerstner from comment #11) > For our SUSE integration of PackageKit I am suggesting the following: > > - removal of /usr/share/polkit-1/rules.d/org.freedesktop.packagekit.rules or > replacement by something that doesn't allow any regular user to install > packages without admin authorization. I'm unsure about this use case in the first place. What are the usual situations where someone is added to the "wheel" group. This requires admin rights to add - what is the general expectations for members of that group. > - the zypp backend in PackageKit needs to be fixed to recognize package > downgrades and prevent them or relay to the appropriate polkit action > (org.freedesktop.packagekit.package-downgrade) for proper authentication. Agreed. Yifan and Jonathan - can you free up space in the schedule for Jonathan to start working on this? I will ping Michael Andres to see if he is available to provide guidance with libzypp questions.
Created attachment 766779 [details] 0001-Do-not-set-JUST_REINSTALL-on-any-kind-of-auth-failur.patch 0001-Do-not-set-JUST_REINSTALL-on-any-kind-of-auth-failur.patch attached to last email
(In reply to Matthias Gerstner from comment #11) > For our SUSE integration of PackageKit I am suggesting the following: > > - removal of /usr/share/polkit-1/rules.d/org.freedesktop.packagekit.rules or > replacement by something that doesn't allow any regular user to install > packages without admin authorization. Users in wheel group are not regular users. So I don't think this is a issue. > - the zypp backend in PackageKit needs to be fixed to recognize package > downgrades and prevent them or relay to the appropriate polkit action > (org.freedesktop.packagekit.package-downgrade) for proper authentication. > Some of our people like dimstar, Michael Andres and coolo have been > working on > it in the past so those are possible candidates. Is there any link for the previous work done?
(In reply to sckang@suse.com from comment #19) > Users in wheel group are not regular users. So I don't think this is a issue. But are they equivalent to root without entering a password? > Is there any link for the previous work done? - dimstar/mlandres from 2016: ca13b738836929776ef9adf1f808739e4fddf715 - commit from coolo (but that was 2013): d3d14631042237bcfe6fb30a60e59bb6d94af425 But that have only been hints, I don't know who is best suited to work on the code.
(In reply to Matthias Gerstner from comment #20) > (In reply to sckang@suse.com from comment #19) > > > Users in wheel group are not regular users. So I don't think this is a issue. > > But are they equivalent to root without entering a password? > Apparently not. But back to Scott's question in comment#12: > What are the usual situations where someone is added to the "wheel" group. This > requires admin rights to add - what is the general expectations for members of > that group?
(In reply to sckang@suse.com from comment #21) > > > Users in wheel group are not regular users. So I don't think this is a issue. > > > > But are they equivalent to root without entering a password? > > > Apparently not. But back to Scott's question in comment#12: > > > What are the usual situations where someone is added to the "wheel" group. This > requires admin rights to add - what is the general expectations for members of > that group? Yes of course somebody needs to add the user to wheel with admin rights. But even then the user needs the admin password to gain root. The security issues uncovered show that unauthenticated installation of packages via PackageKit can be equivalent to getting root privileges without entering a password. So the security properties are changed by this polkit rule.
(In reply to Matthias Gerstner from comment #20) > (In reply to sckang@suse.com from comment #19) > > > Users in wheel group are not regular users. So I don't think this is a issue. > > But are they equivalent to root without entering a password? https://en.wikipedia.org/wiki/Wheel_(Unix_term) And our default /etc/sudoers contains: ## Uncomment to allow members of group wheel to execute any command # %wheel ALL=(ALL) ALL ## Same thing without a password # %wheel ALL=(ALL) NOPASSWD: ALL
(In reply to Dominique Leuenberger from comment #23) > (In reply to Matthias Gerstner from comment #20) > > (In reply to sckang@suse.com from comment #19) > > > > > Users in wheel group are not regular users. So I don't think this is a issue. > > > > But are they equivalent to root without entering a password? > > https://en.wikipedia.org/wiki/Wheel_(Unix_term) > > And our default /etc/sudoers contains: > > ## Uncomment to allow members of group wheel to execute any command > # %wheel ALL=(ALL) ALL > > ## Same thing without a password > # %wheel ALL=(ALL) NOPASSWD: ALL oh, and there is of course pam_wheel: NAME pam_wheel - Only permit root access to members of group wheel SYNOPSIS pam_wheel.so [debug] [deny] [group=name] [root_only] [trust] [use_uid] DESCRIPTION The pam_wheel PAM module is used to enforce the so-called wheel group. By default it permits root access to the system if the applicant user is a member of the wheel group. If no group with this name exist, the module is using the group with the group-ID 0. Further clarifying that 'wheel' users are supposedly root-equivalents
(In reply to dimstar@opensuse.org from comment #24) > > > > Users in wheel group are not regular users. So I don't think this is a issue. > > > > > > But are they equivalent to root without entering a password? > > > > https://en.wikipedia.org/wiki/Wheel_(Unix_term) > > > > And our default /etc/sudoers contains: > > > > ## Uncomment to allow members of group wheel to execute any command > > # %wheel ALL=(ALL) ALL > > > > ## Same thing without a password > > # %wheel ALL=(ALL) NOPASSWD: ALL Yes you could configure that but it isn't configured by default, luckily. > oh, and there is of course pam_wheel: > > NAME > pam_wheel - Only permit root access to members of group wheel I still don't see how this grants a member of the wheel group root access without entering the root password.
(In reply to Matthias Gerstner from comment #25) > > Yes you could configure that but it isn't configured by default, luckily. > > > oh, and there is of course pam_wheel: > > > > NAME > > pam_wheel - Only permit root access to members of group wheel > > I still don't see how this grants a member of the wheel group root access > without entering the root password. pam_wheel? If you enable pam_wheel (it's not enabled by default on SUSE systems) then all your wheel members can sudo to root without password, if 'trust' is given (which is, from what I've seen in the wild, the most common: the root pw is not shared, but members of wheel are allowed to 'su' to root to perform their actions. This is definitively not a seldom setup)
> pam_wheel? If you enable pam_wheel (it's not enabled by default on SUSE > systems) then all your wheel members can sudo to root without password, if > 'trust' is given (which is, from what I've seen in the wild, the most common: > the root pw is not shared, but members of wheel are allowed to 'su' to root to > perform their actions. This is definitively not a seldom setup) Yes I understand that. The default setting is exactly the point here. Users can do all kind of fun stuff if they want to. But we are responsible to ship a safe default configuration. And if we ship this polkit rules file then we subject our users to known security issues in PackageKit without them being aware of it. We can happily ship this rule file as an example file that is not part of the active polkit configuration. Users can then use this file as a template and it is then in their responsibility to judge the results.
(In reply to Matthias Gerstner from comment #27) > > pam_wheel? If you enable pam_wheel (it's not enabled by default on SUSE > > systems) then all your wheel members can sudo to root without password, if > > 'trust' is given (which is, from what I've seen in the wild, the most common: > > the root pw is not shared, but members of wheel are allowed to 'su' to root to > > perform their actions. This is definitively not a seldom setup) > > Yes I understand that. The default setting is exactly the point here. Users > can do all kind of fun stuff if they want to. But we are responsible to ship > a > safe default configuration. We don't populate the wheel group by default - so by this defintiion, we already do have a sane default and users have to explicitly opt-in to the wheel concept;. > And if we ship this polkit rules file then we subject our users to known > security issues in PackageKit without them being aware of it. > > We can happily ship this rule file as an example file that is not part of the > active polkit configuration. Users can then use this file as a template and > it > is then in their responsibility to judge the results. Sounds like a fair compromise
CRD: 2018-04-23 16:00:00 +0200
public now. Hello list, I am forwarding this email which was previously disclosed to the linux-distros mailing list. I made only minor modifications to the original report (marked with "Update" where appropriate). Following is an analysis of PackageKit and the discussion of a number of vulnerabilities that I found to be exploitable in its context. # 1. What is PackageKit? PackageKit is a software suite designed to allow easy software installation and maintenance for end-users across distributions. It abstracts the various package management software found in today's Linux distributions and provides a unified interface for graphical user interface programs to interact with the package management. PackageKit's main component is a daemon `packagekitd` which implements a D-Bus interface. Clients can retrieve information about installed packages and can request package management actions to be performed. A backend within `packagekitd` translates the abstract PackageKit commands into actual package management commands. Backends exist for all major Linux package management systems like zypper, yum, apt and others. PackageKit is enabled by default on most if not all major Linux distributions when a fully integrated desktop environment like GNOME or KDE is installed. For the purposes of this analysis I looked into openSUSE Leap 42.3, Debian 9 Strech, Ubuntu 17.10, CentOS 7.4.1708 and Fedora 27 which covers the major backends zypper, apt, yum and dnf. I will leave out the version numbers for the rest of this analysis for brevity. There exist a number of additional backends that I did not look into. Upstream repository: https://github.com/hughsie/PackageKit.git Upstream website: https://www.freedesktop.org/software/PackageKit/ # 2. PackageKit's Security Approach PackageKit uses the polkit permissions framework to authorize individual operations. It has been a code review of the implementation of these polkit actions within PackageKit that led me to the findings discussed in this analysis. One important decision that upstream made is that it is deemed safe that regular users can install validly signed packages in the system without requiring administrator authentication. The motivation for this seems to be improved usability for end users. This is also documented here: https://github.com/hughsie/PackageKit/blob/master/policy/org.freedesktop.pa= ckagekit.policy.in#L33 > - Normal users do not need authentication to install signed packages > from signed repositories, as this cannot exploit a system. > - Paranoid users (or parents!) can change this to 'auth_admin' or > 'auth_admin_keep'. The related polkit action is named `org.freedesktop.packagekit.package-inst= all`. The Linux distributions considered in this analysis ship a polkit policy file that requires `auth_admin` or `auth_admin_keep` for the installation of signed packages as well. However, there is also a custom polkit rule shipped by PackageKit that allows local users in an active session and that are members of the group `wheel` to install signed packages without admin authorization: https://github.com/hughsie/PackageKit/blob/master/policy/org.freedesktop.pa= ckagekit.rules This rule file is installed on openSUSE, Fedora and CentOS unmodified. Ubuntu and Debian ship a different rule file that does not allow this. # 3. Installation of Signed Packages without Administrator Authentication (= Security Issue 1) During my code review I found a section of code that indicated that regardless of what the polkit configuration consists of it is always possible to install signed packages without any form of authentication. The relevant code location is here: https://github.com/hughsie/PackageKit/blob/master/src/pk-transaction.c#L2354 If reinstallation of packages is allowed, then an authentication attempt is made by `packagekitd` but the outcome is ignored. The flag `PK_TRANSACTION_FLAG_ENUM_ALLOW_REINSTALL` is under user control, however. There is currently no way to avoid this loophole in PackageKit by means of configuration files. PackageKit comes with a command line utility called `pkcon` that can be used to perform PackageKit operations. There are two general possibilities how to install packages: - `pkcon install [options] <package>` installs a package from the configured package manager system repositories by name. - `pkcon install-local [options] <package>` installs a package from a user supplied package manager archive file (e.g. rpm or deb archive). The reinstall loophole can be used interactively like this: ``` # performed on CentOS 7.4.1708, the download paths in /var/cache differ # between distributions. $ pkcon install --only-download zsh $ pkcon install-local --allow-reinstall /var/cache/yum/x86_64/7/base/packag= es/zsh-5.0.2-28.el7.x86_64.rpm ``` The second `pkcon` call will trigger the authentication dialog, but even if the password is wrong or the dialog is canceled, the installation of the package will continue. The only distribution I looked into that does not allow this is Fedora which seems to use the dnf backend instead of the yum backend. The current Fedora release can therefore be considered not affected by the issues discussed in this analysis. Update: This security issue was assigned CVE-2018-1106. The bugfix performed by upstream is found in attachment 0001-Do-not-set-JUST_REINSTALL-on-any-kind-of-auth-failur.patch. # 4. Downgrade of Existing Packages (Security Issue 2) Even though installation of signed packages by regular users is considered safe by upstream, it should not be possible to downgrade existing packages. A separate polkit action `org.freedesktop.packagekit.package-downgrade` should be triggered in this case. The individual PackageKit backends are responsible to implement this logic, however. It turned out that not every backend implements this correctly. Using the above approach with `pkcon install-local --allow-reinstall` it is possible to downgrade even important system packages without entering the administrator password in the following cases: - apt backend (tested on Ubuntu, Debian) - zypp backend (tested on openSUSE) Only the yum and dnf backends (tested on CentOS, Fedora) implement the downgrade protection correctly. Using this possiblity a regular user can downgrade packages to vulnerable versions that open up further attack vectors for gaining privileges. I have attached a number of proof of concept scripts that demonstrate this: - `pk_downgrade_debian_bash.py`: this downgrades bash on Debian 9 Stretch to an old one that is still vulnerable to "Shell Shock". - `pk_downgrade_opensuse_systemd.py`: This downgrades systemd on openSUSE version 228 that is vulnerable to CVE-2016-10156. This one is accompanied by `opensuse_exploit_systemd.py` to complete the root exploit. This is not a 100 % root exploit, it requires some extra opportunity that requires systemd to create a new timer stamp file in /var/lib/systemd/timers. # 5. Installation of Signed Packages is Still Dangerous (Security Issue 3) Even if a user is not able to downgrade existing packages without administrator privileges there is still a security issue to consider. A regular user can install local package files downloaded from the Internet that carry a valid signature. When the package in question is not installed yet in the system then this does not count as a downgrade but as a fresh installation. This opens a surprisingly large action space to regular users: - tools for constructing exploits can be easily obtained from the system repositories or the Internet. - outdated software with known bugs can be installed in some circumstances. On some distributions year old packages with valid signatures can be installed this way. - packages can contain scriptlets for performing runtime package setup. These scriptlets may provide additional attack surface when they can be triggered at the discretion of regular users. I have attached two further PoC scripts that demonstrate some of these points: - `pk_root_debian_ntfs3g.py`: This installs an old ntfs-3g package on Debian that is vulnerable to CVE-2017-0358 and exploits it. This variant works only if the `fuse` kernel module is not yet loaded. - `pk_root_ubuntu_firejail.py`: This installs an old firejail package on Ubuntu that is vulnerable to CVE-2017-5180 and exploits it. On CentOS I have been able to construct an attack (no PoC) using CentOS 7.0 packages for abrt 2.1.11-12.el7 which is vulnerable to CVE-2015-1862. This only worked if abrt was not yet installed, however (and it is installed by default). There may be systems out there that fulfill this condition though. These PoCs also show that all necessary tools like compiler, kernel headers etc. can be easily installed to construct the attack. My tests showed that on Ubuntu packages dating back to at least 2012 can be installed as signed packages. On Debian packages dating back to 2001 can be installed. But this may also be due to the issue described in the following section 7). On CentOS 7.4 any packages dating back to CentOS 7.0 can be installed as signed packages. On openSUSE Leap 42.3 packages =66rom openSUSE 11.4 dating from the year 2012 can be installed as signed packages. On Fedora (27) only packages for the same major/minor version can be installed. There exist probably other attacks that can be constructed by installing outdated packages this way. # 6. Missing Sanitization and Safety Measure of User Supplied Input Files I followed the track of the user supplied archive paths passed to `packagekitd` to find out how the user owned archives are handled by the daemon. It turned out that the common `packagekitd` code takes no precautions to copy the file into a safe space that is no longer accessible by the client. This is the job of the backends. The zypp and yum backends do this and copy the file over into a temporary directory owned by root. They subsequently build a local RPM repository from the copied RPM file and operate on it. The apt backend, however, does not do this. The path passed from the client is passed unmodified into the libapt-pkg code. I am not sure whether the libapt-pkg code is prepared to process a file under user control. My worry was and is that there could be race condition involved that would allow the user to replace all or part of the supplied deb archive by something malicious after the signature verification passed. I also found that the client side code makes some effort to sanitize archive paths in `pk_client_convert_real_paths()`: https://github.com/hughsie/PackageKit/blob/master/lib/packagekit-glib2/pk-c= lient.c#L308 The daemon code itself performs no such sanitization, however. I have not found any actual attack vectors based on this yet. But it is possible to pass symlink paths and relative paths to the daemon and the daemon passes it to its backends. I am just adding this to the report for completeness, maybe someone else is interested in this and finds out more. # 7. Lacking Signature Check in the apt backend? (Security Issue 4) While I looked into the situation described in 6) I encountered an even worse condition in the apt backend: It seems to be possible to install modified deb packages without admin authentication. This is demonstrated in the attached PoC `pk_apt_install_modified.py`. This PoC works on Debian and Ubuntu. It downloads a validly signed package, injects a setuid-root binary, installs it and runs it to gain root privileges. I have not further analyzed where this security leak originates, because I am not familiar with the libapt-pkg code and I need the help of the community to identify possible further security issues involved. Update: I was told by Debian maintainers that individual deb packages don't carry a signature but only repositories. So it looks like the apt backend would need to handle installation of local deb files completely different to perform signature verification. # 8. Affected Versions The basic issue described in 3) that allows to circumvent the polkit configuration was introduced via git commit: f176976e24e8c17b80eff222572275517c16bdad and affected versions include >=3D 1.0.10 up until current 1.1.9. The missing downgrade protection described in 4) has probably been always present in the affected backends but I did not check up on it. The issue of installing new signed packages without admin authorization as described in 5) is by PackageKit design and exploitability depends on the distribution's configuration and on the existence of issue 3). Since I don't know what exactly the problem is that causes modified packages to be installed in the apt backend as described in 7) I can't make any statements here at the moment. Update: With security issue 1 (CVE-2018-1106) fixed, the other findings in this report should not pose an immediate danger as long as the polkit configuration requires root privileges for the involved polkit actions. Only administrators should then be able to reach the code paths in question. # 9. Recommendations My personal recommendation to prevent the issues described in 3), 4) and 5) is to not allow regular users to perform any of the involved actions without admin authentication. To achieve this there must be no code in place that circumvents the polkit configuration. The upstream polkit rules file that allows active local users in the group wheel to install packages without authentication should be dropped. Update: The attached patch provided by upstream will fix security issue 3) and thereby allow to configure PackageKit safely. Regarding the issue described in 4) the backends should additionally correctly implement the detection of downgrades and call the appropriate polkit actions. Regarding the issue described in 7) I have not enough insight to give any recommendation (except of course, not to allow installation of untrusted packages without at least asking for authorization for org.freedesktop.packagekit.package-install-untrusted). The discussed PackageKit backends may be used by other distributions than considered in this report. These distributions should be identified and checked as well. Also the less widespread backends that have not been considered in this analysis should be checked for their behaviour and affectedness. # 10. Timeline - 2018-03-26: I found out about the issues described in 3) and 4) and conta= cted upstream about the issue and voiced some general concerns. Upstream basically told me installing signed packages without authentication is "by design" and unless I can show some working exploit this would not be wort= h a CVE. Preventing downgrades would be the job of the backends and is no iss= ue in packagekitd itself. - 2018-04-03: After further analysis and testing I was able to devise the PoCs presented in 5). - 2018-04-05: I noticed the situation described and exploited in 7). - 2018-04-09: Finished writing this report and putting together PoCs. Published on linux-distros. - 2018-04-11: Red Hat Product Security assigned CVE-2018-1106 for security issue 1 described in 3). - 2018-04-23: Published on oss-sec. Cheers Matthias
SUSE-SU-2018:1047-1: An update that fixes one vulnerability is now available. Category: security (important) Bug References: 1086936 CVE References: CVE-2018-1106 Sources used: SUSE Linux Enterprise Workstation Extension 12-SP3 (src): PackageKit-1.1.3-24.6.1 SUSE Linux Enterprise Software Development Kit 12-SP3 (src): PackageKit-1.1.3-24.6.1 SUSE Linux Enterprise Server 12-SP3 (src): PackageKit-1.1.3-24.6.1 SUSE Linux Enterprise Desktop 12-SP3 (src): PackageKit-1.1.3-24.6.1
openSUSE-SU-2018:1049-1: An update that fixes one vulnerability is now available. Category: security (important) Bug References: 1086936 CVE References: CVE-2018-1106 Sources used: openSUSE Leap 42.3 (src): PackageKit-1.1.3-5.3.1
This is an autogenerated message for OBS integration: This bug (1086936) was mentioned in https://build.opensuse.org/request/show/601533 Factory / PackageKit
This is an autogenerated message for OBS integration: This bug (1086936) was mentioned in https://build.opensuse.org/request/show/605366 15.0 / PackageKit
All affected code stream are fixed. Closing bug.