5.02.2012

Capture login session with "script", chroot jail


This documents the process to restrict a user to a chroot'd env, log their session with script, and allow only ssh activities.  Specifically, I use it to lock down and track external vendors or consultants.

Tested on Red Hat 6.2, but it should work on lower RH versions just fine.  On systems without SELinux, remove those options from the commands below.

Here's the basic setup:

  • rvendor is our user for this example
  • chrooters is the group containing all of our restricted users
  • login home directory: /home/rvendor/
  • chroot directory: /home/restricted_users/chroot_jails/rvendor/
  • chroot and 'script' script location: /home/restricted_users/scripts/
  • typescript output files from 'script': /home/restricted_users/script_files/
  • all the user has access to in the chroot jail are the bash builtins, ssh, and su.  Not 100% foolproof, by any means, but it's decent.



Create the account, and a group (to be used for sudo later)

    $ grep rvendor /etc/passwd
    rvendor:x:9999:9999:chrootd vendor account:/home/rvendor:/bin/bash
    $ grep chrooters /etc/group
    chrooters::9999:


Create a script to do the actual chroot and log via "script"

    $ sudo cat /home/restricted_users/scripts/chrooter
    !/bin/bash
    FILENAME=`date +%Y%m%d-%H.%M.%S`-$USER.$$
    /usr/bin/script -qaf /home/restricted_users/script_files/$USER/$FILENAME -c "/usr/bin/sudo /usr/sbin/chroot /home/restricted_users/chroot_jails/$USER /bin/su - $USER " exit



Create the directory for the chroot'd env


    $ sudo mkdir -p /home/restricted_users/chroot_jails/rvendor/{bin,dev,etc,lib64,usr,var}
    $ sudo ln -s /home/restricted_users/chroot_jails/rvendor/usr/bin /bin
    $ sudo ln -s /home/restricted_users/chroot_jails/rvendor/usr/lib64 /lib64
    $ sudo chown -R nobody:chrooters /home/restricted_users/chroot_jails/rvendor
    $ sudo chmod -R 070 /home/restricted_users/chroot_jails/rvendor
    $ sudo ls -la  /home/restricted_users/chroot_jails/rvendor
    total 28
    d---rwx---. 7 nobody chrooters 4096 Apr 24 14:41 .
    drwxr-xr-x. 7 root   root      4096 Apr 24 14:41 ..
    d---rwx---. 2 nobody chrooters 4096 Apr 24 14:41 bin
    d---rwx---. 2 nobody chrooters 4096 Apr 24 14:41 etc
    d---rwx---. 2 nobody chrooters 4096 Apr 24 14:41 lib64
    d---rwx---. 2 nobody chrooters 4096 Apr 24 15:03 usr
    d---rwx---. 2 nobody chrooters 4096 Apr 24 14:41 var


Set up the output area for the script sessions:

    $ sudo mkdir -p /home/restricted_users/script_files/rvendor
    $ sudo chown rvendor /home/restricted_users/script_files/rvendor


Setup sudo so that the chrooters group can run chroot with no passwd

    $ sudo visudo
    >>
    %chrooters         ALL=NOPASSWD: /usr/sbin/chroot


Create the jailed account in the chrooted env

    $ sudo cat /home/restricted_users/chroot_jails/rvendor/etc/passwd
    root:LK:0:0:root:/:/bin/bash
    rvendor:x:9999:9999:chrootd vendor account:/:/bin/bash
    $ sudo cat /home/restricted_users/chroot_jails/rvendor/etc/group
    root::0:root
    chrooters::9999:


