dx-packages team mailing list archive
-
dx-packages team
-
Mailing list archive
-
Message #43476
[Bug 1900255] Re: accountsservice drop privileges denial of service (GHSL-2020-187, GHSL-2020-188)
** Information type changed from Private Security to Public Security
--
You received this bug notification because you are a member of DX
Packages, which is subscribed to accountsservice in Ubuntu.
Matching subscriptions: dx-packages
https://bugs.launchpad.net/bugs/1900255
Title:
accountsservice drop privileges denial of service (GHSL-2020-187,
GHSL-2020-188)
Status in accountsservice package in Ubuntu:
Fix Released
Bug description:
# GitHub Security Lab (GHSL) Vulnerability Report: `GHSL-2020-187`,
`GHSL-2020-188`
The [GitHub Security Lab](https://securitylab.github.com) team has
identified potential security vulnerabilities in
[accountsservice](https://git.launchpad.net/ubuntu/+source/accountsservice/).
We are committed to working with you to help resolve these issues. In
this report you will find everything you need to effectively
coordinate a resolution of these issues with the GHSL team.
If at any point you have concerns or questions about this process,
please do not hesitate to reach out to us at `securitylab@xxxxxxxxxx`
(please include `GHSL-2020-187` or `GHSL-2020-188` as a reference).
If you are _NOT_ the correct point of contact for this report, please
let us know!
## Summary
The accountsservice daemon drops privileges to perform certain
operations. For example while performing the
`org.freedesktop.Accounts.User.SetLanguage` D-Bus method, which can be
triggered by an unprivileged user, accounts-daemon temporarily drops
privileges to the same UID as the user, to avoid being tricked into
opening a file which the unprivileged user should not be able to
access. Unfortunately, by changing its
[RUID](https://en.wikipedia.org/wiki/User_identifier#Real_user_ID) it
has given the user permission to send it signals. This means that the
unprivileged user can send accounts-daemon a `SIGSTOP` signal, which
stops the process and causes a denial of service.
## Product
[accountsservice](https://git.launchpad.net/ubuntu/+source/accountsservice/)
## Tested Version
* accountsservice, version 0.6.55-0ubuntu12~20.04.1
* Tested on Ubuntu 20.04.1 LTS
Note: I believe these issues only exist in Ubuntu's version of
accountsservice. I couldn't find the vulnerable functions in the git
repos maintained by
[freedesktop](https://gitlab.freedesktop.org/accountsservice/accountsservice)
or [debian](https://salsa.debian.org/freedesktop-
team/accountsservice). I originally discovered the vulnerable code in
the version of the code that I had obtained by running `apt-get source
accountsservice`, but I struggled to figure out where it came from
when I started searching the official repositories. I eventually
tracked it down to this patch file: [0010-set-
language.patch](https://git.launchpad.net/ubuntu/+source/accountsservice/tree/debian/patches/0010
-set-language.patch?h=ubuntu/focal-
updates&id=e0347185d4c5554b026c13ccca691577c239afd5).
## Details
### Issue 1: accountsservice drop privileges `SIGSTOP` denial of
service (`GHSL-2020-187`)
A [source code
patch](https://git.launchpad.net/ubuntu/+source/accountsservice/tree/debian/patches/0010
-set-language.patch?h=ubuntu/focal-
updates&id=e0347185d4c5554b026c13ccca691577c239afd5) that (as far as I
know) only exists in Ubuntu's version of accountsservice, adds a
function named
[`user_drop_privileges_to_user`](https://git.launchpad.net/ubuntu/+source/accountsservice/tree/debian/patches/0010
-set-language.patch?h=ubuntu/focal-
updates&id=e0347185d4c5554b026c13ccca691577c239afd5#n66):
```c
static gboolean
user_drop_privileges_to_user (User *user)
{
if (setresgid (user->gid, user->gid, -1) != 0) {
g_warning ("setresgid() failed");
return FALSE;
}
if (setresuid (accounts_user_get_uid (ACCOUNTS_USER (user)), accounts_user_get_uid (ACCOUNTS_USER (user)), -1) != 0) {
g_warning ("setresuid() failed");
return FALSE;
}
return TRUE;
}
```
This function is used to drop privileges while doing operations on
behalf of an unprivileged user. Dropping the
[EUID](https://en.wikipedia.org/wiki/User_identifier#Effective_user_ID)
is a sensible precaution, which prevents accountsservice from
accessing a file which the unprivileged user cannot access themselves.
Unfortunately, dropping the
[RUID](https://en.wikipedia.org/wiki/User_identifier#Real_user_ID) has
the opposite effect of making security worse, because it enables the
unprivileged user to send signals to accountsservice. For example,
they can send a `SIGSTOP` which stops the accountsservice daemon and
causes a denial of service.
The vulnerability can be triggered via multiple different D-Bus
methods. Many of them involve precise timing to send the `SIGSTOP`
signal at just the right moment. But there is a much simpler and more
reliable way to reproduce the vulnerability by combining the privilege
dropping vulnerability (`GHSL-2020-187`) with the infinite loop
vulnerability (`GHSL-2020-188`), which is described next. So please
see the description of `GHSL-2020-188`, below, for a proof-of-concept
that triggers both vulnerabilities.
#### Impact
An unprivileged local user can cause a local denial of service that
affects all users of the system. Stopping the accountsservice daemon
prevents the login screen from working, because `gdm3` needs to talk
to accounts-daemon (via D-Bus).
Unfortunately, the impact is worse than just local denial of service,
because this vulnerability can be chained with a separate
vulnerability in gdm3 to achieve privilege escalation. Please see the
description of `GHSL-2020-188`, below, for a proof-of-concept of the
privilege escalation vulnerability.
#### Remediation
When dropping privileges, only drop the EUID and not the RUID.
### Issue 2: accountsservice `.pam_environment` infinite loop
(GHSL-2020-188)
A [source code
patch](https://git.launchpad.net/ubuntu/+source/accountsservice/tree/debian/patches/0010
-set-language.patch?h=ubuntu/focal-
updates&id=e0347185d4c5554b026c13ccca691577c239afd5) that (as far as I
know) only exists in Ubuntu's version of accountsservice, adds a
function named
[`is_in_pam_environment`](https://git.launchpad.net/ubuntu/+source/accountsservice/tree/debian/patches/0010
-set-language.patch?h=ubuntu/focal-
updates&id=e0347185d4c5554b026c13ccca691577c239afd5#n366):
```c
static gboolean
is_in_pam_environment (User *user,
const gchar *property)
{
gboolean ret = FALSE;
const gchar *prefix;
FILE *fp;
g_autofree gchar *pam_env = NULL;
if (g_strcmp0 (property, "Language") == 0)
prefix = "LANG";
else if (g_strcmp0 (property, "FormatsLocale") == 0)
prefix = "LC_TIME";
else
return FALSE;
pam_env = g_build_path ("/", accounts_user_get_home_directory
(ACCOUNTS_USER (user)), ".pam_environment", NULL);
if (!user_drop_privileges_to_user (user))
return FALSE;
if ((fp = fopen (pam_env, "r"))) {
gchar line[50];
while ((fgets (line, 50, fp)) != NULL) {
if (g_str_has_prefix (line, prefix)) {
ret = TRUE;
break;
}
}
fclose (fp);
}
user_regain_privileges ();
return ret;
}
```
This function parses the contents of a file named `.pam_environment`
in the (unprivileged) user's home directory. The user can trigger an
infinite loop by creating a symlink to `/dev/zero`:
```bash
ln -s /dev/zero ~/.pam_environment
```
The infinite loop can then be triggered by sending a D-Bus message to
the accountsservice daemon:
```bash
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply=literal /org/freedesktop/Accounts/User`id -u` org.freedesktop.Accounts.User.SetLanguage string:kevwozere &
```
Because the accountsservice daemon is now stuck in an infinite loop,
and has dropped privileges, it is now easy to also demonstrate
`GHSL-2020-187`:
```bash
kill -SIGSTOP `pidof accounts-daemon`
```
The accountsservice daemon is now unresponsive, which means that the
GNOME login screen no longer works. Unfortunately, this vulnerability
can be chained with a separate vulnerability in gdm3 (which I have
reported simultaneously to GNOME) to get privilege escalation. The
steps (tested on Ubuntu Desktop 20.04.1 LTS) are as follows:
* An unprivileged user logs into their account.
* They send a `SIGSTOP` to accountsservice, using the instructions above.
* They log out of their account.
* They open a text console (usually with a key combination such as Ctrl-Alt-F3).
* They login to the text console.
* They send accounts-daemon a `SIGSEGV`, followed by a `SIGCONT`, which causes accounts-daemon to crash.
* Because the accountsservice daemon was unresponsive, gdm3 is under the mistaken impression that there are zero user accounts on the system. So it triggers `gnome-initial-setup`, because it thinks this is a first-time installation.
* The user clicks through the `gnome-initial-setup` dialog boxes and creates a new account for themselves. The new account is a member of the `sudo` group.
I have made a video of this proof-of-concept, which you can see
[here](https://drive.google.com/file/d/1rpRbXW1PRKMKRcxft3x-
9tprjEbHLgOQ/view?usp=sharing). The video is only visible to people
who have the link, so it as safe as long as you are careful who you
share the link with.
#### Impact
An unprivileged local user can cause a local denial of service that
affects all users of the system. Making the accountsservice daemon
unresponsive prevents the login screen from working, because `gdm3`
needs to talk to accounts-daemon (via D-Bus).
Unfortunately, the impact is worse than just local denial of service,
because this vulnerability can be chained with a separate
vulnerability in gdm3 to achieve privilege escalation, as explained in
the proof-of-concept above.
#### Remediation
I would recommend using `fstat` to check that the file is a regular
file before reading it.
## Credit
These issues were discovered and reported by GHSL team member
[@kevinbackhouse (Kevin
Backhouse)](https://github.com/kevinbackhouse).
## Contact
You can contact the GHSL team at `securitylab@xxxxxxxxxx`, please
include a reference to `GHSL-2020-187` or `GHSL-2020-188`in any
communication regarding this issue.
## Disclosure Policy
This report is subject to our [coordinated disclosure
policy](https://securitylab.github.com/disclosures#policy).
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/accountsservice/+bug/1900255/+subscriptions