Surveiller les connexions avec auditd
Par devloop, mercredi 26 Décembre 2007 à 21:21 :: Sécurité Informatique :: #488 :: rss
auditd est un démon qui permet de surveiller ce qu'il se passe au niveau du noyau Linux 2.6.
Une fois activé il se met en écoute de nouvelles règles de surveillance et enregistre dans un fichier de journalisation (/var/log/audit/audit.log) tous les événements correspondants aux règles définies.
Le démon auditd et les programmes clients qui l'accompagnent (auditctl, ausearch, aureport) peuvent être utilisés à différentes fins, par exemple pour surveiller les accès effectués sur des fichiers sensibles.
Dans cet exemple, nous allons voir comment surveiller les connexions réseaux. Avec iptables nous pourrions logger les connexions entrantes et sortantes, malheureusement nous n'aurions pas les informations concernant le programme qui participe à ces connexions
Pour savoir si vous disposez d'auditd, le plus simple est encore de regarder s'il est présent parmis les processus en cours (commande ps aux). Si c'est le cas, cela ne signifie pas pour autant qu'il soit actif. Pour cela il faut lancer la commande (en gras) :
Si on relance auditctl -s, nous obtiendrons
Afin de voir les logs défiler, je vous recommande d'exécuter un tail -f /var/log/audit/audit.log dans une console.
Informons maintenant auditd que nous souhaitons garder les connexions à l'oeil. L'option
En réalité, il n'y a pas de syscall nommé
On utilisera alors la commande auditctl -a exit,always -S socketcall à la place.
Aucun message de confirmation n'apparait à l'exécution de la commande mais un message devrait apparaître dans le fichier de log et ils nous est possible de lister les règles avec auditctl :
Tout un tas de lignes ont fait leur apparition dans le fichier de log. Pour l'article, je n'ai gardé que celles qui m'intéresse à savoir :
type=SYSCALL msg=audit(1198689227.553:67): arch=40000003 syscall=102 success=yes exit=3 a0=1 a1=bfeaf4f0 a2=0 a3=0 items=0 ppid=6356 pid=6608 auid=4294967295 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 comm=
type=SOCKETCALL msg=audit(1198689227.553:67): nargs=3 a0=2 a1=1 a2=6
type=SYSCALL msg=audit(1198689227.553:68): arch=40000003 syscall=102 success=yes exit=0 a0=e a1=bfeaf4f0 a2=0 a3=0 items=0 ppid=6356 pid=6608 auid=4294967295 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 comm=
type=SOCKETCALL msg=audit(1198689227.553:68): nargs=5 a0=3 a1=1 a2=2 a3=bfeaf528 a4=4
type=SYSCALL msg=audit(1198689227.553:69): arch=40000003 syscall=102 success=yes exit=0 a0=3 a1=bfeaf4f0 a2=0 a3=0 items=0 ppid=6356 pid=6608 auid=4294967295 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 comm=
type=SOCKETCALL msg=audit(1198689227.553:69): nargs=3 a0=3 a1=804f020 a2=10
Je vous l'accorde, ce n'est par très parlant
On va décrypter ça
Les lignes SYSCALL, comme leur nom l'indique, nous renseigne sur l'appel système qui a été détecté ainsi que le programme à son origine et les droits qu'il possède à ce moment.
Comme expliqué ici ou là, on apprend que socketcall est bien le syscall numéro 102 (ou 0x66 en hexadécimal).
Il prend comme argument le nom de la fonction réseau à utiliser, chacune ayant une valeur prédéfinie:
Voilà enfin la dernière partie qui nous intéresse et qui correspond au connect suivant :

