7

Context

In our development team, we have to build a component. This component is a full client side one written in Javascript.

A client web application wishing to embed this component will call it like below:

<iframe id="fullScreenIframe" src="http://my-server.com/component?param1=val1&param2=..."></iframe>

The problem

One of the parameters accepted by the component makes some of us nervous. The origin parameter is used to generate a link to take the user back to the client web application.

Here is how the component manages this parameter:

$(document).ready(function() {
    var origin = urlParameters["origin"];// Dynamically built from the current document url

    if(origin != undefined){
        // The link to take the user back...
        $("#welcomePage").attr("href",origin);

        // Another link in the breadcrumb using the same `origin` parameter
        $("#simulationPage").attr("href", "index.html"+"?origin="+origin);
    }

    // ...
}

What we already told him

  • Website phishing

Even if the origin parameter is passed to jQuery, any website can be used in a phishing scam. A user can be asked to (re)enter their credentials thinking they are on a real site. The hole here will be the component.

  • Allowlist with valid values

The valid values of origin can be stored remotely in an allowlist. The component would check the allowlist first before generating the link. A default link can be generating if an unexpected value is found.

Those two arguments didn't convince him. He wants to be demonstrated that the origin parameter can be a security hole. What would you tell him?

By the way, I'm looking for a good PoC demonstrating the weakness of the origin parameter.

kelalaka
  • 5,409
  • 4
  • 24
  • 47
Stephan
  • 375
  • 1
  • 9
  • I do not really understand what you are asking. – Neil Smithline Dec 03 '15 at 21:01
  • http://security.stackexchange.com/questions/79728/why-should-i-use-whitelist-on-a-waf/79731#79731 <- related to your conundrum – Ohnana Dec 04 '15 at 14:55
  • I'm not really clear what you believe the security risk is here. In your scenario how is the attacker able to modify the contents of the Origin parameter? Right now I'm agreeing with the developer in question that you need to clarify what the threat is. – Steve Sether Dec 07 '15 at 15:52
  • @SteveSether The component accepts anything from outside **without** sanitization. This is the threat. Check the accepted answer for details. – Stephan Dec 07 '15 at 16:00
  • @Stephan I'm not sure you understand my question. It accepts anything from where, your own server? What is it that you're trusting? The specific threat is important here. If you're vulnerable to a XSS attack I wouldn't really bet that input validation in Javascript is going to save you, since an attacker can input their own javascript using XSS. – Steve Sether Dec 07 '15 at 16:06
  • @SteveSether The component can be embedded from anywhere in the wild. It's a public component. The component now checks that the origin value is a url actually. – Stephan Dec 07 '15 at 16:11

3 Answers3

3

As long as you're relying on incoming user information, you'll never be fully protected/safe. Anything can be spoofed, altered, modified; and, subsequently, your component is now compromised.

If you want to go the route of retaining some trust, it would make sense to allowlist. However, going a step further may be more ideal--you issue tokens in lieu of specifying domains (think of how Google Analytics uses a UA-XXX number over mysite.com). Push administration back on their web admin and the possibility of faulty domains/security vulnerabilities is now their responsibility.


To further elaborate what I'm referring to, instead of having a allowlist, setup a database of tokens:

tokens
id       # Primary Key
token    # Unique generated token

Then, have a 1:* relationship where valid origins can be defined for that key:

origins
id       # Primary key
token_id # Forieign Key, tokens.id
origin   # origin (e.g. google.com)

Then create a token for a specific client (whomever is going to include your component on their page). For example, let's say we have the token abc123def456:

<iframe src="http://server.com/component?key=abc123def456"></iframe>

Here, your component would perform a server-side lookup against your tokens table and validate. You could also add additional checks against the Referer header, but that's up to you (and realizing Referer could be spoofed anyways). Default bahvior would be to deny *, so you'd show a page saying "No origins specified, please configure" (or something of the sort).

Next, they login to the admin page and add "abc.com". Now, the widget becomes:

<iframe src="http://server.com/component?key=abc123def456&origin=abc.com"></iframe>

Now, server side, you're validating key along with the origin (against your compiled allowlist in origins table (associated to that key). If a hacker were to try to use this (or modify it) an invalid origin (with respect to the key) would bounce and show an error page.

If they decide not to specify origin, you could also configure a default origin so anytime you include just /component?key=abc123def456 it assumes the default origin.

Or something like that

Stephan
  • 375
  • 1
  • 9
  • *"their web admin"*, *"their responsibility"* ... who is "their"? – Stephan Dec 04 '15 at 08:44
  • The owner/webmaster of the page bringing in the control via Iframe – Brad Christie Dec 04 '15 at 12:01
  • Can you shade a light, in your post, on this point: *"think of how Google Analytics uses a UA-XXX number over mysite.com"* ? – Stephan Dec 04 '15 at 12:40
  • Basically, instead of defining `origin=www.site.com` you specify `key=abc123def456`. Then, in your configuration, have the user specify what `origin` means (within the context of the widget). Otherwise, (coupled with the key) allow them to continue specifying `origin` (but check it against sites defined for that key). You can also introduce security measures (such as checking referrer is valid against sites defined for that token). – Brad Christie Dec 04 '15 at 13:35
3

When I hear about allowlists, it takes me back to the history of firewalls.

When firewalls were first used, they operated on a "accept everything by default except what is denied". This created A LOT of problems for early firewalls and sys admins since they had to proactively keep on top of threats and add them to the denylist.

When the industry realised the problem and switched to the current system of "block everything by default except what is allowed", then this drastically reduced the threat landscape and the pressure on the sys admin teams.

Use this analogy when faced with this again. This should convince most people.

Stephan
  • 375
  • 1
  • 9
user92592
  • 544
  • 1
  • 5
  • 13
0

Finally, I found a PoC for an XSS attack. The component is vulnerable when it is called like below:

http://my-server.com/component?origin=javascript:alert%28%27Hello%20world!%27%29

It proves a malicious script can potentially run once the user clicks on the link generated by the component.

Finally our team mate has accepted to strengthen the component.

Instead of an allowlist, he chose to check that origin value is a valid url.

Stephan
  • 375
  • 1
  • 9
  • If you've answered your question, you should "accept" an answer and remove this question from the queue. Good to hear your teammate has come round! :) – Ohnana Dec 04 '15 at 14:58