Project

General

Profile

Actions

Bug #2952

closed

Unvalidated input during system_firmware_check.php

Added by Jeremy Porter over 8 years ago. Updated over 7 years ago.

Status:
Resolved
Priority:
High
Assignee:
-
Category:
Upgrade
Target version:
Start date:
04/16/2013
Due date:
% Done:

100%

Estimated time:
Plus Target Version:
Release Notes:
Affected Version:
2.1
Affected Architecture:

Description

When the system goes to check firmware, it checks over http:, not https, secondly it blindly accepts any returned response and attempts to parse it.
If for instance you are behind a captive portal, with a flash app install, that gets injected right through.
This appears to be where the problem is: $remote_version = trim(@file_get_contents("/tmp/{$g['product_name']}_version"));

Actions #1

Updated by Jose Silva over 8 years ago

The code supports HTTPS. You just have to add the "s" to the system_firmware_settings.php > updater settings. What it looks like is that snapshots.pfsense.org isn't working over https

what it could be done in this place, would be to use http://de1.php.net/manual/en/function.filter-var.php

something like:

    $remote_version = urldecode ($str );
    $remote_version = filter_var($remote_version, FILTER_SANITIZE_STRING);
    $remote_version = filter_var($remote_version, FILTER_SANITIZE_SPECIAL_CHARS);
Actions #2

Updated by Jose Silva over 8 years ago

The code supports HTTPS. You just have to add the "s" to the system_firmware_settings.php > updater settings. What it looks like is that snapshots.pfsense.org isn't working over https

what it could be done in this place, would be to use http://de1.php.net/manual/en/function.filter-var.php

something like:

    $remote_version = urldecode ($str );
    $remote_version = filter_var($remote_version, FILTER_SANITIZE_STRING);
    $remote_version = filter_var($remote_version, FILTER_SANITIZE_SPECIAL_CHARS);

just to avoid the maybe possible scenario of XSS on the textarea.

Actions #3

Updated by Ian Gallagher over 7 years ago

Hi,

I'd like to bring this issue up again, and increase it's priority to critical or high, as I have verified the Cross-Site Scripting (XSS) to be exploitable.

It is possible to attack the web admin UI via XSS as theoretically described here 9 months ago, and I just verified on a 2.0.1-RELEASE NanoBSD 4G install (Netgate 7541). Not sure if this is fixed in the current 2.1 branch, but this bug leads me to believe that it isn't.

If an attacker controls the update server (which is a possible scenario - either if the main pfSense repo or any others (Netgate, other vendors, etc.) via any means (update server owned, malicious repository admin) that attacker could potentially execute javascript on any and all pfSense installs in which a local admin visited the "system_firmware_check.php page (check for automatic updates). With script execution in this context, an attacker could completely take over the router with admin/root privileges as the logged in user can execute shell and PHP commands on the router itself.

As far as I can tell, this injection can occur regardless of firmware images being signed, because the version data is displayed before the firmware image is downloaded or it's authenticity verified.

I've setup a malicious HTTP server and pointed my router at it to check for updates. I've modified the file "version-nanobsd-4g" from the following:

2.1p1-RELEASE

To contain the following:

2.1p1-RELEASE"; alert("XSS Via Update version file contents"); this.document.forms[0].output.value += " 

This causes the inline Javascript present in the system_firmware_check.php page to contain the following (around line 262, for me):

<script language="JavaScript">
this.document.forms[0].output.value = "A new version is now available\n\nCurrent version: 2.0.1-RELEASE\n  NanoBSD Size : 4g\n       Built On: Mon Dec 12 19:00:03 EST 2011\n    New version: 2.1p1-RELEASE"; alert("XSS Via Update version file contents"); this.document.forms[0].output.value += "\n\n  Update source: http://xss_server/updates/FW-7541/\n";
this.document.forms[0].output.scrollTop = this.document.forms[0].output.scrollHeight;
</script>

The script is executed as you would expect, closing the string assignment, executing the alert box, and then completing the string assignment. The alert could easily be replaced with something more malicious and there would be no user interaction or notification of the exploit.

Actions #4

Updated by Ian Gallagher over 7 years ago

Verified to still be present and exploitable in 2.1p1-RELEASE/nanobsd 4g (Netgate image), by replacing the reported version with a larger version and the payload:

13.37-XSS"; alert("XSS Via Update version file contents"); this.document.forms[0].output.value += " 
Actions #5

Updated by Jeremy Porter over 7 years ago

  • Category set to Dashboard
  • Target version set to 2.1.1
  • Affected Version set to 2.1

Netgate Pfsense images 2.1p1 and higher upgrade over HTTPS, making this attack more difficult.

Actions #6

Updated by Ian Gallagher over 7 years ago

While I'm a big fan of the updates going over HTTPS for transport security, I would say that this is a different issue. If I ran a pfsense update repository mirror, I could easily use this to execute code on users' routers, even while serving up authentic images.

BTW, I created a related bug #3405 because I was worried about this falling through the cracks (since it's been open for 9mo).

Actions #7

Updated by Chris Buechler over 7 years ago

  • Category changed from Dashboard to Upgrade
  • Priority changed from Normal to High
Actions #8

Updated by Renato Botelho over 7 years ago

  • Status changed from New to Feedback
  • % Done changed from 0 to 100
Actions #10

Updated by Ian Gallagher over 7 years ago

I'd advocate a more appropriate fix than addslashes() for this - slash-escaping is not sufficient to protect against HTML and Javascript injection in this context, rather the data should be either whitelisted (the known characters should be within a reasonable, strict set for this string) and/or HTML entity escaped. Ideally, this would be handled by the template layer, but if the template system does not automatically HTML encode output, the htmlspecialchars() method can be used in place of addslashes(). This would product the proper HTML entity encoded string for this context, which as a bonus, would render any special characters as properly readable on the page.

If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). However, this is not recommended. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.
Instead of this, you should use a template engine that applies HTML escaping by default - see below. All HTML should be passed out through the template engine.
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.
Keep in mind that this scenario won't mitigate XSS when you use user input in dangerous elements (style, script, image's src, a, etc.), but mostly you don't. Also keep in mind that every output that is not intended to contain HTML tags should be sent to the browser filtered with the following function.

Is there any way the template system itself could be used to protect against XSS here, and elsewhere in the project?

Actions #11

Updated by Renato Botelho over 7 years ago

  • Status changed from Feedback to Resolved

It was replaced by htmlspecialchars()

Actions

Also available in: Atom PDF