Add the required binaries  and libs (bash, ssh)
***** cp -pc to preserver file context + permissions for SELinux *****

    $ ldd /bin/bash
    linux-vdso.so.1 =>  (0x00007fffca3ff000)
    libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003b7a200000)
    libdl.so.2 => /lib64/libdl.so.2 (0x0000003b78200000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003b78600000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003b77e00000)


    $ sudo cp -pc /bin/bash /home/restricted_users/chroot_jails/rvendor/bin/bash
    $ sudo cp -pc /lib64/libtinfo.so.5 /lib64/libdl.so.2 /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2 /home/rvendor/lib64

    $ sudo cp -pc /usr/bin/ssh /home/restricted_users/chroot_jails/rvendor/usr/bin/ssh
    $ for x in `ldd /usr/bin/ssh | cut -d' ' -f3 |grep ^/` ; do sudo cp -pcH $x /home/rvendor/$x ; done

    $ sudo ls -laZ /home/restricted_users/chroot_jails/rvendor/lib64
    d---rwx---. nobody chrooters system_u:object_r:default_t:s0   .
    d---rwx---. nobody chrooters system_u:object_r:default_t:s0   ..
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       ld-linux-x86-64.so.2
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libcom_err.so.2
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libcrypto.so.10
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libcrypt.so.1
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libc.so.6
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libdl.so.2
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libfipscheck.so.1
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libfreebl3.so
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libgssapi_krb5.so.2
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libk5crypto.so.3
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libkeyutils.so.1
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libkrb5.so.3
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libkrb5support.so.0
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libnsl.so.1
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libnspr4.so
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libnss3.so
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libnssutil3.so
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libplc4.so
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libplds4.so
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libpthread.so.0
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libresolv.so.2
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libselinux.so.1
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libtinfo.so.5
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libutil.so.1
    -rwxr-xr-x. root   root      system_u:object_r:lib_t:s0       libz.so.1 



The Red Hat coreutils su is a bit different, as it is compiled with pam.
So, we'll compile our own to simplify, and remove the pam dependency.


    $ wget http://ftp.gnu.org/gnu/coreutils/coreutils-8.16.tar.xz
    --2012-05-01 12:12:42--  http://ftp.gnu.org/gnu/coreutils/coreutils-8.16.tar.xz
    Resolving ftp.gnu.org... 208.118.235.20, 2001:4830:134:3::b
    Connecting to ftp.gnu.org|208.118.235.20|:80... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 5042844 (4.8M) [application/x-tar]
    Saving to: “coreutils-8.16.tar.xz”
    100%[========================================================>] 5,042,844   --.-K/s   in 0.09s  
    2012-05-01 12:12:43 (51.3 MB/s) - “coreutils-8.16.tar.xz” saved [5042844/5042844]
    $ tar xvJf coreutils-8.16.tar.xz
    $ cd  coreutils-8.16
    $ ./configure
    $ make


Copy the su binary into position:

    $ sudo cp src/su /home/restricted_users/chroot_jails/rvendor/bin/
     Give it perms and context to match system install:
    $ sudo chmod --reference=/bin/su /home/restricted_users/chroot_jails/rvendor/bin/su
    $ sudo chcon --reference=/bin/su /home/restricted_users/chroot_jails/rvendor/bin/su
    $ sudo ls -alZ /bin/su /home/restricted_users/chroot_jails/rvendor/bin/su
    -rwsr-xr-x. root root system_u:object_r:su_exec_t:s0   /bin/su
    -rwsr-xr-x. root root system_u:object_r:su_exec_t:s0   /home/rvendor/bin/su


Check the libs to make sure we have what we need

    $ sudo ldd /home/restricted_users/chroot_jails/rvendor/bin/su
        linux-vdso.so.1 =>  (0x00007fff1cf2f000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x0000003b7ae00000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003b78600000)
        libfreebl3.so => /lib64/libfreebl3.so (0x0000003b7b200000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003b77e00000)
        libdl.so.2 => /lib64/libdl.so.2 (0x0000003b78200000)


Now we need is the libs to get us to talk to /etc/passwd /etc/group in the chroot jail

    $ sudo cp -cp /lib64/libnss_files.so.2 /lib64/libnss_compat.so.2 /home/restricted_users/chroot_jails/rvendor/lib64

   
ssh needs some entropy, so, we'll create a /dev/random, urandom, /dev/null devices
(man 4 random, man 4 null)

    $ sudo mknod -m 644 /home/restricted_users/chroot_jails/rvendor/dev/random c 1 8
    $ sudo mknod -m 644 /home/restricted_users/chroot_jails/rvendor/dev/urandom c 1 9  
    $ sudo mknod -m 666 /home/restricted_users/chroot_jails/rvendor/dev/null c 1 3
    $ sudo mknod -m 666 /home/restricted_users/chroot_jails/rvendor/dev/tty c 5 0


We need an ssh directory

    $ sudo mkdir /home/restricted_users/chroot_jails/rvendor/.ssh
    $ sudo chown rvendor.chrooters /home/restricted_users/chroot_jails/rvendor/.ssh
    $ sudo chmod 700 /home/restricted_users/chroot_jails/rvendor/.ssh

And start the known_hosts file:

    $ sudo touch  /home/restricted_users/chroot_jails/rvendor/.ssh/known_hosts
    $ sudo chown rvendor:chrooters \
       /home/restricted_users/chroot_jails/rvendor/.ssh/known_hosts
    $ sudo chmod 644 /home/restricted_users/chroot_jails/rvendor/.ssh/known_hosts




OK, at this point, the chroot jail is completely functional.   All that are available are bash builtins, and ssh, su.   We could firm it up even more by using rbash.... but then, need to move the chrooter script to the rvendor home dir.  No biggy, just not really needed at this point


Set up the user's .bash_profile to launch the chrooter script.  End the file with 'exit', so bash session log's out when script session terminates.  This effectively locks this user to only running within script session, chroot'd.

    $ sudo vi /home/rvendor/.bash_profile
    $ sudo cat  /home/rvendor/.bash_profile
    /home/restricted_users/scripts/chrooter
    exit


We'll also set the PS1 prompt to include hostname and time stamp to make tracking activity easier.   You'll need to have this in the .bash_profile (or .bashrc) on any servers downstream that the account has access to, to be useful.

    $ sudo vi /home/restricted_users/chroot_jails/rvendor/.bash_profile
    $ sudo cat  /home/restricted_users/chroot_jails/rvendor/.bash_profile
    PS1="[\t \h] \w $ "
    export PS1


Finally, create an /etc/hosts file in the chroot env with the hosts that they are going
to be connecting to.

    $ sudo vi /home/restricted_users/chroot_jails/rvendor/etc/hosts
    $ sudo cat /home/restricted_users/chroot_jails/rvendor/etc/hosts
    XXX.XXX.XXX.XXX thatserver




Here are the results

$ sudo su - rvendor
< do some stuff, ssh out of the host>


And the resulting script file:

$ sudo cat  /home/restricted_users/script_files/rvendor/20120502-13.04.00-rvendor.30824
Script started on Wed 02 May 2012 01:04:00 PM MDT
[19:04:00 thisserver] / $ ls -al
-bash: ls: command not found
[19:04:10 thisserver] / $ cd etc
[19:04:12 thisserver] /etc $ ls
-bash: ls: command not found
[19:04:12 thisserver] /etc $ cat hosts
-bash: cat: command not found
[19:04:17 thisserver] /etc $   <this is a TAB/TAB bash completion to show built-ins>
!          bind       compopt    elif       fc         if         printf     set        time       unset
./         break      continue   else       fg         in         pushd      shift      times      until
:          builtin    coproc     enable     fi         jobs       pwd        shopt      trap       wait
[          caller     declare    esac       for        kill       read       source     true       while
[[         case       dirs       eval       function   let        readarray  ssh        type       {
]]         cd         disown     exec       getopts    local      readonly   su         typeset    }
alias      command    do         exit       hash       logout     return     suspend    ulimit    
bash       compgen    done       export     help       mapfile    script     test       umask    
bg         complete   echo       false      history    popd       select     then       unalias  
[19:04:43 thisserver] /etc $ cd
[19:04:46 thisserver] / $ ssh someuser@thatserver
The authenticity of host 'thatserver (XXX.XXX.XXX.XXX)' can't be established.
RSA key fingerprint is 99:67:aa:83:60:fd:2e:2c:81:5f:cc:f4:e3:87:db:49.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'thatserver' (RSA) to the list of known hosts.
Password:
Last login: Wed May  2 13:05:09 2012 from thisserver
[13:05:10 thatserver] ~ $ hostname
thatserver
[13:05:11 thatserver] ~ $ date
Wed May  2 13:05:12 MDT 2012
[13:05:12 thatserver] ~ $ blah blah blah
-bash: blah: command not found
[13:05:16 thatserver] ~ $ exit
logout
Connection to thatserver closed.
[19:05:17 thisserver] / $ exit
logout

No comments: