1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
SuSE secure compartment
v1.1
(c) 2000 by Marc Heuse <marc@suse.de>
INTRODUCTION
------------
This tool was written to securely run untrusted services and programs.
It has all options needed to make the impact of an successful hacker
attempt on a service as small as possible.
INSTALLING
----------
Type "make install" (this will also compile the program)
The binary "compartment" will be installed in /usr/sbin, the textfiles
README, CHANGES and TODO to /usr/doc/packages/compartment and the man page
compartment.1 to /usr/share/man/man1
IMPORTANT TIPS
--------------
This section should be below "how to run" however I fear that *you* might
stop reading before getting to this section.
So listen up and take notice of these important tips:
* always try to use the --chroot option. This might take some work and
pain, however it is the best way to secure a service.
* always try to use the --user AND --group option if no root
priviliges are needed.
* if root privs are needed, use capabilities
* if you use capabilities:
-> always chroot !
-> chown all files/dirs to another user than root if thats
possible - otherwise just those which really need to be
writable by the program
* there are several capsets which should not be used, because then
it might be easy to become the real superuser of the machine:
CAP_NET_ADMIN, CAP_NET_RAW, CAP_FOWNER, CAP_SYS_MODULE,
CAP_SYS_CHROOT, CAP_SYS_PTRACE, CAP_SYS_ADMIN
And several others can be used to denial-of-service the machine!
Once again: always chroot when using capabilities!
Remember these tips!
If you have got problems getting a program running chrooted or with capsets,
try to "strace -v -s 250 -ff -F -qix -o problem /usr/sbin/compartment ...."
the problem - check for system calls which failed and try to figure out how
to get it working.
And please: if you get a program/daemon running with chrooting and/or
capsets, please send me an email (marc@suse.de) with all information. Far
below is a section called "how to get the service xxx running" which needs
*your* input.
HOW TO RUN
----------
Run "compartment" without any argument to see the options:
SuSE secure compartment v1.0 Marc Heuse <marc@suse.de> http://www.suse.de/~marc
Syntax: compartment [options] /full/path/to/program
Options:
--chroot path chroot to path
--user user change uid to this user
--group group change gid to this group
--init program execute this program/script before doing anything
--cap capset set capset name. This option can be used several times.
--verbose be verbose
--quiet do no logging (to syslog)
--fork fork (if everything is fine)
Hints: always try to chroot; use --user&group if possible; chroot and chown all
files to another user than root if you use capabilties. Read the README file!
Known capset names: none CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH
CAP_FOWNER CAP_FSETID CAP_FS_MASK CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP
CAP_LINUX_IMMUTABLE CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_ADMIN
CAP_NET_RAW CAP_IPC_LOCK CAP_IPC_OWNER CAP_SYS_MODULE CAP_SYS_RAWIO
CAP_SYS_CHROOT CAP_SYS_PTRACE CAP_SYS_PACCT CAP_SYS_ADMIN CAP_SYS_BOOT
CAP_SYS_NICE CAP_SYS_RESOURCE CAP_SYS_TIME CAP_SYS_TTY_CONFIG
(see linux/capability.h for more information)
THE OPTIONS
-----------
--chroot is the path to chroot to. Notice that you need all needed libraries
in (chroot_path)/lib! (run "ldd program_to_run" to see which libraries are
needed.) After you created (chroot_path)/lib and copied the libraries there,
create (chroot_path)/etc as well and run "ldconfig -X -r chroot_path".
Finally copy all needed program files and create /dev devices if necessary.
--user sets the userid which will run the program
--group sets the groupid which will run the program
if either --user or --group is used, setgroups(0, NULL) will be called, to
drop all suplementary groups.
--init is a program which will be initially run. You can use this e.g. to create
a fresh chroot environment before launching the real programs chrooted.
--verbose tells you everything "compartment" does
--quiet tells you nothing (doesn't log anything to syslog)
--fork forks before executing the program, however checks that everything is
right beforehand. That means that you have to specify the full pathname of
the program to execute!
--cap let's you define one or more capsets. e.g. if you set
--cap CAP_NET_BIND_SERVICE the process will be able to bind to ports < 1024,
but not any other thing, root can normally do!
NOTE: You can't use --cap and --user together (the 2.2 and most 2.3 kernels
do not support this. This is fixed in the late 2.3 series. SuSE compartment
will support this when 2.4 gets outs)
If you want to know what capsets are available and what they do, check out
(/usr/include/)linux/capability.h
A WORD ABOUT /CHROOT
--------------------
If you are chrooting a service, you have to create a secure chroot
compartment.
Most important: /chroot should be on a partition of it's own, to prevent
local hardlink attacks.
Furthermore, you can use ext2 mount security options:
nosuid - to prevent suid file creation from a compromised service
noatime - for performance reasons
About other mount options:
ro (readonly) - is great but usually won't work with your services
because most would need to write to a file somewhere.
nodev - also great and important, but then you can't log to syslog
via the log device (e.g. /chroot/dev/log)
noexec - can't be used because compartment has to execute the service
After you have setup this, create the following directories within /chroot:
bin and dev. Both should have 0755 permissions.
Ensure that syslog creates a second log device in /chroot/dev. This is done
by starting syslogd with the option "-a /chroot/dev/log".
If you have SuSE Linux, this can easily be done by setting the
SYSLOGD_PARAMS variable in /etc/rc.config with this parameter.
If you use the example scripts init_bind8 and/or init_squid2, then put the
init_* file(s) into the /chroot/bin directory with 0700 permissions.
HOW TO GET THE SERVICE/PROGRAM XXX RUNNING
------------------------------------------
This section needs input. Have you successfully used chrooting etc. on
apache, wu-ftpd, named etc. etc.? Send the information to marc@suse.de and
I will put it here so everyone can enhance the security on his system.
BIND8 - named:
See the file init_bind8 which is appended to this README on how this could
be implemented with bind8.
You have to create /chroot and put init_bind8 into /chroot/bin/ and
afterwards exchange the named execution in the rc startup scripts (it's
/etc/rc.d/named on SuSE Linux, where the line is
startproc /usr/sbin/named -u named -g named
) with:
/usr/sbin/compartment --chroot /chroot/bind8 --init /chroot/bin/init_bind8 \
--cap CAP_NET_BIND_SERVICE --fork --group root /usr/sbin/named
Please note that if you want to change the zones or config files, that you
have to change the normal files within /etc and /var/named and NOT the ones
in /chroot! You have to restart the service for the changes to take effect.
You also have to change the syslogd startup: add the following commandline
option: "-a /chroot/dev/log" which adds another unix domain socket for logging.
SQUID2:
See the file init_squid2 which is appended to this README (after init_bind8)
on how this couldbe implemented with squid2.
You have to create /chroot and put init_squid2 into /chroot/bin/ and
afterwards exchange the squid execution in the rc startup scripts (it's
/etc/rc.d/squid on SuSE Linux, where the lines are:
/usr/sbin/squid -z
and
startproc -l /var/squid/squid.out /usr/sbin/squid -sYD
) with:
/usr/sbin/compartment --chroot /chroot/squid2 --init /chroot/bin/init_squid2 \
--user squid --fork /usr/sbin/squid -sYD
You also have to change the syslogd startup: add the following commandline
option: "-a /chroot/dev/log" which adds another unix domain socket for logging.
The logfiles of squid2 will be placed in /chroot/log !
LOGGING
-------
Everything is logged to stderr and syslog (unless --quiet is used).
Also the whole argument list is printed to syslog.
Everything is logged with DAEMON.NOTICE
QUESTIONS / BUGS
----------------
Send an email to marc@suse.de.
A beta of the package can always be found at http://www.suse.de/~marc
----- EXAMPLE SCRIPT : init_bind8 -----
#!/bin/sh
#
# auto_chroot_script for named from the bind8 package and SuSEcompartment v0.8
# (c) 2000 by Marc Heuse <marc@suse.de>
#
#
# compartment call (where this script is /chroot/bin/init_bind8):
# /usr/sbin/compartment --chroot /chroot/bind8 --init /chroot/bin/init_bind8 \
# --cap CAP_NET_BIND_SERVICE --fork --group root /usr/sbin/named
#
CHROOT_DIR="/chroot/bind8" # chroot directory
OWNER="bin.bin" # user.group owner of all chrooted files
DEV_LOG="/chroot/dev/log" # add "-a /chroot/dev/log" to the syslogd start
DIR_LIST_755="/var /etc /lib /bin /dev"
DIR_LIST_1775="/tmp /var/run /var/named/slave"
FILE_LIST="/usr/sbin/named /etc/localtime /etc/named.conf /etc/protocols \
/etc/resolv.conf /etc/services /var/named/* /dev/null"
CHOWN_ROOT=""
CHGRP_ROOT="$DIR_LIST_1775"
# start
umask 022
export PATH="/usr/sbin:/sbin:/usr/bin:/bin"
rm -rf "$CHROOT_DIR"
mkdir -p -m 755 "$CHROOT_DIR" || exit 1
cd "$CHROOT_DIR"
for i in $DIR_LIST_755; do
mkdir -p -m 755 "$CHROOT_DIR/$i"
done
for i in $DIR_LIST_1775; do
mkdir -p -m 1775 "$CHROOT_DIR/$i"
done
ln -s . usr
ln -s bin sbin
ln -s tmp var/tmp
for i in $FILE_LIST; do
LIB=`ldd $i 2> /dev/null |grep -v "not a "| awk '{print$ 3}'`
cp -a $i "$CHROOT_DIR/$i"
for j in $LIB; do
test -e "$CHROOT_DIR/$j" || cp -p "$j" "$CHROOT_DIR/lib"
done
done
ldconfig -r "$CHROOT_DIR" 2> /dev/null
chown -R $OWNER "$CHROOT_DIR"
for i in $CHOWN_ROOT; do
chown root "$CHROOT_DIR/$i"
done
for i in $CHGRP_ROOT; do
chgrp root "$CHROOT_DIR/$i"
done
test -e "$DEV_LOG" || {
echo "Warning: $DEV_LOG not found. Add \"-a $DEV_LOG\" to the syslogd startup."
exit 1
}
ln "$DEV_LOG" dev/log
# end
----- EXAMPLE SCRIPT : init_squid2 -----
#!/bin/sh
#
# auto_chroot_script for squid from the squid2 package and SuSEcompartment v0.8
# (c) 2000 by Marc Heuse <marc@suse.de>
#
#
# compartment call (where this script is /chroot/bin/init_squid2):
# /usr/sbin/compartment --chroot /chroot/squid2 --init /chroot/bin/init_squid2 \
# --user squid --fork /usr/sbin/squid -sYD
#
CHROOT_DIR="/chroot/squid2" # chroot directory
OWNER="bin.bin" # user.group owner of all chrooted files
DEV_LOG="/chroot/dev/log" # add "-a /chroot/dev/log" to the syslogd start
DIR_LIST_755="/var/squid/logs /var/squid/cache /usr/share/squid /etc /lib \
/bin /dev"
DIR_LIST_1775="/tmp"
FILE_LIST="/etc/squid.conf /etc/resolv.conf /etc/nsswitch.conf /etc/hosts \
/etc/host.conf /lib/libnss_*.so.2 /etc/localtime /etc/services \
/usr/sbin/squid /usr/sbin/dnsserver /usr/sbin/unlinkd \
/dev/null"
CHOWN_SQUID="/var/squid/*"
LOGS="access.log cache.log store.log" # in /var/squid/logs
# start
umask 022
export PATH="/usr/sbin:/sbin:/usr/bin:/bin"
test -d /chroot/log || mkdir -m 0755 /chroot/log
rm -rf "$CHROOT_DIR"
mkdir -p -m 755 "$CHROOT_DIR" || exit 1
cd "$CHROOT_DIR"
mkdir -m 755 var
ln -s . usr
ln -s bin sbin
ln -s tmp var/tmp
for i in $DIR_LIST_755; do
mkdir -p -m 755 "$CHROOT_DIR/$i"
done
for i in $DIR_LIST_1775; do
mkdir -p -m 1775 "$CHROOT_DIR/$i"
done
for i in $FILE_LIST; do
LIB=`ldd $i 2> /dev/null |grep -v "not a "| awk '{print$ 3}'`
cp -a $i "$CHROOT_DIR/$i"
for j in $LIB; do
test -e "$CHROOT_DIR/$j" || cp -p "$j" "$CHROOT_DIR/lib"
done
done
ldconfig -r "$CHROOT_DIR" 2> /dev/null
cp -a /usr/share/squid "$CHROOT_DIR"/usr/share
chown -R $OWNER "$CHROOT_DIR"
for i in $CHOWN_SQUID; do
chown squid "$CHROOT_DIR/$i" 2> /dev/null
done
test -e "$DEV_LOG" || {
echo "Warning: $DEV_LOG not found. Add \"-a $DEV_LOG\" to the syslogd startup."
exit 1
}
ln "$DEV_LOG" dev/log
set -o noclobber
for i in $LOGS; do
test -e /chroot/log/"$i" || {
> /chroot/log/$i || exit 1
}
chown squid.root /chroot/log/"$i"
chmod 640 /chroot/log/"$i"
ln /chroot/log/$i var/squid/logs/$i
done
set +o noclobber
/usr/sbin/compartment --chroot "$CHROOT_DIR" --user squid /usr/sbin/squid -z
# end
|