there seems to be some interest in this, so i thought i would post my notes,
made more presentable.

here i detail ways to use ssh to restrict access to the filesystem as well as
X, mitigating the 'security nightmare' that is X11, not to mention preventing
possible leaking of local data. this uses more proven code so may be better
than eg virtualization for some things.

comments/questions/corrections/etc welcome. i'm sure i missed something.

this subject of isolating untrusted programs has been coming up recently,
though mostly in regards to web browsers (firefox, xombrero). now i don't use
firefox (or any 'modern browser'), but other X programs i have tested work
fine (xpdf mplayer xloadimage djview4 feh).  there are some that don't seem
to work that i haven't tracked down the exact cause yet (qiv zathura; something
to do with glib). this works well with w3m+feh for me though.

if someone is ambitious enough to try firefox, for a start, they should read
faq 10.16 which has a basic method of working out dependences, though i've
expanded on that here.

also Johnathon Thornburg's work here saved me some time, and gets into the
security issues:
  http://marc.info/?l=openbsd-misc&m=141616701418506&w=1

still, i'm not sure you can do this for firefox, but this may get you started.
if not, your best bet may be J. Thornburg's method here:
  https://marc.info/?l=openbsd-misc&m=141867559504962&w=2
which you should read anyway.

much of the rest of the information is spread around various man pages (eg
sshd_config(5))

also note Xephyr is required for some programs using 'ssh -X' eg xpdf


0. intro

for simplicity, i will be setting up a single jail for multiple programs.
you could isolate each program with it's own user and jail. one issue though
would be that many dependencies would be duplicated. on the other hand you
could then use ssh's ForceCommand.

for future reference, i will assume there is a user:

/etc/passwd:
    _inmate:*:1111:1111:public jail account:/home/cell:/bin/sh

/etc/group:
    _chaingang:*:1111:


1. setting up ssh to chroot:

you need to add an entry like the following to /etc/ssh/sshd_config:

Match User _inmate
       ChrootDirectory /home/jail
       AuthorizedKeysFile /home/jail.authorized_keys
       X11Forwarding yes
       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand xpdf /tmp/*pdf
 
you may have to tweak this a bit depending on your use.

if you are using X11 programs you will need "X11Forwarding yes"

if you are using a terminal (eg a console web browser) you may need "PermitTTY
yes". (some X programs also require a terminal for some functions eg mplayer).

if you are using a single command, you will want to use ForceCommand.

remember also that the authorized_keys file must be owned by _inmate, but
in the above example i keep it outside of the jail so the user doesn't have
access.

N.B. remember that when the user's directory is processed, the home directory
in /etc/passwd will be appended to the above ChrootDirectory. in our example,
the ChrootDirectory is /home/jail and the user _inmate's home directory in
/etc/passwd is /home/cell, which ssh will be combine into /home/jail/home/cell.

example using ForceCommand:

Match User _inmate
       ChrootDirectory /home/jail
       AuthorizedKeysFile /home/jail.authorized_keys
       X11Forwarding no
       AllowTcpForwarding no
       PermitTTY yes
       ForceCommand w3m -B


2. setting up basic chroot filesystem

there are some files you need in the chroot in order for various programs to
function, at a minimum you need shared library support and the user's homedir:

essential user files
  /home/jail/home/cell/
  /home/jail.authorized_keys
(must be owned by user ie _inmate)

NOTE: all following files are relative to chroot directory ($_chroot), in
this case /home/jail. for the most part you can 'cp -p file $_chroot/file'.

to handle shared libs (required):
  /sbin/ldconfig
  /usr/libexec/ld.so
  /var/run/
after these files are installed, you will need to run ldconfig
  $ chroot $_chroot ldconfig /usr/{,X11R6,local}/lib
which will create /var/run/ld.so.hints.

basic directories that are needed:
  /bin
  /sbin
  /etc
  /usr/{,X11R6,local}/lib
  /tmp

and since we are going to be installing packages, create:
  /var/db/pkg/

to run X you will need a minimum:
  /etc/fonts/
  /usr/X11R6/lib/X11/fonts/
  /usr/X11R6/bin/xauth

you will also need the shared libraries xauth depends on:

  $ ldd /usr/X11R6/bin/xauth
  /usr/X11R6/bin/xauth:
          Start    End      Type Open Ref GrpRef Name
          1669e000 366a3000 exe  1    0   0      /usr/X11R6/bin/xauth
          09606000 2960a000 rlib 0    2   0      /usr/X11R6/lib/libXau.so.10.0
          0b3fd000 2b401000 rlib 0    1   0      /usr/X11R6/lib/libXext.so.13.0
          0e418000 2e41c000 rlib 0    1   0      /usr/X11R6/lib/libXmuu.so.6.0
          0092e000 209ad000 rlib 0    3   0      /usr/X11R6/lib/libX11.so.16.0
          0b40b000 2b43b000 rlib 0    1   0      /usr/lib/libc.so.77.3
          02b35000 22b3b000 rlib 0    3   0      /usr/X11R6/lib/libxcb.so.3.1
          02cbb000 22cbf000 rlib 0    1   0      
/usr/X11R6/lib/libpthread-stubs.so.2.0
          0f995000 2f99a000 rlib 0    1   0      /usr/X11R6/lib/libXdmcp.so.11.0
          055bc000 055bc000 rtld 0    1   0      /usr/libexec/ld.so

so all entries of type 'rlib' above need to be copied to the proper place
under /home/jail, eg:

for _lib in $(ldd /usr/X11R6/bin/xauth | grep ' rlib ' | awk '{printf $7" "}')
do
  [ -f $_chroot/$_lib ] || cp -p $_lib $_chroot/$_lib
done

you need a shell (required by X):
  /bin/sh
(this is needed for xauth to function. ssh calls popen() which calls execle()
with /bin/sh in order to run it. i haven't found out how to do without a shell
yet)

for dns you will need:
  /etc/resolv.conf
and maybe:
  /etc/hosts
(i have local definitions in hosts)

if you want a terminal:
  /dev/tty
  /usr/share/misc/terminfo.db
(for a session sshd_config(5) recommends:
  /dev/{null,zero,tty,stdin,stdout,stderr,arandom}

(also, ssh complains without access to /dev/ttypX files, although nothing
significant seems to happen)

there may be some things that use time:
  $ cp -R /etc/localtime $_chroot/etc/

if you add programs like ls(1) that need user/group names, you need
  /etc/pwd.db
  /etc/group
(note: without pwd.db 'ls' lodges complaints in /var/log/message)

i also have a /home/jail/tmp/ dir same as /tmp/.
files for the commands i run are copied or linked here. they should be owned
by non-_inmate, but they need read permission to be useful.


3. adding packages/dependencies:

adding a package is a bit difficult, especially with dependencies. it is
complicated and tedious. (i wrote a script for this which i include at the
end for convenience).

one method i worked out is basically:

$ (cd /usr/ports/textproc/xpdf && make print-run-depends)

which gives:

This port requires package(s) "jpeg-9a libiconv-1.14p1 ghostscript-fonts-8.11p2
png-1.6.14 openmotif-2.3.4p0" to run.

this will give the proper order needed to install them.

problems:
there are some problems you might run into here. a version of mplayer i was
testing with required libgnutls (via ldd mplayer) but gnutls was not included
as a dependency (for a reason, it wasn't one. if gnutls was already installed
it got pulled in. this particular case only lasted a while.)

there are other methods to getting the dependences, which are in my script.


4. running programs

you should alread have X running, which will be on port 6000 (DISPLAY=:0)

first you want a copy of Xephyr running (some programs will not function using
'ssh -X' without Xephyr).

  $ Xephyr :1 &

Xephyr will be listening on DISPLAY=:1 (port 6001)

now you want to use ssh to login to the jailed user _inmate, creating a
secure X11 tunnel to the Xephyr instance:

  $ env DISPLAY=:1 ssh -X _inmate@localhost xpdf /tmp/file.pdf

ssh reads in DISPLAY to know where the local end of the tunnel is (the X
server). if you do not set it as above, it will be set to the current server
as specified in DISPLAY (probably :0) and will bypass Xephyr (:1).

this will set up an X11 tunnel, probably on DISPLAY=:10 (port 6010), which is
what all programs running in the jail will use (DISPLAY will be set by ssh
automatically)

you can also set ForceCommand to run just that program:
Match User _inmate
       ChrootDirectory /home/jail
       AuthorizedKeysFile /home/jail.authorized_keys
       X11Forwarding yes
       AllowTcpForwarding no
#       PermitTTY no
       ForceCommand xpdf /tmp/*pdf

which you can run using:

  $ env DISPLAY=:1 ssh -X _inmate@localhost


since the programs i use are for existing files, i need to copy or link them
into the jail. i use a script which looks something like this:

#!/bin/sh
_jailroot=/home/jail
[ ${#1} -eq 0 ] && { echo "nothing to do"; return 0; }
if [[ "$(df -k "$1")" = "$(df -k $_jailroot/tmp)" ]];then
  ln "$1" $_jailroot/tmp
else
  cp "$1" $_jailroot/tmp
fi
env DISPLAY=:1 ssh -X _inmate@localhost xpdf /tmp/"$1"
rm $_jailroot/tmp/"$1"


appendix 1. some package quirks

some packages require some special handling. these are a few things i ran
across, but there are certainly others. this should give you an idea of some
problems you may run across.

for gdk-pixbuf, you need to manually run:

  $ sudo chroot sh -c "gdk-pixbuf-query-loaders 
>/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"

or the equivalent for that version.

the problems with pango seem to me to indicate a bigger problem. inside the
jail, pango complains and requires:

  $ pango-querymodules > '/etc/pango/pango.modules'

i have the exact package installed outside the jail, and it functions fine
without 'pango.modules', which doesn't seem to get installed normally. to
get it to work in the jail you need to:

  $ sudo chroot sh -c "pango-querymodules >/etc/pango/pango.modules"


appendix 2. scripts.

i am sending these in a different mail, so that this one is not too long.

Reply via email to