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

Toolbox race condition and potential fix #12

Open
swoops opened this issue Jul 25, 2022 · 2 comments
Open

Toolbox race condition and potential fix #12

swoops opened this issue Jul 25, 2022 · 2 comments

Comments

@swoops
Copy link

swoops commented Jul 25, 2022

Toolbox is injected just a bit late. This means inline code in the website will execute before the toolbox has a chance to hook sinks. Inline code is common among ad networks, where difficult to find XSS is also common.

You can fix this if you move this feature to the background script and use browser.contentScripts.register.

example problem

I loaded the a page with the following content:

<!DOCTYPE html>
<script>
alert("Page alerts");
</script>

I then used a toolbox to switch alert for prompt

alert=prompt;alert("thisIsPrompt");

Visiting the page caused an alert because the inline script finished executing before the toolbox was loaded. You can see the prompt that is fired by the toolbox is under the alert box.

ss1

So if you were attempting to proxy/reflect or hook alert as an interesting sink, you would of missed at least one execution.

Why

I did not look to hard at your code, but surely your toolbox scripts are stored in some browser API storage system. All calls to that system are async. Additionally, content scripts don't have access to those API's so you query them through the background script with another async message. While those asyncs are waiting, the loaded page is executing code.

FIX

browser.contentScripts.register lets you register a new content script from the background script. This can be done with a string or file. Using both you can easily inject the toolbox into the page before the page can execute any code. There is still an async storage lookup, but it happens only once in the background script, then the content script gets registered like a static file. No ansycs happen during page load and the toolbox gets to execute before inline scripts.

Be aware, this API is Firefox only. So it can't be ported to Chrome if you chose to do that in the future.

Also of note, there is a matches parameter that the API selects so you can easily isolate what websites you want to send the toolbox to.

Example

I know the fix works because I use it in my own web extension. You can see the relevant code here:
https://github.com/swoops/eval_villain/blob/master/src/js/background.js#L331. The code is a user config that is pulled from storage and the file shoves it into the page.

Using the same code from the "example problem" above, Eval Villain pulls the user config from storage that says to hook alert, registers the content script, then when the page loads Eval Villain hooks alert before the page executes any inline scripts:

ss2

Size of code does not matter, JS is single threaded. So as long as there is no async, the page never gets a chance to steal the thread and do something.

You are welcome to use any of my code. I would of even sent you a pull but I think your code is to pretty to corrupt with my terrible JS.

Great tool, I look forward to using it.

@B-i-t-K
Copy link
Member

B-i-t-K commented Aug 31, 2022

This is a cool idea, I will try to implement it

@D3vil0p3r
Copy link

@B-i-t-K @swoops Was this issue solved?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants