Saturday, September 29, 2012

Securing Google Chrome in Ubuntu 12.04 with AppArmor and Seccomp

Yesterday I posted some custom Firefox AppArmor profiles for Ubuntu 12.04. Today I will show you how to get the most protection for Google Chrome on Ubuntu 12.04.



Before I get started with the AppArmor profiles, I would like to point out a new feature with Chrome starting with version 21.  If you are using that version or newer and are on Ubuntu 12.04 (or any distro with a 3.5+ kernel) then you can enable a second sandbox.  Chrome has long shipped with the PID/chroot sandbox, but recently they have enabled an even stronger one that will work along side the other.  This new sandbox uses the seccomp filtering code in the Linux kernel to filter system calls.

NOTE: If you are using Chrome v.22 or higher, then you do not need to perform the following actions, as the seccomp-BPF sandbox is already enabled, so you can skip to the apparmor profile section.

If you are using Chrome v.21 or older, then that version does not use the seccomp-bpf-sandbox, but the older "legacy" seccomp (non-BPF) sandbox.  You should first check to see if it is enabled.  You can check by looking at "about:sandbox" inside the Chrome URL bar.  If you see that the seccomp sandbox is not enabled, then you can follow the steps below.  Otherwise skip to the apparmor profile section.  

Enabling the seccomp sandbox


Step 1:

Run this command:

sudo cp /usr/share/applications/google-chrome.desktop ~/.local/share/applications/

This will make a copy of your original Google Chrome .desktop file and put it in your .local directory inside of home.

Step 2:

Run this command:


gedit ~/.local/share/applications/google-chrome.desktop


Step 3:

With this text file open, navigate to line 108 (or thereabout) and find the line starting with "Exec=".  Change that line to the following:


Exec=/opt/google/chrome/google-chrome --enable-seccomp-sandbox %U

Next find the line 168 (or thereabout) and add the following to the end of that line.  Be sure the line you're editing starts with "Exec=."

--enable-seccomp-sandbox

Now find line 221 (or thereabout) and do the same thing as as the previous step.  Essentially you want to make sure each "Exec" line has "--enable-seccomp-sandbox" appended to it.

Step 4:

