Bug 1086936 (CVE-2018-1106) - VUL-0: CVE-2018-1106: PackageKit: regular users can install and downgrade arbitrary (signed) packages without admin authorization
Summary: VUL-0: CVE-2018-1106: PackageKit: regular users can install and downgrade ar...
Status: RESOLVED FIXED
Alias: CVE-2018-1106
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents (show other bugs)
Version: unspecified
Hardware: Other Other
: P3 - Medium : Major
Target Milestone: ---
Assignee: Jonathan Kang
QA Contact: Security Team bot
URL:
Whiteboard: CVSSv3:RedHat:CVE-2018-1106:5.5:(AV:L...
Keywords:
Depends on:
Blocks:
 
Reported: 2018-03-26 16:15 UTC by Matthias Gerstner
Modified: 2019-07-19 14:37 UTC (History)
9 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---
matthias.gerstner: needinfo? (songchuan.kang)


Attachments
0001-Do-not-set-JUST_REINSTALL-on-any-kind-of-auth-failur.patch (2.28 KB, patch)
2018-04-11 15:23 UTC, Marcus Meissner
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Matthias Gerstner 2018-03-26 16:15: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
Comment 1 Matthias Gerstner 2018-03-26 16:17:22 UTC
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.
Comment 3 Matthias Gerstner 2018-03-26 16:22:24 UTC
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.
Comment 4 Matthias Gerstner 2018-03-27 10:09:18 UTC
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?
Comment 8 Matthias Gerstner 2018-04-09 14:10:20 UTC
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.
Comment 11 Matthias Gerstner 2018-04-09 14:21:36 UTC
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.
Comment 12 Scott Reeves 2018-04-11 05:26:26 UTC
(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.
Comment 16 Marcus Meissner 2018-04-11 15:23:34 UTC
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
Comment 19 Jonathan Kang 2018-04-12 10:24:07 UTC
(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?
Comment 20 Matthias Gerstner 2018-04-12 10:53:51 UTC
(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.
Comment 21 Jonathan Kang 2018-04-16 03:01:00 UTC
(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?
Comment 22 Matthias Gerstner 2018-04-16 10:38:46 UTC
(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.
Comment 23 Dominique Leuenberger 2018-04-16 10:53:15 UTC
(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
Comment 24 Dominique Leuenberger 2018-04-16 11:01:15 UTC
(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
Comment 25 Matthias Gerstner 2018-04-16 11:07:16 UTC
(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.
Comment 26 Dominique Leuenberger 2018-04-16 11:18:24 UTC
(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)
Comment 27 Matthias Gerstner 2018-04-16 12:10:45 UTC
> 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.
Comment 29 Dominique Leuenberger 2018-04-16 12:30:32 UTC
(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
Comment 39 Victor Pereira 2018-04-20 12:16:43 UTC
CRD: 2018-04-23 16:00:00 +0200
Comment 40 Marcus Meissner 2018-04-23 15:17:37 UTC
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
Comment 41 Swamp Workflow Management 2018-04-23 19:07:35 UTC
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
Comment 42 Swamp Workflow Management 2018-04-23 22:07:11 UTC
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
Comment 43 Swamp Workflow Management 2018-04-26 12:30:06 UTC
This is an autogenerated message for OBS integration:
This bug (1086936) was mentioned in
https://build.opensuse.org/request/show/601533 Factory / PackageKit
Comment 45 Swamp Workflow Management 2018-05-08 14:40:06 UTC
This is an autogenerated message for OBS integration:
This bug (1086936) was mentioned in
https://build.opensuse.org/request/show/605366 15.0 / PackageKit
Comment 47 Alexander Bergmann 2019-07-19 09:20:01 UTC
All affected code stream are fixed. Closing bug.