Coordinated Disclosure Timeline

Summary

accountsservice has a double-free bug, which can be triggered by an unprivileged local user, by calling the SetLanguage D-Bus method.

Product

accountsservice

Note: as far as we know, the bug only exists in Ubuntu’s fork of accountsservice. The bug is in a patch file named 0010-set-language.patch, which we do not believe is included on other distributions, such as Debian.

Tested Version

0.6.55-0ubuntu13.2

Tested on Ubuntu 21.10

Details

Issue 1: double-free in the SetLanguage D-Bus method (GHSL-2021-1011)

The function user_get_fallback_value has a static variable named system_formats_locale, which is allocated and initialized on the first call and then returned on subsequent calls:

static gchar *
user_get_fallback_value (User        *user,
                         const gchar *property)
{
        static gchar *system_language;
        static gchar *system_formats_locale;    <===== ONLY ALLOCATED ONCE

        if (g_strcmp0 (property, "Language") == 0 && system_language)
                return system_language;
        if (g_strcmp0 (property, "FormatsLocale") == 0 && system_formats_locale)
                return system_formats_locale;    <===== RETURNED TO CALLER
        ...

Since this memory is only allocated once, it should not be freed by the caller. However, in user_change_language_authorized_cb, the pointer is stored in a variable named fallback_locale, which has a g_autofree annotation, so the memory is freed at the end of the enclosing block:

if (!is_in_pam_environment (user, "FormatsLocale")) {

        /* set the user formats (certain LC_* variables) explicitly
           in order to prevent surprises when LANG is changed */
        g_autofree gchar *fallback_locale = user_get_fallback_value (user, "FormatsLocale");    <===== NO ALLOC
        g_autofree gchar *validated_locale = user_locale_validate (user, fallback_locale, context);
        gchar *formats_locale = user_update_environment (user,
                                                         validated_locale,
                                                         "save-to-pam-env",
                                                         context);

        if (formats_locale != NULL)
                accounts_user_set_formats_locale (ACCOUNTS_USER (user), formats_locale);
        <===== fallback_locale AUTOMATICALLY FREED HERE
}

This leads to a double free, if the SetLanguage D-Bus method is called multiple times.

An unprivileged user can trigger the bug like this:

rm -f ~/.pam_environment
dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User1001 org.freedesktop.Accounts.User.SetLanguage string:hi

The first step, deleting ~/.pam_environment, is required to trigger the vulnerable code path. If you run those instructions a few times accounts-daemon will crash due to a double-free.

Impact

This is a memory corruption vulnerability in a process that runs with root privileges, so it could be exploited by an unprivileged local attacker to escalate privileges.

Issue 2: memory leak in user_update_environment

This issue is just a regular bug, not a security vulnerability, but it might be worth fixing at the same time as the other bug.

The function user_update_environment allocates a string (in the local variable validated_data) and returns it. At all three call sites of user_update_environment the memory is not freed. The easiest one to trigger is this one in user_change_formats_locale_authorized_cb:

gchar *locale = user_update_environment (user,
                                         validated_locale,
                                         "save-to-pam-env",
                                         context);

You can (slowly) leak memory like this:

while true
do
    dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User1001 org.freedesktop.Accounts.User.SetFormatsLocale string:en_US.UTF-8
    dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User1001 org.freedesktop.Accounts.User.SetFormatsLocale string:en_GB.UTF-8
done

It leaks memory far too slowly to cause any problems, so from an attacker’s perspective it’s mainly of interest for heap grooming purposes. (The poc attached to this report does not use it though.)

CVE

Credit

This issue was discovered and reported by GHSL team member @kevinbackhouse (Kevin Backhouse).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2021-1011 in any communication regarding this issue.