5

I am about to develop a little script to gather information for a chroot-jail.

In my case this looks (at the first glance) pretty simple: The application has a clean rpm-install and did install almost all files into a sub-directory of /opt.

My idea is:

  • Do a find of all binaries
  • Check their library-dependencies
  • Record the results into a list
  • Do a rsync of that list into the chroot-target-directory before startup of the application

Now I wonder - ist there any script around that already does such a job (perl/bash/python)?

So far I found only specialized solutions for single applications (like sftp-chroot).

Although is does not matter (imho) - OS is CentOS 5 x86_64 current minor release and patch-level.

rpm -ql is IMHO not generic enough, since it will only cover rpm-based distributions. The mention of the "clean install" above was just to mention that the files of the software are not distributed across the whole file-system. So my starting point is - at the moment - a find /opt/directory/... that should work on almost any system (even not Linux).

voretaq7
  • 79,879
  • 17
  • 130
  • 214
Nils
  • 7,695
  • 3
  • 34
  • 73
  • So you want to move the installation to another directory, something the ancient software vendor won't support (if the company even still exists)? Doesn't sound very wise to me. The easy solution is to throw it in a virtual machine. – Michael Hampton Oct 19 '12 at 20:20
  • @MichaelHampton No matter if it's easy, it's not necessarily feasible. As a professional I regulary have to deal with proprietary 3rd party software which needs legacy libraries. No matter if you want to keep it at it's current location, move it to a jail/chroot-envrionment or to a VM, it's clearly on-topic. – Alexander Janssen Oct 19 '12 at 20:24
  • @AlexanderJanssen I didn't vote to close this question. – Michael Hampton Oct 19 '12 at 20:26
  • @MichaelHampton Oh, I didn't meant to imply that. The question is interesting nonetheless. – Alexander Janssen Oct 19 '12 at 20:31
  • @Nils What OS and distribution are you using anyway? – Alexander Janssen Oct 19 '12 at 21:43
  • I started working on a script, but it doesn't work yet. Maybe someone wants to improve it: https://gist.github.com/e006fa8b3d0127a788c9 – Alexander Janssen Oct 19 '12 at 21:47
  • @MichaelHampton this is already in a VM. BUT this thing has to operate as root. So VM (in a DMZ), inbound and outbout firewall are not enough to give me a good feeling - this service is going to be contacted from the outside, from an external network, that is not "secure". – Nils Oct 20 '12 at 20:17
  • @AlexanderJanssen I had a similar thought for building the script. Then I realized two things: a) libraries can include other libraries not accounted for in the first `ldd` pass - I solved that by doing a ldd-iteration until the result-set does not increase any longer. I will post my current script as an answer, so you all can look over it. b) next problem: There are a number of shell-scripts involved, that call binaries, too (not too many in my case). I will update my question with details for the OS. – Nils Oct 20 '12 at 20:23
  • http://wiki.debian.org/Debootstrap for a Debian/Ubuntu solution. BTW, you need good separation look at LXC, not a chroot. http://lxc.sourceforge.net/ – Zoredache Oct 20 '12 at 21:48
  • @Zoredache lxc looks interesting and might accomplish my goal, too (more like my initial bind-ro-mount attempt). And it seems to be easier than putting up SELinux-rules. Can you make **lxc** an answer of its own, so I can upvote it? – Nils Oct 21 '12 at 19:23

4 Answers4

2

I would suggest creating a template chroot and installing all the packages you want just like it was a normal OS. After that you can manage the chroot using your typical tools (update scripts, package manager, etc.) and rsync the updates into each chroot built using that template.

There are a few advantages to this approach. The two big ones are you can manage the template using familiar tools (no strange hoops to jump through to upgrade your chroot), and if you have one chroot which can't be updated for some reason (say it needs a particular version of some package) you can exclude it from the rsync upgrade process and manage it independently as though it were a standalone machine, marking the package as "held" or equivalent so it doesn't get stomped on.

Your mileage (and implementation requirements) may vary...

voretaq7
  • 79,879
  • 17
  • 130
  • 214
  • I think I will go somewhat in that direction by putting "standard" binaries like `sed`, `awk`, `find`, ... into that chroot.environment, too. I would not go too far there - if an attacker can break into this environment, he/she should not find too many "useful" tools. – Nils Oct 20 '12 at 20:33
  • 1
    you're missing the point - you would not put the binaries in the chroot - you would install the package(s) that provide the binaries, so that when someone finds a major security hole in `sed` tomorrow you don't have to worry about which version of `sed` you installed: Just make sure the package providing it is up to date :-) – voretaq7 Oct 20 '12 at 21:41
  • that is why I want to make an rsync into the chroot-environmelnt on startup. If the original gets patched, so will the chroot-copy. I`ve seen worse things. SLES10 bind copies all needed libs and binaries into the chroot on startup. Regardless if they have changed or not. – Nils Oct 21 '12 at 19:18
0

First approach (service is the application itself): Do a bind-ro-mount in the chroot for all the "usual" binaries, libs, etc...:

  • /etc
  • /bin
  • /usr
  • /lib
  • /lib64
  • /var
  • /home/used_accounts
  • /opt/service

Now this was ok to test if the service runs in the chroot. To my astonishment my HIDS told me that there was a write located in a sub-directory in /opt/service.

So I manually chrooted into this with a shell and tested write-access - which worked!

So if nothing else helps - RTFM. man mount hinted that a read-only-bind-mount only works with kernel 2.6.26 or greater (bad luck here: CentOS 5 is 2.6.18).

Another drawback: This leaves a potential attacker with the full set of operating-system-tools.

0xC0000022L
  • 1,516
  • 2
  • 22
  • 42
Nils
  • 7,695
  • 3
  • 34
  • 73
0

Now this is, where my scipt is at the moment:

mkchroot.cfg:

# Configuration file for building a chroot envirnoment with Linux
#
# V 1.2 2012-10-24
#
# Define which directories to scan for executables
#  use space to separate directories
DIRS="/opt/application /opt/bin"
#
# Define a number of files to check outside the dirctories set in the DIRS
# directive above. Use space to separate entries.
FILES="/bin/sh"
#
# Define additional things that should be added to chroot without check.
# This could be block or char-devices. Use space to separate entries. 
ADDITIONAL="/dev/urandom /dev/null /var/lock/subsys /var/application"
#
# Target chroot-directory
TARGETDIR=="/var/lib/application"
#
# Here goes the list of files that has to be synced to chroot
FILELIST="/tmp/chroot_files.dat"
#

mkchroot.sh

#!/bin/sh
. /opt/application/mkchroot.cfg
getlibs ()
{
  # Parameter1: Name of a file containing files to check
  for b in $(cat ${1})
    do
      ldd $b |grep -v ":"|grep "/"|sed "s/.*>//g; s/ (.*//g"|awk '{print $1}'
  done
}
# Main program
clear
for f in ${FILELIST}_bin ${FILELIST}_tmp ${FILELIST}_lib ${FILELIST}
  do
    [ -f $f ] && rm $f
done
for d in $DIRS
  do
    echo Build filelist for directory $d
    find $d -type f -exec file {} \; 2>/dev/null |grep ELF |cut -d : -f 1 >>${FILELIST}_bin
done
for f in $FILES
  do
    echo $f >>${FILELIST}_bin
done
echo Find libaries on stage 1
getlibs ${FILELIST}_bin >>${FILELIST}_tmp
# Now find indirect libraries until list does not get any longer...
sort -u ${FILELIST}_tmp >${FILELIST}_lib
typeset -i LIBNEW="$(wc -l <${FILELIST}_lib )" LIBOLD=0 STAGE=2
while [ $LIBNEW -ne $LIBOLD ]
  do
    echo Find libaries on stage $STAGE
    let STAGE++
    LIBOLD=$LIBNEW
    cp ${FILELIST}_lib ${FILELIST}_tmp
    getlibs ${FILELIST}_lib >>${FILELIST}_tmp
    sort -u ${FILELIST}_tmp >${FILELIST}_lib
    LIBNEW=$(wc -l <${FILELIST}_lib)
done
cp ${FILELIST}_lib ${FILELIST}_tmp
for e in $ADDITIONAL
  do
    echo $e >>${FILELIST}_tmp
done
echo Für chroot zu synchronisierende Dateien:
GDIRS=$(echo $DIRS |sed "s/ /\\\|/g;")
grep -v "$GDIRS" ${FILELIST}_tmp |sort -u >${FILELIST}
cat $FILELIST

Problem that still exists: There are shell-files within my chroot. They might reference some other binaries.

As workaround these have to be put manually into $FILES.

Nils
  • 7,695
  • 3
  • 34
  • 73
0

There is a set of tools named jailkit.

This may work with linux, too. According to its home-page it is confirmed to work with

  • Solaris
  • "many" Linux distributions
  • OpenBSD
  • FreeBSD
  • MacOSX

Its dependencies look good:

  • (g)libc
  • python
  • posix threads
Nils
  • 7,695
  • 3
  • 34
  • 73