Now, this step requires you to navigate physically (though Nautilus) to the /home/*/.local/share/applications/ directory.  It is a hidden directory, so you will have to check the "show hidden files" option in Nautilus.  Once you navigate there, find the google-chrome.desktop file and drag and drop it to your Unity panel (be sure to delete the old Chrome icon from the panel first).

Step 5:

Now click the icon on the Unity panel and make sure Chrome starts up.  If so, then in the Chrome URL bar, type the following:

about:sandbox

You should see a screen that looks like this:



All done, you are now sandboxed with both Seccomp and the legacy sandbox.



AppArmor Profile:


Now on to AppArmor.  If you are using Chromium, this AppArmor profile won't work properly. This profile will only be for Google's official Chrome and only for Ubuntu 12.04. If this doesn't satisfy your criteria, then unfortunately this profile wont be for you.

Also, before I get started, I need to point out that, just like with my Firefox profile, this profile has several peripheral profiles that go along with it for maximum protection. Fortunately, these profiles are the same as they are for Firefox (and will work with either browser).  So if you don't have them already, see my last post and grab the following profile:

Required:

browser_openjdk (this goes in /etc/apparmor.d/abstractions)
usr.lib.totem.totem-plugin-viewer

Optional (if you use Mplayer or Transmission):

usr.bin.gnome-mplayer
usr.bin.transmission-gtk

Once again, this only works with Google's official Chrome, which should be installed to the /opt/google/chrome directory. If you don't have it installed there, then you're out of luck here.

Just like with Firefox, Chrome comes with a couple of other executables, namely its sandbox and the "nacl-helper."  Also, it comes with a shell script to launch the browser.  The shell script is named "google-chrome."  The main binary is simply "chrome."  We are going to make profiles separately for each of these.  So if you have already downloaded the profiles I mentioned previously, then I can go ahead and list the various Chrome profiles now.  First up is the shell script:

Name: opt.google.chrome.google-chrome
Directory: /etc/apparmor.d/
Profile:

# Last Modified: Tue Sep 25 14:16:39 2012
#include <tunables/global>

/opt/google/chrome/google-chrome {
  #include <abstractions/base>
  #include <abstractions/bash>



  /bin/bash rix,
  /bin/dash r,
  /bin/mkdir rix,
  /bin/readlink rix,
  /bin/which rix,
  /dev/tty rw,
  /opt/google/chrome/chrome Px,
  /opt/google/chrome/google-chrome r,
  /proc/filesystems r,
  /usr/bin/dirname rix,

}

Next up is the "nacl_helper-bootstrap":

Name: opt.google.chrome.nacl_helper_bootstrap
Directory: /etc/apparmor.d/
Profile:

# Last Modified: Tue Sep 25 14:16:39 2012
#include <tunables/global>

/opt/google/chrome/nacl_helper_bootstrap {
  #include <abstractions/base>



  /opt/google/chrome/nacl_helper mr,
  /opt/google/chrome/nacl_helper_bootstrap mr,
  /proc/cpuinfo r,
  /proc/filesystems r,
  /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq r,

}

Next is the chrome-sandbox:

Name: opt.google.chrome.chrome-sandbox
Directory: /etc/apparmor.d/
Profile:


# Last Modified: Tue Sep 25 14:54:59 2012
#include <tunables/global>

/opt/google/chrome/chrome-sandbox {
  capability chown,
  capability dac_override,
  capability fsetid,
  capability setgid,
  capability setuid,
  capability sys_admin,
  capability sys_chroot,
  capability sys_ptrace,



  /etc/ld.so.cache r,
  /lib/@{multiarch}/ld-*.so* mr,
  /lib/x86_64-linux-gnu/libc-*.so mr,
  /lib/x86_64-linux-gnu/libpthread-*.so mr,
  /lib{,32,64}/ld-*.so* mr,
  /lib{,32,64}/libc-*.so* mr,
  /lib{,32,64}/libld-*.so* mr,
  /lib{,32,64}/libm-*.so* mr,
  /lib{,32,64}/libpthread-*.so* mr,
  
  /proc/ r,
  /proc/*/fd/ r,
  owner /tmp/** rw,
  @{PROC}/ r,
  @{PROC}/[0-9]*/ r,
  @{PROC}/[0-9]*/fd/ r,
  @{PROC}/[0-9]*/oom_adj w,
  @{PROC}/[0-9]*/oom_score_adj w,
  @{PROC}/[0-9]*/task/[0-9]*/stat r,

  # Transition to main chrome binary
  /opt/google/chrome/chrome rPx,
  /opt/google/chrome/chrome-sandbox r,

}

And Finally the Chrome profile itself:

Name: opt.google.chrome.chrome
Directory: /etc/apparmor.d/
Profile:

# Last Modified: Sat Sep 29 03:29:29 2012
#include <tunables/global>

/opt/google/chrome/chrome {
  #include <abstractions/audio>
  #include <abstractions/base>
  #include <abstractions/browser_openjdk>
  #include <abstractions/dbus-session>
  #include <abstractions/fonts>
  #include <abstractions/nvidia>

  network inet dgram,
  network inet stream,
  network inet6 stream,

  /bin/which rix,
  /dev/ r,
  /etc/fstab r,
  /etc/gai.conf r,
  /etc/group r,
  /etc/host.conf r,
  /etc/hosts r,
  /etc/lsb-release r,
  /etc/mtab r,
  /etc/nsswitch.conf r,
  /etc/passwd r,
  /etc/python2.7/sitecustomize.py r,
  /etc/resolv.conf r,
  /etc/udev/udev.conf r,

  owner /home/*/ r,
  /home/*/.ICEauthority r,
  /home/*/.Xauthority r,
  /home/*/.cache/dconf/user rw,
  /home/*/.cache/gnome-mplayer/plugin/gecko-mediaplayer* rw,
  /home/*/.cache/google-chrome/Default/Cache/* rw,
  /home/*/.cache/google-chrome/Default/Media*/* rw,
  /home/*/.config/dconf/user r,
  /home/*/.config/google-chrome/ r,
  /home/*/.config/google-chrome/** rwk,  
  /home/*/.config/ibus/bus/ w,
  /home/*/.config/user-dirs.dirs r,
  /home/*/.fontconfig/* r,
  /home/*/.gksu.lock r,
  /home/*/.goutputstream-* r,
  /home/*/.gtk-bookmarks r,
  /home/*/.icons/ r,
  /home/*/.local/share/icons/ r,
  /home/*/.local/share/icons/** r,
  /home/*/.local/share/mime/* r,
  /home/*/.local/share/recently-used.xbel* rw,
  /home/*/.mozilla/firefox/*.default/compatibility.ini r,
  /home/*/.mozilla/firefox/profiles.ini r,
  /home/*/.nv/GLCache/ r,
  /home/*/.nv/GLCache/** rwk,
  /home/*/.pki/nssdb/* r,
  /home/*/.pki/nssdb/*.db rwk,
  /home/*/.pulse-cookie rwk,
  /home/*/.thumbnails/normal/* r,
  /home/*/.xsession-errors r,
  owner /home/*/Downloads/ r,
  owner /home/*/Downloads/** rw,
  owner /home/*/Public/ r,
  owner /home/*/Public/** r,

  /opt/google/chrome/** r,
  /opt/google/chrome/*.so mr,
  /opt/google/chrome/PepperFlash/libpepflashplayer.so mr,
  /opt/google/chrome/chrome mrix,
  /opt/google/chrome/chrome-sandbox rPx,
  /opt/google/chrome/extensions/ rw,
  /opt/google/chrome/google-chrome Px,
  /opt/google/chrome/nacl_helper_bootstrap Px,
  /opt/google/chrome/xdg-settings Cx,

  /proc/ r,
  /proc/[0-9]*/cmdline r,
  /proc/[0-9]*/fd/ r,
  /proc/[0-9]*/io r,
  /proc/[0-9]*/maps r,
  /proc/[0-9]*/mounts r,
  /proc/[0-9]*/oom_score_adj w,
  /proc/[0-9]*/stat r,
  /proc/[0-9]*/statm r,
  /proc/[0-9]*/status r,
  /proc/[0-9]*/task/ r,
  /proc/[0-9]*/task/[0-9]*/stat r,
  /proc/cpuinfo r,
  /proc/filesystems r,
  /proc/meminfo r,
  /proc/sys/kernel/shmmax r,

  /run/resolvconf/resolv.conf r,
  /run/shm/.com.google.Chrome.* rw,
  /run/shm/com.google.Chrome.shmem.* rw,

  /selinux/ r,

  /sys/bus/pci/devices/ r,
  /sys/devices/pci[0-9]*/**/class r,
  /sys/devices/pci[0-9]*/**/device r,
  /sys/devices/pci[0-9]*/**/irq r,
  /sys/devices/pci[0-9]*/**/resource r,
  /sys/devices/pci[0-9]*/**/vendor r,
  /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq r,

  /tmp/ r,
  /tmp/* mrw,
  /tmp/.com.google.Chrome.*/ rw,
  /tmp/.com.google.Chrome.*/Singleton* w,
  /tmp/CRX_75DAF8CB7768/ rw,
  /tmp/CRX_75DAF8CB7768/* rw,
  /tmp/icedteaplugin-*/ w,
  /tmp/icedteaplugin-*/[0-9]*-icedteanp-* rw,
  /tmp/scoped_dir_*/ rw,
  /tmp/scoped_dir_*/.com.google.Chrome.* rw,
  /tmp/scoped_dir_*/CRX_INSTALL/ rw,
  /tmp/scoped_dir_*/CRX_INSTALL/** rw,
  /tmp/scoped_dir*/DECODED* rw,
  /tmp/scoped_dir_*/mccea*_[0-9]*.crx rw,

  /usr/bin/gnome-mplayer Px,
  /usr/bin/lsb_release rix,
  /usr/bin/python2.7 r,
  /usr/bin/xdg-open Cx,
  /usr/bin/xdg-settings Cx,

  /usr/include/python2.7/pyconfig.h r,
  /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/IcedTeaPlugin.so mr,
  /usr/lib/mozilla/plugins/gecko-mediaplayer-*.so mr,
  /usr/lib/mozilla/plugins/gecko-mediaplayer.so mr,
  /usr/lib/totem/totem-plugin-viewer Px,
  /usr/lib/x86_64-linux-gnu/gtk-2.0/*/immodules/*.so mr,
  /usr/lib/x86_64-linux-gnu/pango/*/modules/pango-*.so mr,
  /usr/local/lib/python2.7/dist-packages/ r,

  /usr/share/X11/XErrorDB r,
  /usr/share/glib-2.0/schemas/gschemas.compiled r,
  /usr/share/gvfs/remote-volume-monitors/ r,
  /usr/share/gvfs/remote-volume-monitors/* r,
  /usr/share/icons/ r,
  /usr/share/icons/** r,
  /usr/share/mime/** r,
  /usr/share/misc/pci.ids r,
  /usr/share/pixmaps/ r,
  /usr/share/pyshared/* r,
  /usr/share/themes/** r,

  /var/tmp/ r,
  /var/tmp/* rw,

  owner /{run,dev}/shm/pulse-shm* k,
  /{run,dev}/shm/pulse-shm* rw,


  profile /opt/google/chrome/xdg-settings {

    /bin/dash r,
    /bin/grep rix,
    /bin/readlink rix,
    /bin/sed rix,
    /bin/which rix,
    /dev/null w,
    /etc/gnome/defaults.list r,
    /etc/ld.so.cache r,
    /etc/locale.alias r,
    /home/*/.local/share/applications/google-chrome.desktop r,
    /home/*/.local/share/applications/mimeapps.list r,
    /lib/x86_64-linux-gnu/ld-*.so r,
    /lib/x86_64-linux-gnu/libc-*.so mr,
    /lib/x86_64-linux-gnu/libdl-*.so mr,
    /lib/x86_64-linux-gnu/libm-*.so mr,
    /lib/x86_64-linux-gnu/libselinux.so.* mr,
    /opt/google/chrome/xdg-settings r,
    /proc/*/maps r,
    /proc/filesystems r,
    /usr/bin/basename rix,
    /usr/bin/cut rix,
    /usr/bin/gawk rix,
    /usr/bin/mawk rix,
    /usr/bin/xdg-mime rix,
    /usr/lib/libsigsegv.so.* mr,
    /usr/lib/locale/** r,
    /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache r,

  }

  profile /usr/bin/xdg-open {
    #include <abstractions/base>


    /bin/dash r,
    /etc/gnome/defaults.list r,
    /etc/nsswitch.conf r,
    /etc/passwd r,
    /home/*/.local/share/applications/mimeapps.list r,
    /home/*/.local/share/applications/mimeinfo.cache r,
    /home/*/.local/share/mime/* r,
    /proc/*/fd/ r,
    /usr/bin/evince Px,
    /usr/bin/gnome-open rix,
    /usr/bin/gvfs-open rix,
    /usr/bin/transmission-gtk Px,
    /usr/bin/xdg-open r,
    /usr/share/applications/*.desktop r,
    /usr/share/applications/evince.desktop r,
    /usr/share/applications/gimp.desktop r,
    /usr/share/applications/mimeinfo.cache r,
    /usr/share/mime/* r,

  }

  profile /usr/bin/xdg-settings {

    /bin/cat rix,
    /bin/dash r,
    /bin/grep rix,
    /bin/readlink rix,
    /bin/sed rix,
    /bin/which rix,
    /dev/null w,
    /etc/gnome/defaults.list r,
    /etc/ld.so.cache r,
    /etc/locale.alias r,
    /home/*/.local/share/applications/google-chrome.desktop r,
    /home/*/.local/share/applications/mimeapps.list r,
    /lib/x86_64-linux-gnu/ld-*.so r,
    /lib/x86_64-linux-gnu/libc-*.so mr,
    /lib/x86_64-linux-gnu/libdbus-1.so.* mr,
    /lib/x86_64-linux-gnu/libdl-*.so mr,
    /lib/x86_64-linux-gnu/libglib-2.0.so.* mr,
    /lib/x86_64-linux-gnu/libm-*.so mr,
    /lib/x86_64-linux-gnu/libpcre.so.* mr,
    /lib/x86_64-linux-gnu/libpthread-*.so mr,
    /lib/x86_64-linux-gnu/libresolv-*.so mr,
    /lib/x86_64-linux-gnu/librt-*.so mr,
    /lib/x86_64-linux-gnu/libselinux.so.* mr,
    /lib/x86_64-linux-gnu/libz.so.* mr,
    /proc/[0-9]*/maps r,
    /proc/filesystems r,
    /usr/bin/basename rix,
    /usr/bin/cut rix,
    /usr/bin/gawk rix,
    /usr/bin/gconftool-2 rix,
    /usr/bin/mawk rix,
    /usr/bin/xdg-mime rix,
    /usr/bin/xdg-settings r,
    /usr/lib/libsigsegv.so.* mr,
    /usr/lib/locale/** r,
    /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache r,
    /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.* mr,
    /usr/lib/x86_64-linux-gnu/libffi.so.* mr,
    /usr/lib/x86_64-linux-gnu/libgconf-2.so.* mr,
    /usr/lib/x86_64-linux-gnu/libgio-2.0.so.* mr,
    /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.* mr,
    /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.* mr,
    /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.* mr,
    /usr/lib/x86_64-linux-gnu/libxml2.so.* mr,

  }
}

You will notice that I gave xdg-open and xdg-settings their own child profiles.  I did this so they can't run unconfined and so that they can't have access to all of Chrome's files.  This is far more secure than running them Ux or even ix (as the default Chromium profile in Ubuntu does).

Activating the Profile:

Type in the terminal:

cd /etc/apparmor.d/
sudo aa-enforce opt.google.chrome* usr.bin.evince

Note: if you also grabbed the other profiles for totem, mplayer and transmission, then you need to add them to the above command.

Open up Chrome to make sure it works (it should if you're using Ubuntu 12.04).  Note that this profile will only allow you to download files to /Downloads.  Just a heads up.

You now have three separate sandboxes for Chrome and are running the most secure general purpose browser setup available, imo.

If you have any questions feel free to comment.

5 comments:

  1. Hi, thanks for sharing this stuff.

    After applying your Google Chrome AppArmor profile Google Chrome reports it's not set as default browser. Every time I start browser I am getting the question if I want to set it as default one.

    System Settings -> Details -> Default Application shows Google Chrome being default, and it was default browser before applying your rules.

    Do you have and clue what restriction is responsible for this behavior?

    ReplyDelete
  2. Take a look at /var/log/syslog and see what the exact error is. Post it here and I'll try to help.

    ReplyDelete
  3. I have solved that with adding

    /usr/local/share/applications/google-chrome.desktop r,

    to 'profile /usr/bin/xdg-settings {' in /etc/apparmor.d/opt.google.chrome.chrome file.

    There was also a problem with printing. I have solved this with adding read permission to /etc/cups/ppd/ directory.

    ReplyDelete
  4. Hi, I applied the profiles to chrome and firefox...everything seems to be working on the firefox side of things. I can't open chrome AT ALL. /var/log/syslog says:

    Apr 19 16:33:28 patricia-Inspiron-1440 kernel: [ 540.391261] type=1400 audit(1366403608.862:50): apparmor="DENIED" operation="open" parent=1 profile="/opt/google/chrome/chrome" name="/proc/2958/auxv" pid=2958 comm="chrome" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
    Apr 19 16:33:28 patricia-Inspiron-1440 kernel: [ 540.394404] type=1400 audit(1366403608.862:51): apparmor="DENIED" operation="open" parent=2958 profile="/opt/google/chrome/chrome-sandbox" name="/lib/i386-linux-gnu/libpthread-2.15.so" pid=2966 comm="chrome-sandbox" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
    Apr 19 16:33:28 patricia-Inspiron-1440 kernel: [ 540.394464] type=1400 audit(1366403608.862:52): apparmor="DENIED" operation="open" parent=2958 profile="/opt/google/chrome/chrome-sandbox" name="/lib/i386-linux-gnu/libpthread-2.15.so" pid=2966 comm="chrome-sandbox" requested_mask="r" denied_mask="r" fsuid=0 ouid=0


    so it looks like the chrome-sandbox profile...what to do??

    ReplyDelete
  5. I did this all , but google does not open anymore
    and I got this messge on the terminal
    mkdir: cannot create directory `/home/daniel': Permission denied
    /usr/bin/google-chrome: line 25: /usr/bin/touch: Permission denied
    /usr/bin/google-chrome: line 42: /opt/google/chrome/chrome: No such file or directory

    ReplyDelete