HSC
Network Security Consulting Agency Since 1989 - Specialized in Unix, Windows, TCP/IP and Internet
Text mode: access to the page content
Hervé Schauer Consultants
You are here: Home > Resources > Tips > chrooter un démon
Go to: HSC Trainings
Télécharger le catalogue des formations
Search:  
Version française
   Services   
o Skills & Expertise
o Consulting
o ISO 27001 services
o Audit & Assessment
o Penetration tests
o Vunerability assessment (TSAR)
o Forensics
o ARJEL
o Training courses
o E-learning
   Conferences   
o Agenda
o Past events
o Tutorials
   Resources   
o Thematic index
o Tips
o Lectures
o Courses
o Articles
o Tools (download)
o Vulnerability watch
   Company   
o Hervé Schauer
o Team
o Job opportunities
o Credentials
o History
o Partnerships
o Associations
   Press and
 communication
 
 
o HSC Newsletter
o Bulletin juridique HSC
o Press review
o Press releases
o Publications
   Contacts   
o How to reach us
o Specific inquiries
o Directions to our office
o Hotels near our office
|>|chrooter un démon  

by Denis Ducamp (11/11/2000)



La commande chroot permet de lancer un programme en restreignant ses accès
disques à une sous arborescence. En fait pour le processus, la racine du
disque est la racine de l'arborescence dans laquelle il a été restreint.

Il est possible de chrooter de nombreux services. L'exemple ci-dessous
correspond à la mise en cage d'un démon apache configuré en relais-inverse
(voir http://www.hsc.fr/ressources/breves/relais-inverse.html ) sur un 
système Linux sous libc5 (slackware 4.0) avec un noyau 2.4.0-test4 .

apache étant installé et correctement configuré dans l'arborescence /www
(./configure ... --prefix=/www) , il faut construire la cage comme suit :

    cd /www
    ln -s . www
    mkdir etc

. créer l'utilisateur et le groupe utilisé :

    echo 'nobody:x:65534:100:nobody:/dev/null:' > etc/passwd
    echo 'nogroup::-2:' > etc/group

. créer le fichier de résolution DNS :

    cp /etc/resolv.conf etc/resolv.conf

. créer les fichier nécessaires à la localisation horaire :

    cp /etc/localtime etc/localtime
    mkdir -p usr/lib/zoneinfo          
    mkdir -p usr/share/zoneinfo
    mkdir -p var/lib/zoneinfo
    ln -s /etc/localtime var/lib/zoneinfo
    ln -s /var/lib/zoneinfo/localtime usr/lib/zoneinfo
    ln -s /var/lib/zoneinfo/localtime usr/share/zoneinfo

. créer les périphériques utilisés :

    mkdir dev
    mknod -m 666 dev/null -c 1 3
    mknod -m 644 dev/urandom c 1 9

. copier les bibliothèques utilisées :

    mkdir lib
    cp /lib/libc.so.5 /lib/libm.so.5 /lib/ld-linux.so.1.9.9 lib
    ln -s ld-linux.so.1.9.9 lib/ld-linux.so.1
    ln -s ld-linux.so.1 lib/ld-linux.so

Pour savoir quelles sont les bibliothèques utilisées, utiliser ldd :

    cd /www
    ldd bin/httpd
        libm.so.5 => /lib/libm.so.5 (0x4000b000)
        libc.so.5 => /lib/libc.so.5 (0x40014000)

Il se peut, comme ici, qu'une bibliothèque soit manquante. Ici ld-linux.so.1
est nécessaire au chargement des bibliothèques dynamiques libc5. Sous
glibc2, le fichier nécessaire est ld-linux.so.2 alors qu'au format a.out il
s'agit du fichier ld.so .

Avec certains systèmes, certaines bibliothèques dynamiques sont chargées par
d'autres bibliothèques dynamiques sans apparaître avec la commande ldd. Même
si l'exécutable est statique, ces bibliothèques dynamiques doivent être
incluses dans la cage. Dans ce cas il est possible de recopier toutes les
bibliothèques dans la cage et d'exécuter le service durant quelques temps.
Pour savoir quelles bibliothèques ont été utilisées, la commande "ls -artlu"
permet de voir la date de dernier accès en lecture de chaque fichier; ceci
ne fonctionnant que si la partition n'est pas en lecture seule et que
l'enregistrement automatique de la date de dernier accès n'est pas
désactivé.

Lancer le relais par la commande suivante :

    # cd /www
    # chroot . ./bin/httpd
    ./bin/httpd: can't open cache '/etc/ld.so.cache'

Le message d'erreur ci-dessus est dû au système de chargement des
bibliothèques dynamiques et peut être ignoré.

Les commandes "chroot /www /www/bin/httpd" et "chroot /www /bin/httpd"
depuis le répertoire / sont également utilisables, mais je préfère
personnellement mettre l'oiseau dans la cage avant de fermer la porte ;-)

Il est possible de vérifier les fichiers ouverts par le relais avec le
programme lsof ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/ :

httpd      5740   root  cwd    DIR       3,70     1024    225341 /www
httpd      5740   root  rtd    DIR       3,70     1024    225341 /www
httpd      5740   root  txt    REG       3,70  1382240     69673 /www/bin/httpd
httpd      5740   root  mem    REG       3,70    79508     43062 /www/lib/ld-linux.so.1.9.9
httpd      5740   root  mem    REG       3,70    32168     43031 /www/lib/libm.so.5
httpd      5740   root  mem    REG       3,70   614840     43060 /www/lib/libc.so.5
httpd      5740   root    0r   CHR        1,3             116784 /www/dev/null
httpd      5740   root    1w   CHR        1,3             116784 /www/dev/null
httpd      5740   root    2w   REG       3,70      702     69889 /www/logs/error_log
httpd      5740   root   15w   REG       3,70      702     69889 /www/logs/error_log
httpd      5740   root   16u  inet    5475799                TCP *:443 (LISTEN)
httpd      5740   root   17w   REG       3,70     8496     69890 /www/logs/ssl_engine_log
httpd      5740   root   18w   REG       3,70        0     69895 /www/logs/ssl_mutex.5739
httpd      5740   root   19w   REG       3,70      388     69891 /www/logs/access_log
httpd      5740   root   20w   REG       3,70      388     69891 /www/logs/access_log
httpd      5740   root   21w   REG       3,70      481     69893 /www/logs/ssl_request_log
httpd      5740   root   22w   REG       3,70        0     69898 /www/logs/httpd.lock.5740 (deleted)

Les points remarquables sont :
. apache est chrooté dans /www (ligne rtd)
. les entrées et sorties standard sont redirigées dans /dev/null
. la sortie d'erreur est redirigée dans le fichier /logs/error_log
. le relais n'écoute que sur le port 443 en tcp

Sous Linux il est également possible d'utiliser l'arborescence /proc pour
vérifier cela :

# ls -l /proc/5740
total 198
-r--r--r--   1 root     root            0 Nov 11 15:51 cmdline
lrwxrwxrwx   1 root     root            0 Nov 11 15:51 cwd -> /www
-r--------   1 root     root            0 Nov 11 15:51 environ
lrwxrwxrwx   1 root     root            0 Nov 11 15:51 exe -> /www/bin/httpd
dr-x------   2 root     root            0 Nov 11 15:51 fd
-r--r--r--   1 root     root            0 Nov 11 15:51 maps
-rw-------   1 root     root            0 Nov 11 15:51 mem
lrwxrwxrwx   1 root     root            0 Nov 11 15:51 root -> /www
-r--r--r--   1 root     root            0 Nov 11 15:51 stat
-r--r--r--   1 root     root            0 Nov 11 15:51 statm
-r--r--r--   1 root     root            0 Nov 11 15:51 status
# ls -l /proc/5740/fd
total 11
lr-x------   1 root     root           64 Nov 11 15:52 0 -> /www/dev/null
l-wx------   1 root     root           64 Nov 11 15:52 1 -> /www/dev/null
l-wx------   1 root     root           64 Nov 11 15:52 15 -> /www/logs/error_log
lrwx------   1 root     root           64 Nov 11 15:52 16 -> socket:[5475799]
l-wx------   1 root     root           64 Nov 11 15:52 17 -> /www/logs/ssl_engine_log
l-wx------   1 root     root           64 Nov 11 15:52 18 -> /www/logs/ssl_mutex.5739
l-wx------   1 root     root           64 Nov 11 15:52 19 -> /www/logs/access_log
l-wx------   1 root     root           64 Nov 11 15:52 2 -> /www/logs/error_log
l-wx------   1 root     root           64 Nov 11 15:52 20 -> /www/logs/access_log
l-wx------   1 root     root           64 Nov 11 15:52 21 -> /www/logs/ssl_request_log
l-wx------   1 root     root           64 Nov 11 15:52 22 -> /www/logs/httpd.lock.5740 (deleted)

L'identité sous laquelle tourne le relais peut également être obtenue grâce
à l'arborescence /proc :

# ls -ld /proc/574?
dr-xr-xr-x   3 root     root            0 Nov 11 15:55 /proc/5740
dr-xr-xr-x   3 nobody   nogroup         0 Nov 11 15:55 /proc/5741
dr-xr-xr-x   3 nobody   nogroup         0 Nov 11 15:55 /proc/5742

Dans le cas où le serveur ne voudrait pas se lancer dans la cage, il est
possible d'utiliser la commande suivante :

# cd /www
# strace -f chroot . ./bin/httpd > httpd.strace 2>&1

La commande strace permet de suivre les appels systèmes effectués par
l'application avec les valeurs de retour. En regardant plus particulièrement
les erreurs des appels à open, stat et lstat, il est possible de découvrir
la cause de l'erreur fatale, mais également la présence d'erreurs non
fatales (ex : l'absence du périphérique /dev/urandom).

L'option -f permet de spécifier qu'il est également nécessaire de suivre les
sous processus, sinon ici seul chroot serait surveillé.

Une difficulté couramment rencontrée lorsqu'un service est lancé chrooté se
trouve au niveau de la journalisation via le démon syslogd. Il est tout
d'abord nécessaire de créer un tube nommé :

    # cd /www
    # mkfifo -m 666 dev/null

Puis de relancer le démon syslogd en lui indiquant quelle autre source
d'évènements écouter :

    # cd /
    # /usr/sbin/syslogd -a /www/dev/null

Sous systèmes BSD, utiliser l'option -l à la place de l'option -a .

Il est possible de demander à apache de journaliser ses erreurs via syslogd
en changeant dans le fichier httpd.conf la ligne ErrorLog par :

    ErrorLog syslog

Attention, il ne suffit pas de chrooter un démon, il est aussi nécessaire
qu'il tourne sous une identité non privilégiée. Ici apache change d'identité
dès qu'il n'a plus besoin d'être privilégié. bind fonctionne de la même
façon s'il est lancé avec les options -u et -g et se chroote lui-même avec
l'option -t .

Il est en effet possible pour tout processsus tournant en tant que root de
sortir de la cage dans laquelle il aura été restreint. Pour la description
de la technique la plus simple, voir
http://www.bpfh.net/simes/computing/chroot-break.html .



Last modified on 12 November 2003 at 13:55:00 CET - webmaster@hsc.fr
Mentions légales - Information on this server - © 1989-2013 Hervé Schauer Consultants