Une fois activé il se met en écoute de nouvelles règles de surveillance et enregistre dans un fichier de journalisation (/var/log/audit/audit.log) tous les événements correspondants aux règles définies.
Le démon auditd et les programmes clients qui l'accompagnent (auditctl, ausearch, aureport) peuvent être utilisés à différentes fins, par exemple pour surveiller les accès effectués sur des fichiers sensibles.
Dans cet exemple, nous allons voir comment surveiller les connexions réseaux. Avec iptables nous pourrions logger les connexions entrantes et sortantes, malheureusement nous n'aurions pas les informations concernant le programme qui participe à ces connexions
Pour savoir si vous disposez d'auditd, le plus simple est encore de regarder s'il est présent parmis les processus en cours (commande ps aux). Si c'est le cas, cela ne signifie pas pour autant qu'il soit actif. Pour cela il faut lancer la commande (en gras) :
# auditctl -s AUDIT_STATUS: enabled=0 flag=1 pid=3670 rate_limit=0 backlog_limit=256 lost=0 backlog=0Ici le démon n'est pas actif (enabled=0). Pour l'activer il faut tapper auditctl -e 1 (et
auditctl -e 0quand vous souhaiterez le désactiver).
Si on relance auditctl -s, nous obtiendrons
enabled=1
Afin de voir les logs défiler, je vous recommande d'exécuter un tail -f /var/log/audit/audit.log dans une console.
Informons maintenant auditd que nous souhaitons garder les connexions à l'oeil. L'option
-Spermet d'activer la surveillance sur un appel système. A tout hazard on tente la commande :
# auditctl -a exit,always -S connect Syscall name unknown: connectEt là... c'est le drame
connect. Les différents syscalls réseau passent par socketcall.
On utilisera alors la commande auditctl -a exit,always -S socketcall à la place.
Aucun message de confirmation n'apparait à l'exécution de la commande mais un message devrait apparaître dans le fichier de log et ils nous est possible de lister les règles avec auditctl :
# auditctl -l LIST_RULES: exit,always syscall=socketcallpuisque tout est ok, on lance un netcat sur www.perdu.com (port 80) et là... tout va très vite !
Tout un tas de lignes ont fait leur apparition dans le fichier de log. Pour l'article, je n'ai gardé que celles qui m'intéresse à savoir :
type=SYSCALL msg=audit(1198689227.553:67): arch=40000003 syscall=102 success=yes exit=3 a0=1 a1=bfeaf4f0 a2=0 a3=0 items=0 ppid=6356 pid=6608 auid=4294967295 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 comm=
netcatexe=
/usr/bin/netcatkey=(null)
type=SOCKETCALL msg=audit(1198689227.553:67): nargs=3 a0=2 a1=1 a2=6
type=SYSCALL msg=audit(1198689227.553:68): arch=40000003 syscall=102 success=yes exit=0 a0=e a1=bfeaf4f0 a2=0 a3=0 items=0 ppid=6356 pid=6608 auid=4294967295 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 comm=
netcatexe=
/usr/bin/netcatkey=(null)
type=SOCKETCALL msg=audit(1198689227.553:68): nargs=5 a0=3 a1=1 a2=2 a3=bfeaf528 a4=4
type=SYSCALL msg=audit(1198689227.553:69): arch=40000003 syscall=102 success=yes exit=0 a0=3 a1=bfeaf4f0 a2=0 a3=0 items=0 ppid=6356 pid=6608 auid=4294967295 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=pts4 comm=
netcatexe=
/usr/bin/netcatkey=(null) type=SOCKADDR msg=audit(1198689227.553:69): saddr=0200005052A5B0910000000000000000
type=SOCKETCALL msg=audit(1198689227.553:69): nargs=3 a0=3 a1=804f020 a2=10
Je vous l'accorde, ce n'est par très parlant
Les lignes SYSCALL, comme leur nom l'indique, nous renseigne sur l'appel système qui a été détecté ainsi que le programme à son origine et les droits qu'il possède à ce moment.
Comme expliqué ici ou là, on apprend que socketcall est bien le syscall numéro 102 (ou 0x66 en hexadécimal).
Il prend comme argument le nom de la fonction réseau à utiliser, chacune ayant une valeur prédéfinie:
#define SYS_SOCKET 1 #define SYS_BIND 2 #define SYS_CONNECT 3 #define SYS_LISTEN 4 #define SYS_ACCEPT 5 #define SYS_GETSOCKNAME 6 #define SYS_GETPEERNAME 7 #define SYS_SOCKETPAIR 8 #define SYS_SEND 9 #define SYS_RECV 10 #define SYS_SENDTO 11 #define SYS_RECVFROM 12 #define SYS_SHUTDOWN 13 #define SYS_SETSOCKOPT 14 #define SYS_GETSOCKOPT 15 #define SYS_SENDMSG 16 #define SYS_RECVMSG 17De cette façon, si on reprend notre première ligne :
type=SYSCALL msg=audit(1198689227.553:67): arch=40000003 syscall=102 success=yes exit=3 a0=1 a1=bfeaf4f0 a2=0 a3=0On en déduit qu'il s'agit d'un appel à la fonction socket() car a0=1=SYS_SOCKET. En lancant un strace parallèlement, on voit que socket() a été utilisé de cette manière :
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3Sachant que PF_INET = 2, SOCK_STREAM = 1 et que IPPROTO_TCP = 6, on n'est peu surpris de retrouver ces valeurs dans la ligne suivante :
type=SOCKETCALL msg=audit(1198689227.553:67): nargs=3 a0=2 a1=1 a2=6La fonction suivante est un setsockopt() : syscall=102 a0=e (14 en décimal) appelé de cette façon :
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0La encore on retrouve les bonnes valeurs dans les messages d'auditd
Voilà enfin la dernière partie qui nous intéresse et qui correspond au connect suivant :
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("82.165.176.145")}, 16) = 0
type=SYSCALL msg=audit(1198689227.553:69): arch=40000003 syscall=102 success=yes exit=0 a0=3... type=SOCKADDR msg=audit(1198689227.553:69): saddr=0200005052A5B0910000000000000000 type=SOCKETCALL msg=audit(1198689227.553:69): nargs=3 a0=3 a1=804f020 a2=10La ligne SOCKADDR correspond à une structure sockaddr (le second argument du connect()) comme commenté ici. Cette structure est la suivante :
struc sockaddr_in
sin_family: resw 1 ; protocol family
sin_port: resw 1 ; port
sin_addr: resd 1 ; struct sin_addr.s_addr
sin_zero: resd 2 ; padding
endstruc
Le saddrse décompose donc en :
- 0x02 : AF_INET
- 0x50 : le port après un htons(), ici le port 80
- 52A5B091 : l'adresse IP est hexadécimal, soit 180.249.41.240 (www.perdu.com)
déchiffrerune connexion dans les logs d'auditd
Commentaires
1. Le mercredi 9 Janvier 2008 à 00:34, par haypo
2. Le mercredi 9 Janvier 2008 à 00:35, par haypo :: site
3. Le mercredi 9 Janvier 2008 à 17:22, par World Domination :: site
4. Le jeudi 17 Janvier 2008 à 08:14, par devloop :: site
5. Le vendredi 25 Janvier 2008 à 11:14, par devloop :: site
Ajouter un commentaire