|
|
by Franck Davy (27/09/2004)
--[ SSH et la redirection X11 ]--
1. Introduction
Cette brève commente quelques problèmes liés à la redirection X11 avec SSH.
Ces « problèmes » ne sont pas nouveaux, généralement largement documentés et
même explicitement mentionnés dans la page de manuel du client OpenSSH :
« X11 forwarding should be enabled with caution. Users with the ability to
bypass file permissions on the remote host (for the user's X authorization
database) can access the local X11 display through the forwarded connection.
An attacker may then be able to perform activities such as keystroke
monitoring. »
L'idée de cette brève est donc de :
- Faire un point rapide sur ces risques, de les illustrer et surtout
d'introduire l'option '-Y' d'OpenSSH, qui met en oeuvre le mode de
redirection X11 (X11Forwarding) dit « trusted ».
- Plus généralement, rappeler que l'utilisation de SSH s'accompagne de quelques
précautions (par exemple, pour lors de la mise en place de SFTP, qui dépasse
le cadre de cette brève), même s'il s'agit d'une solution de référence pour
le remplacement de telnet -- à défaut de telnet/ssl.
2. Redirection X11
Avant d'aborder la redirection X11, un premier type d'erreur fréquemment
rencontré : négliger l'existence même du X11Forwarding, autrement dit, lancer
son terminal « à la telnet » depuis la machine distante :
host-client $ xhost +host-server ; ssh host-server
host-server $ DISPLAY=host-client:10.0 xterm&
En toute logique, si le serveur X de l'hôte host-client est effectivement en
écoute sur la socket TCP spécifiée (correspondant au port 6010/TCP dans
l'exemple), une fenêtre devrait apparaître au niveau de host-client. Le
problème est double dans cette situation :
- utilisation du mécanisme xhost, qui prend la main avant xauth, donnant accès,
depuis host-server, au serveur X de host-client.
=> La sécurité s'appuie donc sur une identification du client X (host-server)
par son adresse IP, et non une authentification de l'utilisateur connecté à
host-server sur la base d'un secret partagé (cookie xauth).
- trafic X11 en clair entre host-client et host-server.
Flux X11
-------------------------------------
| 6010/TCP |
\|/ |
---x--- -------
| | | |
| | ==========================> | |
| | Session SSH | |
------- -------
host-client host-server
Remarque : « client » est à prendre au sens de « client SSH », mais aussi de «
serveur X11 ».
Afin d'éviter un flux X11 « en clair », l'option X11 Forwarding de SSH est donc
à activer -- au niveau client comme au niveau serveur -- mais, nous allons le
voir, avec précaution.
Au niveau du client, il s'agit de l'option en ligne de commande '-X'.
Au niveau du serveur, il s'agit de la directive « X11Forwarding yes » du
fichier de configuration sshd_config.
Pour illustrer le fonctionnement et les problèmes potentiels, considérons
l'exemple suivant -- cas d'un poste d'administration se connectant (avec déport
d'affichage via SSH) sur un serveur distant infogéré :
- L'utilisateur admin souhaite se connecter via SSH à l'hôte
compromised-server, depuis l'hôte network-admin ; au niveau de network-admin,
la variable d'environnement DISPLAY est :0.0 :
admin@network-admin > echo $DISPLAY
:0.0
=> Le serveur X correspondant est en écoute sur la socket unix suivante :
srwxrwxrwx 1 root root 0 2004-09-28 11:52 /tmp/.X11-unix/X0
L'application locale doit donc se connecter à ce serveur X pour affichage.
Le magic-cookie, secret à partager entre serveur X et applications souhaitant
se connecter à ce dernier, est obtenu par la commande xauth(1) :
admin@network-admin > xauth list $DISPLAY
network-admin/unix:0 MIT-MAGIC-COOKIE-1 << 32 character hexkey >>
La valeur du magic-cookie est la chaîne de 32 caractères obtenue. Cette
dernière est enregistrée dans le fichier ~/.Xauthority de l'utilisateur --
les permissions sur ce dernier doivent donc être particulièrement strictes.
Elle est transmise en clair du client au serveur X, d'où l'intérêt d'une
encapsulation dans un canal SSH.
- L'utilisateur admin se connecte sur l'hôte compromised-server, en activant la
redirection X11 -- autorisée au niveau du serveur SSH (X11Forwarding
positionné à yes) :
admin@network-admin > ssh -X compromised-server
admin@compromised-server >
Le DISPLAY sur le serveur compromised-server pointe sur une socket TCP locale en
6010/TCP :
admin@compromised-server > echo $DISPLAY
localhost:10.0
=> Effectivement, au niveau du serveur, le port 6010/TCP est ouvert
localement par le démon sshd, qui assure la redirection X11 :
root@compromised-server # lsof -ni TCP:6010
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
sshd 15663 root 9u IPv4 437835 TCP 127.0.0.1:6010 (LISTEN)
=> Ainsi, les connexions sur compromised-server en 127.0.0.1:6010/TCP seront
redirigées sur network-admin vers la socket unix /tmp/.X11-unix/.X0 par SSH.
Reste le problème de l'authentification X11 : en mode debug2 (-vv), on
constate que la commande suivante est exécutée par SSH au niveau client, afin
de récupérer le magic-cookie xauth -- qui permettra de se connecter à X via
la socket unix :
debug2: x11_get_proto: /usr/bin/X11/xauth list :0.0 . 2>/dev/null
Où :0.0 correspond au DISPLAY local (network-admin).
Le danger survient, classiquement, lorsque l'hôte compromised-server est..
compromis (dans le pire des cas -- des droits d'accès permissifs sur
~/.Xauthority conduiraient au même résultat) : un utilisateur possédant les
privilèges suffisants pour accéder au fichier ~/.Xauthority -- manipulé par
la commande xauth(1) -- de l'utilisateur admin sera en mesure de se connecter
au serveur X local en 6010/TCP (compromised-server) redirigé au niveau de
l'hôte du serveur X du client SSH (network-admin), sorte de « back channel ».
Figure : redirection de compromised-server:127.0.0.1:6010/TCP vers
network-admin:/tmp/.X11-unix/X0 via SSH
avec authentification par xauth(1)
----- ---------------------
\|/ | | |
---x--- | | ------- |
| .X0 | --------------------------- | x 6010/TCP -
| | ==========================> | |
| | Session SSH | |
------- -------
network-admin compromised-server
Remarque : l'utilisation d'une socket TCP est rendue nécessaire par la
séparation des privilèges dans OpenSSH, dans la mesure où le processus possède
alors l'identité de l'utilisateur authentifié, et ne peut donc écrire dans le
répertoire /tmp/.X11-unix dans la mesure où il n'est pas SUID root.
Dès lors, les « attaques » ultra classiques relatives à X11 peuvent être mises
en oeuvre au niveau du serveur compromis, afin de capturer les évènements X via
xev(1) par exemple, ou encore afin d'exécuter des commandes au niveau du poste
client, par l'intermédiaire des XSendEvent -- dont le résultat sera variable
suivant le terminal utilisé (dans l'exemple, aterm(1) est utilisé et accepte de
tels évènements).
On imagine sans difficulté les conséquences de la compromission d'un serveur
Web (par exemple) administré depuis un réseau d'admin dédié via une solution de
type SSH + X11 Forwarding. Voire la situation d'un prestataire infogérant n
plateformes de différents clients, présentant potentiellement des niveaux de
sécurité hétérogènes.
Plus efficace qu'un long discours (plugin Flash nécessaire) :
http://www.hsc.fr/~davy/breves/ssh.html
Remarque : dans la démonstration, l'utilisateur root dispose d'un accès en
lecture au fichier ~/.Xauthority de l'utilisateur admin.
3. Redirection X11 en mode « trusted »
Dans tout l'exposé précédent, l'option '-X' est utilisée. En fait, le
comportement de cette option a été modifié - ou plutôt « enrichi » - dans les
versions postérieures à OpenSSH 3.8p1, via l'introduction de l'option '-Y'.
Cette dernière est décrite (très succinctement) de la façon suivante :
« -Y Enables trusted X11 forwarding. »
En pratique, l'option '-X' active le forwarding X11. Son comportement dépend
ensuite de la présence ou non de l'option '-Y' sur la ligne de commande, ou de
la configuration par défaut dans le fichier ssh_config.
Par défaut, la configuration adoptée est « untrusted » (ForwardX11Trusted no),
qui correspond à ne pas employer l'option '-Y'.
La notion de client X « trusted » et « untrusted » est définie dans les
extensions de sécurité X11 qui mettent en oeuvre un contrôle d'accès par
client, fondé sur la politique de sécurité décrite dans le fichier
/etc/X11/xserver/SecurityPolicy.
Dans ce mode, le client SSH génère un cookie xauth à la volée, qui sera donc
considéré comme « untrusted », et donnera un accès restreint par la politique
de sécurité aux programmes l'employant.
Le principe est, une fois la session SSH authentifiée, que le client SSH
exécute la commande suivante :
debug2: x11_get_proto: /usr/bin/X11/xauth -f /tmp/ssh-TPOAQ11862/xauthfile generate :0.0 MIT-MAGIC-COOKIE-1 untrusted timeout 1200 2>/dev/null
debug2: x11_get_proto: /usr/bin/X11/xauth list :0.0 . 2>/dev/null
=> Le mot-clef « untrusted » est employé dans la commande xauth(1).
Ainsi, dans un premier temps, le client SSH génère un cookie « untrusted »
qu'il associe au serveur local (:0.0). Ce cookie est alors récupéré par la
commande « list ». Il est donc associé au serveur X local, tout en étant
différent du cookie statique et trusted utilisé par les applications locales.
Un *autre* cookie est alors généré par le client SSH, et transmis au serveur
SSH cette fois -- ce dernier alors met à jour le fichier ~/.Xauthority de
l'utilisateur au niveau du serveur SSH en lançant les scripts ~/.ssh/rc,
/etc/ssh/sshrc ou, en dernier lieu, la commande xauth (avec l'option add). À
titre d'illustration, la page de manuel de sshd(8) précise que de tels scripts,
s'ils sont présents, doivent gérer la redirection X11 (détectée par une
variable d'environnement $DISPLAY initialisée), de la façon suivante :
if read proto cookie && [ -n "$DISPLAY" ]; then
if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
# X11UseLocalhost=yes
echo add unix:`echo $DISPLAY |
cut -c11-` $proto $cookie
else
# X11UseLocalhost=no
echo add $DISPLAY $proto $cookie
fi | xauth -q -
=> script qui a donc pour effet de mettre à jour le fichier ~/.Xauthority au
niveau du serveur SSH.
Ensuite, pour toute redirection X11 à travers le tunnel, le client SSH
réalisera l'association entre le cookie untrusted présenté et le cookie
untrusted réellement utilisé au niveau du serveur X (localement, récupéré via
xauth list).
=> D'où le terme de « X11 forwarding with authentication spoofing. » mentionné
en mode verbeux : le cookie employé par les applications déportées est remplacé
(par le client SSH) par le cookie réel employé au niveau du serveur X.
Par rapport à la démonstration, en mode « untrusted » la capture ou l'envoi
d'évènements n'est donc plus possible. En revanche, l'énumération via
xlsclients est toujours autorisée, mais elle peut être désactivée dans le
fichier /etc/X11/xserver/SecurityPolicy pour les clients « untrusted ».
Remarque : au contraire, avec l'option '-Y' (mode trusted), la commande
suivante serait exécutée :
debug2: x11_get_proto: /usr/bin/X11/xauth list :0.0 . 2>/dev/null
Le cookie ainsi généré permet un accès sans limitation au serveur X, les
risques précédemment évoqués s'appliquent donc. Encore une fois, le cookie
niveau serveur SSH est différent du cookie local au client SSH.
Suivant les distributions, le comportement par défaut peut changer.
Typiquement, sous debian, la page de manuel de ssh_config(5) explique :
ForwardX11Trusted
[...]
The default is ``yes'' (Debian-specific).
See the X11 SECURITY extension specification for full details on the restrictions imposed on untrusted clients.
Ainsi, les commandes « ssh -X host » et « ssh -Y host » sont équivalentes dans
ce cas précis, et correspondent à un mode « trusted ».
Les raisons justifiant une telle configuration sont aussi bien d'ordre pratique
que technique, par exemple, celles notamment avancées dans ces messages
suivants -- cas de la distribution debian-knoppix, suivi d'une entrée de la FAQ
du serveur Cygwin/X, relatif à un dysfonctionnement en mode « untrusted » :
http://mailman.linuxtag.org/pipermail/debian-knoppix/2004-May/005235.html
http://x.cygwin.com/docs/faq/cygwin-x-faq.txt
4. Conclusion
On retiendra que l'application SSH est bien plus qu'un simple « telnet
chiffré/authentifié », et comporte quelques effets de bord pour la sécurité
qui, sans constituer une « vulnérabilité », sont à considérer.
Aux précautions à prendre concernant les redirections X11, on ajoutera celles
liées au remplacement du protocole FTP par SCP on SFTP dans les environnements
de production (très courant), visant à offrir un FTP « chiffré/authentifié »,
mais offrant, en fait, un accès distant avec shell et redirection de connexions
TCP. Problème auquel la réponse généralement apportée consistera en la mise en
place d'un serveur SSH sécurisé (désactivation du TCP Forwarding, mise en place
de wrapper/shells restreints pour les utilisateurs), voire d'une solution
alternative de FTP/SSL http://www.hsc.fr/ressources/breves/ftp-ssl.html.fr
5. Références
Quelques papiers/présentations très intéressants faisant un point sur les
mécanismes d'authentification et la sécurité dans X11, et les attaques
traditionnelles qui s'y rapportent :
- « Enhancing XFree86 Security » par Matthieu Herrb -- auquel vont nos
remerciements pour ses remarques et son avis éclairé sur le sujet :
http://www.openbsd.org/papers/xf86-sec.pdf
- « SSH X11 forwarding considered harmful » par Holger van Lengerich :
http://www.giac.org/practical/GCIH/Holger_Van_Lengerich_GCIH.pdf
Enfin, quelques pointeurs permettant, de façon similaire, d'offrir un canal de
retour vers le poste client connecté (sans X11Forwarding dans cette situation),
via des failles au niveau des émulateurs de terminaux :
- « Vulnérabilité dans les émulateurs de terminaux »
http://www.certa.ssi.gouv.fr/site/CERTA-2003-AVI-067/index.html
- « Terminal Emulator Security Issues »
http://www.securityfocus.com/archive/1/313007
|