Introduction For those of you who don't know, PfSense is an open-source network firewall distribution based on FreeBSD operating system used by many companies worldwide to protect their infrastructure. Up until now, it has been more than a year since we've reported a number of security vulnerabilities existing in PfSense to the PfSense security team. At this point, we've given the companies and individuals using PfSense enough time to protect their assets by patching to the latest version of PfSense. Since enough time has passed, we though we might share the vulnerabilities with the world in order for security researchers to gain from the shared knowledge. In this article we'll present the CVE-2014-4687 vulnerability existing in pfSense version <= 2.1.3. In later versions of pfSense, the vulnerabilities have been successfully remediated and are no longer present.

Stored XSS in Schedules If we click on Schedules, we're presented with a web interface shown below. Figure 1: Schedules web interface Then we can add a schedule by pressing the + button. When doing so, we can change the starttime0 POST parameter into "0:00'><script>alert(1);</script><" as highlighted on the picture below. Figure 2: A request with malicious JavaScript sent to the server The inputted JavaScript is then written in response without proper encapsulation of special characters. We can see the response on the picture below. Figure 3: A malicious JavaScript contained in response Once the request is shown in a web browser, it's evident that XSS is possible, because the JavaScript is executed as presented below. Figure 4: The included JavaScript executed in the browser The vulnerability can be used to execute arbitrary JavaScript in the user's web browser, therefore stealing the user's session cookie.

Stored XSS in rss.widget.php A php script widgets/widgets/rss.widget.php contains a stored vulnerability, more precisely in the POST parameter rssfeed. The vulnerable code can be seen below, where the source code lines following the vulnerability have been properly highlighted. <?php if ( $POST [ rssfeed ]) { $config [ widgets ][ rssfeed ] = str_replace ( n , ,, $POST [ rssfeed ]); $config [ widgets ][ rssmaxitems ] = str_replace ( n , ,, POST [ rssmaxitems ]); $config [ widgets ][ rsswidgetheight ] = $POST [ rsswidgetheight ]; $config [ widgets ][ rsswidgettextlength ] = $POST [ rsswidgettextlength ]; writeconfig ( Saved RSS Widget feed via Dashboard ); Header ( Location : / ); } if ( $config [ widgets ][ rssfeed ]) $textareatxt = strreplace (,, n , $config [ widgets ][ rssfeed ]); else $textareatxt = "" ; ?> <textarea name="rssfeed" class="formfld unknown" id="rssfeed" ols="40" rows="3"> <? = $textareatxt ; ?> </textarea> The following request was sent to the web server passing the malicious JavaScript in the rssfeed POST parameter. Figure 5: including a malicious JavaScript in rssfeed POST parameter The returned response contains the following code, where the special characters have not been properly encoded. Figure 6: Previously sent malicious JavaScript code is directly included into the returned web page The following POST parameters are also vulnerable, which are located in the same script: rssmaxitems

rsswidgetheight

rsswidgettextlength

rsswidgettextlength An attacker can send malicious JavaScript to the web application where it's stored and served to other users as well.

Reflected XSS in services_status.widget.php The script widgets/widgets/services_status.widget.php doesn't properly encapsulate the user-supplied data. The code below presents part, where we're assigning the value of the POST variable servicestatusfilter to $config[widgets'][servicestatusfilter]' directly without prior sanitation. Then we're displaying that value in the HTML code. <?php if ( isset ( $_POST [ 'servicestatusfilter' ])) { $config [ 'widgets' ][ 'servicestatusfilter' ] = _POST [ 'servicestatusfilter' ]; write_config ( "Saved Service Status Filter via Dashboard" ); header ( "Location: ../../index.php" ); } ?> <input type="text" size="30" name="servicestatusfilter" lass="formfld unknown" id="servicestatusfilter" value=" <? = config [ 'widgets' ][ 'servicestatusfilter' ] ?> " /> The request below contains a POST parameter servicestatusfilter, which contains the value of ""/><script>alert(1);</script><"". Figure 7: A malicious JavaScript included into the servicestatusfilter POST parameter The response contains the exact same value as shown on the picture below. Figure 8: A malicious JavaScript included into the rssfeed POST parameter Note that the JavaScript doesn't execute in the web browser, because a Location header is also given, so a redirection is made before JavaScript has a chance to execute. Nevertheless this is a vulnerability that needs to be fixed. An attacker can cause arbitrary JavaScript to be executed in the user's web browser.

XSS in Referer HTTP Header in log.widget.php A vulnerability exists in widgets/widgets/log.widget.php in the following code. The Referer HTTP header is read into the $filename variable, which is later included into the response without properly encoding the special characters. $filename = $_SERVER['HTTP_REFERER']; if(headers_sent($file, $line)){ echo '<script type="text/javascript">'; echo '//<![CDATA['; echo 'window.location.href="'.$filename.'";'; echo '//]]>'; echo '</script>'; echo '<noscript>'; echo '<meta http-equiv="refresh" content="0;url='.$filename.'" />'; echo '</noscript>'; } If we send a "<script>" string in a Referer HTTP header, we'll receive the following response, which states that a problem was identified, because the string specified in the Referer HTTP header is not the same as the one specified in the system settings. Figure 9: A response upon sending "<script>" in referer HTTP header This happens because Pfsense implements HTTP_REFERER redirection detection, which is blocked by default: this can be controlled in an System – Advanced – Admin settings as defined below. Figure 10: The pfsense settings regarding referer HTTP header We need to disable the HTTP_REFERER enforcement check and save the settings. After that we can send the ""/></noscript><script>alert(1);</script><noscript><"" string in the Referer HTTP header as shown in the request below. Figure 11: A request containing a malicious JavaScipt in Referer HTTP header The value stored in the Referer HTTP header is presented twice to the user as shown in the response below. Figure 12: A malicious JavaScript code included into the returned web page Since we've properly escaped the <noscript> and other HTML elements, the injected JavaScript should execute on the user's browser, which is shown below. Figure 13: The execution of malicious JavaScript code Because of the default HTTP_REFERER enforcement check in the Pfsense settings, which is enabled by default, this bug is harder to exploit, but the vulnerability is still present, so it must be mitigated. There is also a number of POST parameters that are being included in the response without proper sanitation, which makes the attack probable. The vulnerable POST parameters are: filterlogentries

actpass

actblock

actreject

filterlogentriesinterfaces An attacker can inject JavaScript in Referer HTTP header, which is executed in the user's web browser.

JavaScript injection in exec.php The Diagnostics: Execute command functionality allows an attacker to upload a file to the server, which is shown below. Figure 40: The file upload functionality In order for the user to be able to access this functionality, he must have the Diagnostics: Command privileges as presented below. Figure 14: The required privileges When uploading a file, an attacker has a chance to inject arbitrary JavaScript in the txtRecallBuffer parameter. On the picture below, we can see that we inputted the "bbb'); var arrRecalBuffer = new Array('aaa" string in the txtRecallBuffer parameter. Figure 15: A malicious input data sent to the server The above request results in the response presented below, where it's evident that arbitrary JavaScript code injection is possible. Figure 16: Previously sent input data included directly into the JavaScript code block Note that we can't exploit the vulnerability, because the whole JavaScript block is enclosed in the comments with <!-- --> characters. Normally, we can break out of the commented section by first injecting the ending > characters, and then including arbitrary code, but we can't do that in the case above, since special characters < and > are properly encoded. JavaScript can be injected into the web page, which might allow attackers to execute arbitrary JavaScript in user's browser.