Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with content filtering in local frames on iOS #40649

Closed
3 of 5 tasks
pes10k opened this issue Aug 24, 2024 · 4 comments · Fixed by brave/brave-core#26622
Closed
3 of 5 tasks

Issues with content filtering in local frames on iOS #40649

pes10k opened this issue Aug 24, 2024 · 4 comments · Fixed by brave/brave-core#26622
Assignees
Labels
feature/shields/adblock Blocking ads & trackers with Shields feature/shields The overall Shields feature in Brave. features/shields/cosmetic-filtering OS/iOS Fixes related to iOS browser functionality priority/P3 The next thing for us to work on. It'll ride the trains. privacy QA Pass - iPhone X QA/Test-All-Platforms QA/Yes release-notes/include
Milestone

Comments

@pes10k
Copy link
Contributor

pes10k commented Aug 24, 2024

Description

Brave iOS mishandles some aspects of content filtering in local frames (e.g., frames with the url about:blank, or otherwise inherit the security origin of the parent frame, w/o having that origin in the frame's URL)

  1. the iOS app does not apply cosmetic filtering rules in local frames
  2. for the subset of request blocking and request replacing that is done through JS injection in the iOS app (fetch, XMLHTTPRequest, etc), the context of the request is determined incorrectly, which will confuse cases where rules have first-party or third-party filters
  3. scriptlets are not executed in local frames in Brave iOS

The root reason is that checks for the frame's origin are done using window.location.href, which will be something like about:blank, even though the frame's code is running with access to cookies/etc for the parent frame.

This is also a concern for scriptlets, which also aren't executed in iOS in local frames. This is a problem bc the parent frame can access the global object for the child local frame to re-obtain access to unmodified JS structures and prototypes (and so circumvent the scriptlets)

Steps to reproduce

The below is a general example of the vulnerability. The different issues discussed above can all be exploited through slightly different means.

This filter list rule should block all first-party image requests on site.example: site.example$first-party,img

However, if you run the following JS in a page hosted from site.example, the image request will not be blocked

const frameElm = document.createElement('iframe')
frameElm.src = 'about:blank'
document.body.appendChild(frameElm)

const imgElm = document.createElement('img')
frameElm.contentDocument.body.appendChild(imgElm)
imgElm.src = '/image.png'

The casue

Actual result

the image request to //site.example/image.png will not be blocked.

Expected result

the image request to //site.example/image.png shoud be blocked.

Reproduces how often

Easily reproduced

Brave version

all versions

Device/iOS version

all versions

Affected browser versions

  • latest AppStore
  • latest TestFlight
  • previous TestFlight

Reproducibility

  • with Brave Shields disabled
  • in the latest version of mobile Safari

Miscellaneous information

Feel free to contact @pes10k with any questions about this. These vulnerabilities were the result of an ongoing research project between Brave an the University of California, San Diego

@pes10k pes10k added OS/iOS Fixes related to iOS browser functionality feature/shields The overall Shields feature in Brave. privacy features/shields/cosmetic-filtering feature/shields/adblock Blocking ads & trackers with Shields labels Aug 24, 2024
@pes10k
Copy link
Contributor Author

pes10k commented Aug 24, 2024

as an example of why this matters for a scriptlet, consider the following:

a filter list has the rule site.example##+js(nowebrtc), indicating that a scriptlet should be run on site.example to prevent site.example from accessing WebRTC (e.g., window.RTCPeerConnection).

However, site.example can then re-gain access to WebRTC APIs w/ a local frame (since scriptlets aren't run in local frames).

 // this will be blocked / NOOP bc of this scriptlet
 // https://github.com/gorhill/uBlock/blob/26b2ab8bb5fc572a64e75d58f8d4d6388d9909c5/assets/resources/scriptlets.js#L3040
const connection1 = new RTCPeerConnection()
// this will noop bc of the scriplet. No connection is created
connection1.createOffer() 

const frameElm = document.createElement('iframe')
frameElm.src = 'about:blank'
const originalRTCPeerConnection = frameElm.contentWindow.RTCPeerConnection
const connection2 = new originalRTCPeerConnection()
// this will NOT noop, the site has regained access to the WebRTC API
connection2.createOffer()

@ShivanKaul
Copy link
Collaborator

ShivanKaul commented Aug 25, 2024

We will need to do this check for local schemes i.e. about, blob or data (not data: since it gets a new empty origin) (https://fetch.spec.whatwg.org/#local-scheme)

@pes10k
Copy link
Contributor Author

pes10k commented Sep 4, 2024

@ShivanKaul you should still check data, and make sure that parent frames can't access window on the child frame (since they could circumvent scriptlets that way, even if they can't regain access to storage)

@ShivanKaul ShivanKaul added the priority/P3 The next thing for us to work on. It'll ride the trains. label Sep 10, 2024
@brave-builds brave-builds added this to the 1.75.x - Nightly milestone Dec 3, 2024
@Uni-verse Uni-verse added the QA/In-Progress Indicates that QA is currently in progress for that particular issue label Dec 11, 2024
@Uni-verse
Copy link
Contributor

Verified on iPhone XR running iOS 17.7 using version 1.75 (91)

Ensured the following using the test plan mentioned in brave/brave-core#26622 (comment)

  • Verified This should be hidden text is hidden.
  • Verified This should be blocked is not displayed in the main or the iframe.
  • Verified First party body has a value of 1, First local frame body has a value of 1.
  • Verified that disabling Shields will override the custom filters for the website.
example example example
img1 img2 img3

@Uni-verse Uni-verse added QA Pass - iPhone X and removed QA/In-Progress Indicates that QA is currently in progress for that particular issue labels Dec 11, 2024
StephenHeaps added a commit to brave/brave-core that referenced this issue Jan 13, 2025
- Generic cosmetic filter list rules are not applied on some sites (brave/brave-browser#42471).
- Local frames fix (brave/brave-browser#40649).
- Use secure $.windowOrigin (brave/brave-browser#42539).
StephenHeaps added a commit to brave/brave-core that referenced this issue Jan 13, 2025
- Generic cosmetic filter list rules are not applied on some sites (brave/brave-browser#42471).
- Local frames fix (brave/brave-browser#40649).
- Use secure $.windowOrigin (brave/brave-browser#42539).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature/shields/adblock Blocking ads & trackers with Shields feature/shields The overall Shields feature in Brave. features/shields/cosmetic-filtering OS/iOS Fixes related to iOS browser functionality priority/P3 The next thing for us to work on. It'll ride the trains. privacy QA Pass - iPhone X QA/Test-All-Platforms QA/Yes release-notes/include
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants