An exploit has been discovered that could allow ad blocking filter list maintainers for the Adblock Plus, AdBlock, and uBlocker browser extensions to create filters that inject remote scripts into web sites.
With ad blockers having a a user base of over 10 million installs, if malicious scripts were injected it would have a huge impact as they could perform unwanted activity such as stealing cookies, login credentials, causing page redirects, or other unwanted behavior.
The $rewrite filter option
For those who are unfamiliar with how ad blockers work, they utilize lists of URLs related to advertisements and malicious behavior and are typically maintained by a small team of people or even a single person. When these lists are loaded by an ad blocking extension, like Adblock Plus, the extension will prevent the browser from connecting to the listed URLs and thus advertisements or malicious scripts are unable to load.
For example, below is the filter list for the popular ad blocking list called EasyList.
When Adblocker Plus 3.2 was released in 2018, a new filter list option was added called $rewrite. This option allowed a list maintainer to replace a web request that matches a particular regular expression with another URL.
The only caveat is that the replacement string must be a relative URL, which means it does not contain a hostname, and when rewritten must be in the same origin domain as the original request.
For example, the following filter rule will cause all requests for example.com/ad.gif to be replaced with example.com/puppies.gif. So instead of ads being displayed on a page, you will see cute pictures of puppies.
Yuhong Bao's blog
On the other hand, as the rewritten URL has to be on the same origin as the original URL and must be a relative URL, the following $rewrite rule will not work.
To make $rewrite even more difficult to exploit, this filter option will not work against requests of the type
So if a malicious script has to be on the same site, has to be rewritten to a relative URL, and can't be loaded via a script tag, how can a list maintainer exploit it?
Chaining $rewrite with web service redirects for an exploit
Today security researcher Armin Sebastian explained that under certain conditions it is possible for a rogue ad blocker filter maintainer to create a rule that injects a remote script into a particular site.
To do this, you would need to find a site that allows scripts to load from any domain, contains an open redirect, and uses XMLHttpRequest or Fetch to download scripts that will be executed. This was not too difficult to find, as Sebastian utilized Google Maps for his Proof of Concept.
The following criteria must be met for a web service to be exploitable using this method:
- The page must load a JS string using XMLHttpRequest or Fetch and execute the returned code
- The page must not restrict origins from which it can fetch using Content Security Policy directives, or it must not validate the final request URL before executing the downloaded code
- The origin of the fetched code must have a server-side open redirect or it must host arbitrary user content
The two keys to the puzzle is the use of XMLHttpRequest or Fetch to download scripts and an open redirect.
This is because requests using XMLHttpRequest or Fetch to download remote scripts for execution will not fail when using the $rewrite option. Furthermore, the open redirect is equally as important because it allows for the reading of the script by XMLHttpRequest from a remote site, while still appearing to be in the same origin.
As an example, Sebastian utilized Google Maps, which utilizes XMLHttpRequest to load scripts and because google.com has an open redirect as part of the search results pages. This allowed him to chain an exploit together using the $rewrite filter option along with the open redirect to read a remote script as shown below.
With the above rule in place, when you visit www.google.com/maps/, the filter rule will use Google's open redirect to read the contents of from https://majestic-ramsons.herokuapp.com/.
Sebastian has reported this to Google, but their stance has always been that the open redirect is "Intended behavior".
"Google has been notified about the exploit, but the report was closed as “Intended Behavior”, since they consider the potential security issue to be present solely in the mentioned browser extensions. This is an unfortunate conclusion, because the exploit is composed of a set of browser extension and web service vulnerabilities that have been chained together."
In order to mitigate this chained exploit, Sebastian recommends that web sites utilize the Content Security Policy header and the connect-src option to specify a whitelist of sites that scripts can be loaded from.
"The exploit can be mitigated in the affected web services by whitelisting known origins using the
connect-src CSP header, or by eliminating server-side open redirects."
Why would a filter maintainer go rogue?
While there may numerous ways to modify a filter list, Sebastian told BleepingComputer his main concern is a "filter list operators that may perform targeted attacks that are difficult to detect".
As many filter list maintainers are volunteers, it's conceivable that they would add an unwanted filter for numerous reasons.
For example, Sebastian explains that in 2018 a list maintainer added a filter for political reasons that blocked various union web sites in Finland that were conducting protests.
It should also be noted that while the extensions come with only a few filter lists, there are many more maintained by third-parties that can be added. It would not be surprising to find that a popular list is purchased and then modified to include malicious filters or for a maintainer to be enticed by money to make a temporary change and revert back before anyone notices.