jplayer / jPlayer

jPlayer : HTML5 Audio & Video for jQuery
http://jplayer.org/
Other
4.6k stars 1.47k forks source link

Reused regular expression for jQuery parameter, creates ability to use jPlayer for SOME-attacks #327

Open fransr opened 9 years ago

fransr commented 9 years ago

Hi, I want to explain an issue still present in jPlayer due to the regex pattern you're using today in the jQuery-functionality/prevention checks (the function checkFlashVars together with illegalChar). This issue opens up for an attack called SOME – Same Origin Method Execution (the concept was initially posted public by Ben Hayak. More info here: http://securityaffairs.co/wordpress/29338/hacking/same-origin-method-execution-attack.html)

The issue is that the same regex – being used to validate that the FlashVars-parameters are valid – is also used to check the jQueryIllegal-function on the jQuery-parameter sent into the SWF-file. The character which makes the issue possible, and should not be in the jQuery-parameter is the dash-character: "-".

Using this character in the jQuery-parameter you can get any JS-function to be called, by inserting jQuery as a bogus property of a string and by adding the dash inbetween:

Jplayer.swf?jQuery=String.jQuery-alert

Now an alert won't do any harm, but utilizing the SOME-attack you're able to do bad things on whatever is hosted on the same domain.

Attack Scenario

For example. Imaging you have a "install application" page on the same domain as jPlayer is hosted. This page requires the user to click "Install" for it to be installed:

<html>
<body>
<h1>Installation of Application</h1>
<form action="http://example.com" method="post" id="x">
    <input type="hidden" name="csrf-token" value="XXXYYYZZZ" />
    <button type="submit">INSTALL APP X</button>
</form>
</body>
</html>

This is just an example, that's why I've used example.com as the target of the POST-request. Also note that this installation page is patched against CSRF.

Now, to do this attack we can now use the jPlayer with the issue mentioned above. The jPlayer will submit the form, with the CSRF-token from another window.

There are two ways to execute this attack. It all depends on if the server - that is hosting the jPlayer.swf - is sending any CSP or X-Frame-Options headers. If not, we only need the victim to click a link posted anywhere. The response of this link would then look like this:

<iframe name="y" src="http://example.com/install.html" onload="x.innerHTML='<iframe src=http://example.com/Jplayer.swf?jQuery=String.jQuery-window.parent.frames.y.document.forms.x.submit></iframe>'"></iframe>
<div id="x"></div>

This will create two iframes, first the installation page and then jPlayer.

If the server is using CSP or X-Frame-Options, we need to host the link on a place where we can trigger a location-change when the user clicks the link, so this one needs two interactions, first clicking the link from the attacker, and then click the link on the attacker's page for the popup to be allowed (due to popup-blockers): <a href="http://example.com/Jplayer.swf?jQuery=String.jQuery-window.opener.document.forms.x.submit" target="_blank" onclick="location='http://example.com/install.html'">HELLO!</a>

As you see here, the same thing happens in both examples:

  1. Two frames are opened, in iframes or in new windows/same window.
  2. Since the jPlayer.swf and the "installation of application"-example are on the same domain, these two windows can communicate with each other. Using window.opener or window.parent.frames depending on the method we're using.
  3. The jPlayer is launched after the installation page (also since SWF has some delay to load).
  4. The jPlayer then calls the function we need, and since both submit() and click() doesn't really care about the parameter - which in jPlayer's case will be "#"+id - they will both trigger.
  5. The form is now submitted and the application is added.

Here's also a movie showing the complete scenario in both examples: http://detectify-labs.s3.amazonaws.com/jPlayer-some/jPlayer-SOME.mov The first one needs interaction and the second one will trigger automatically (since my test page is not using any CSP or X-Frame-Options).

There are several other ways to execute this attack, this is just one example.

Here's the vulnerable code:

for each (_local2 in _arg1) { 
    if (this.illegalChar(_local2)){ 
        this.securityIssue = true; 
    }; 
}; 
if (!this.securityIssue){ 
    if (this.jQueryIllegal(_arg1.jQuery)){ 
        this.securityIssue = true; 
    }; 
};

and:

private function illegalChar(_arg1:string):boolean { 
    var _local2:RegExp = /^[-A-Za-z0-9_.]+$/; 
    return (!(_local2.test(_arg1))); 
} 
private function jQueryIllegal(_arg1:string):boolean {
    var _local2:RegExp = /(jQuery)/; 
    return (!(_local2.test(_arg1))); 
}

How to fix:

It's easy, and will most certainly not break anyone's implementation of jPlayer: You should not allow "-" to be a part of the jQuery parameter, and since you're not really able to make function names that contain dash at all (not in this case at least, since only -a-zA-Z0-9._ is allowed here) there's no reason for it to be a part of the jQuery-parameter in particular.

Regards, Frans Rosén (https://twitter.com/fransrosen) and Mathias Karlsson (https://twitter.com/avlidienbrunn)