MetaMask JavaScript Security Stack (Part 3 - Snow) [๐]
14 Jul 2023Originally posted on X
After covering LavaMoat ๐ scuttling #security feature and its fundamental issue of being unable to deny access to the "document" prop, which effectively eliminates its core concept, I implied we address that too with our in-house security tool.
#JavaScript folks? Meet Snow โ๏ธ:
Recap: What's scuttling?
Scuttling is a security feature in LavaMoat that removes all powerful capabilities from the global object so that if JS code escapes its LavaMoat sandbox to find more powerful APIs, it'll fail thanks to this feature making the global object useless:
Recap: What's scuttling's weak spot?
Problem is, not all props can be scuttled. One specifically ("document") can be used to form new global objects (e.g. with iframes) where the powerful APIs scuttling tries to deny can once again be found,
Making scuttling not very effective:
So what can we do about it?
Applying scuttling to all potential future global objects automatically, would restore the power of scuttling.
Because then, if attackers use "document" to create a new global object, scuttling would immediately be applied to that new object - magic!
In other words:
1. scuttle main global object (=top)
2. intercept iframe creation
3. attacker creates iframe
4. scuttle iframe's global object at interception
5. return iframe to attacker
Result:
Attacker gets the iframe they formed, but its global object is also scuttled!
But,
This is rather complicated because the browser doesn't offer us such power.
Meaning, we'd have to implement such a solution as a #JavaScript shim, where we map and (synchronously!) intercept all possible ways of forming new global objects.
Accomplishing that will allow us to...
... not only scuttle any newly created global object, but in general to run any arbitrary code for every time such an object is created - before the creator gets access to it.
That would restore the power of scuttling.
You see where I'm going with this, right?
Meet SNOW JS โ๏ธ:
Snow does just that!
By installing Snow in your webpage as first script, Snow intercepts (aka monkey patches) all methods of creating new realms.
Afterwards, by passing Snow a callback, Snow does its best in making sure to invoke that callback with every new realm creation.
Building a bulletproof version of Snow is a long on-going mission that's yet to be completed, facing multiple complex obstacles along the way.
But with Snow, we're less concerned of "document" prop killing our scuttling idea - we just recursively scuttle child objects instead ๐
Btw, if you're building similar security tools that apply JS runtime protection to web apps, you're probably affected by similar threats. You're welcome to reach out, ask about and also use Snow.
In the next ๐งต, I'll get more technical, exploring parts of Snow and its challenges.
In the meantime, some resources on Snow+scuttling:
* Integrating Snow into MetaMask ๐ฆ
* Snow on GitHub
* Live Demo of Snow (can you pop an alert?)
* Awesome Realms Security Repo
#JavaScript folks? Meet Snow โ๏ธ:
Recap: What's scuttling?
Scuttling is a security feature in LavaMoat that removes all powerful capabilities from the global object so that if JS code escapes its LavaMoat sandbox to find more powerful APIs, it'll fail thanks to this feature making the global object useless:
Recap: What's scuttling's weak spot?
Problem is, not all props can be scuttled. One specifically ("document") can be used to form new global objects (e.g. with iframes) where the powerful APIs scuttling tries to deny can once again be found,
Making scuttling not very effective:
So what can we do about it?
Applying scuttling to all potential future global objects automatically, would restore the power of scuttling.
Because then, if attackers use "document" to create a new global object, scuttling would immediately be applied to that new object - magic!
In other words:
1. scuttle main global object (=top)
2. intercept iframe creation
3. attacker creates iframe
4. scuttle iframe's global object at interception
5. return iframe to attacker
Result:
Attacker gets the iframe they formed, but its global object is also scuttled!
But,
This is rather complicated because the browser doesn't offer us such power.
Meaning, we'd have to implement such a solution as a #JavaScript shim, where we map and (synchronously!) intercept all possible ways of forming new global objects.
Accomplishing that will allow us to...
... not only scuttle any newly created global object, but in general to run any arbitrary code for every time such an object is created - before the creator gets access to it.
That would restore the power of scuttling.
You see where I'm going with this, right?
Meet SNOW JS โ๏ธ:
Snow does just that!
By installing Snow in your webpage as first script, Snow intercepts (aka monkey patches) all methods of creating new realms.
Afterwards, by passing Snow a callback, Snow does its best in making sure to invoke that callback with every new realm creation.
Building a bulletproof version of Snow is a long on-going mission that's yet to be completed, facing multiple complex obstacles along the way.
But with Snow, we're less concerned of "document" prop killing our scuttling idea - we just recursively scuttle child objects instead ๐
Btw, if you're building similar security tools that apply JS runtime protection to web apps, you're probably affected by similar threats. You're welcome to reach out, ask about and also use Snow.
In the next ๐งต, I'll get more technical, exploring parts of Snow and its challenges.
In the meantime, some resources on Snow+scuttling:
* Integrating Snow into MetaMask ๐ฆ
* Snow on GitHub
* Live Demo of Snow (can you pop an alert?)
* Awesome Realms Security Repo