New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Loading player…

The Attacker is Inside: Javascript Supplychain Security and LavaMoat

DevconMon, Oct 9, 2023, 12:00 AM

Visit the https://archive.devcon.org/ to gain access to the entire library of Devcon talks with the ease of filtering, playlists, personalized suggestions, decentralized access on Swarm, IPFS and more. https://archive.devcon.org/archive/watch/6/the-attacker-is-inside-javascript-supplychain-security-and-lavamoat/ We all use open source, it is the wealth of the commons that forms the foundations we all build on. While this is incredibly empowering, we may be inviting the devil to dine with us. This talk examines software supplychain attacks in the javascript and crypto ecosystems and how to keep your app, wallet, and users safe. We'll look at the free and opensource tool LavaMoat that protects MetaMask. Speaker(s): Kumavis, Naugtur Skill level: Intermediate Track: Security Keywords: security,javascript,development Follow us: https://twitter.com/efdevcon, https://twitter.com/ethereum Learn more about devcon: https://www.devcon.org/ Learn more about ethereum: https://ethereum.org/ Devcon is the Ethereum conference for developers, researchers, thinkers, and makers. Devcon 6 was held in Bogotá, Colombia on Oct 11 - 14, 2022. Devcon is organized and presented by the Ethereum Foundation, with the support of our sponsors. To find out more, please visit https://ethereum.foundation/

Transcript

foreign [Music] hi everyone I'm kumavis I founded metamask with Dan Finley and now I run the security research team at metamask today's talk is the attacker is inside JavaScript supply chain security and lava mode uh so yeah love mode this is what I've been spending the past couple years working on first and foremost it is a set of security tools for any JavaScript application to mitigate software supply chain risks so what is the software supply chain it's everything that touches an application or plays a role in its development sonotype has this cool website it's a timeline of supply chain attacks you can scroll through it and see how many they are and a lot of them are from Python and rust but a good 50 are from mpm they're from the JavaScript ecosystem so why is Javascript supply chain targeted so so frequently primarily because it's really popular this is from the stack Overflow user survey and uh for self-described professional developers javascript's way at the top and there's typescript in node.js not far behind so when we're talking about JavaScript supply chain we're primarily talking about npm dependencies so this is your apps dependencies your dependencies dependencies your build systems dependencies any other tools you might be using you might think that these are your dependencies just the dependencies listed and packaged Json in your app but that's just like an inner ring around your application in part of a constellation of your whole dependency graph so that's why there's so many node modules in the node modules directory okay so to understand what it looks like when it goes wrong let's look at the copay wallet hack uh copay wallet was a Bitcoin wallet by bit pay and this is my primary case study for Designing lava mode so at the time end of 2018 uh the copay wallet hack also known as the event stream incident made a lot of news an attacker got control of a dependency that was used in a Bitcoin wallet deployed a targeted attack against that wallet and stole private keys and digital assets from the users of that wallet and it was I think three versions of the wallet that had the attack in it were published so they didn't even know it was in there for a while okay so let's look at the the build pipeline to understand how it got in there now so this is a non-custodial wallet so the keys are in the user's application only they're not on a server or something like this so the attack happened here at runtime that's where the secrets were here that's where the private keys were but uh the evil dependency wasn't even part of the front-end application it was part of their build system so it actually entered in here and then it went on the disk during build time and modified a dependency that ended up in the web app but it sorry it could have also happened here at the dependency install time um npm has life cycle scripts so after you install a package it gets a chance to just run any command on your computer to you know finish up its install process or whatever so Jackson Palmer of Dogecoin said bitpay essentially trusted all the Upstream developers to never inject malicious code into their wallet Upstream developers being the dependency developers in this case and uh yeah he's right and it sounds pretty scary when you say it in these terms and was bitpay being particularly unsafe well this is how we make all JavaScript applications today and most wallets not metamask so so when this attack happened there was all this discussion how do we fix this should we never use dependencies what are we giving up on an open source and collaboration what about don't roll your own crypto like how does that fit in audit all your dependencies always yeah that's a great idea but how many dependencies do you have hundreds thousands tens of thousands and when you need to make a change are you going to be able to wait and re-audit all those things so is there nothing else what else do we have here so around this time I I met agorik and learned of their indo.gs hardened JavaScript tool set so these are tools for working with untrusted JavaScript and in the core of it they have this package called SAS and it gives you a couple things for dealing with untrusted JavaScript um so there's a couple things about JavaScript that make it easy to attack one is everything is mutable by default all the built-in functionality and everything so you can just go in and modify array prototype and map and and change the way JavaScript works this can also give you access to objects that are being used like on the complete other side of the application of where you got your attack in so you want to lock this down and conveniently CES provides a function called lockdown that does exactly this by calling lockdown you're doing what's shown here at the bottom of the screen basically calling object freeze on all the prototypes all the built-in parts of JavaScript okay that was simple enough all right there's this other problem called ambient Authority this means simply by being able to run some JavaScript you get access to all the powers of that platform network access or disk access so say I have some little package I'm an attacker I've gotten a hold of sub-package that's deployed in my victims code now this package doesn't do very much it's just formatting strings but because of ambient Authority I have access to fetch the network access us of access to environment variables and I can send them home to my evil layer and maybe there's some API keys or something in there so just because I get to provide a little bit of code I get to have all powers of the platform and that's quite dangerous so cess provides this notion of a compartment it puts a little container around the JavaScript and limits access to what that code can can touch or modify so for example if I have some code that that needs to make Network requests and it needs to know the current location of the web app in the web browser or something I can give it just those things and not give it disk access or other powerful features of the web browser and then I can run my code in here and it will only get access to those things as well as the basic JavaScript functionality you don't need to know the internals but I think it's really fascinating and I've been working with JavaScript for a long time before I saw how this works and I didn't think it was possible so let's take a look it relies on two weird parts of JavaScript that you may not be familiar with one is the with statement with the with statement first you have an object it has some properties on it and you can you have the with keyword and then you put the object as the target of The Wiz keyword then you have this block inside the block all the properties on the object can be accessed as if they were variables in scope well there it is it's not particularly interesting but that's what the width statement does the next piece is the proxy if you're familiar with Getters and Setter of properties it's like that for the whole object in any operation on that object you get various handlers to intercept what those things do now by combining these two things with the with statement and then a proxy in here we control all the scope access inside this block so you have your untrusted code here it's trying to like get network access with fetch it'll look it up here it'll go to the proxy it'll say do you have Fetch and your proxy can throw a reference error return undefined whatever you want but it can block that lookup another way to write this which is easier to audit it may be easier to think about is with two statements one here the inner one you put the untrusted code here it's trying to look up fetch it'll look up inside this object first and that's the object we gave to the compartment when we said you should have access to these things and these things only if it's in there it'll it'll just get it it'll get whatever value you gave it if it's not in there it'll go up to the scope Terminator and that thing just always says no you don't get it there's a couple more things you need to make it safe but you don't really need to think about the implementation you can just use this API okay so SAS gives us lockdown and compartment and I compose these in lava mode lava mode wraps packages inside of compartments and only gives them what they need to run so that little string formatting package we had before it won't have access to network and I won't have access to disk another powerful features how you use it sorry it's a little small it's kind of like this previously you might run node index for your little server you replace that with love mode index But first you put this right Auto policy API and that will generate a policy file of what the packages are allowed to use and then you just run you just replace node with lava mode and run normally and it will at runtime enforce those packages only get what they need the policy looks something like this this is a policy for one package you'll have a bunch of them in your policy file this is all automatically generated and works 99 percent of the time without any additional changes uh here in the built-ins these are built-in packages provided from node we're giving them just exactly what they need for example we're giving it just read access from the file system and not write access or anything else also giving some Global variable access and they're only allowed to import these packages so that's just an example but in order to help you review your policy we have this visualization dashboard the per so there's the list of your dependencies on the left and a graph of your dependencies on the right the purple node is our application here our example application and then all these uh this graph coming out of it are all the dependencies and the transitive dependencies and you can you can dig in and take a look at what these packages are and what their policy is and the point of this is to help you prioritize the auditing of your dependencies and to review your policy because remember with without lava mode this is what your app looks like every single package has is maximally dangerous whereas with lava mode we know that some of these are are safe all these green ones for example are not importing any globals or any built-ins they're only composing other packages this is a static version in case the internet.org okay so here's the build pipeline again install time build time and then runtime on your users machine so we have in lava mode tools for each of these steps for depth install we have lava mode allow scripts this me this will prevent all these dependencies from being able to run a random command on your computer when you install them and then you can opt into just the ones you want at build time you want to run your build process in lava mode node and you want to add to your build process a plug-in for your bundler so we have one for browserify we're working on one for webpack for react native and swc switch so this is in production in metamask we're protecting tens of millions of users now so we know this can scale you can use it too but we do need your help it's open source it's really it's out there find it on GitHub uh try it out let us know if it works if you run into a bug open an issue if we don't have a plug-in for your bundler let us know and maybe you can help us with that okay thank you very much this has been lava mode thank you does anyone has any questions uh so I actually worked at bitpay on a different team oh cool uh it's dirt overlapping the time of the copay hack and uh yeah like you said it's it's not necessarily that that company had bad processes it's sort of the whole ecosystem doesn't really have a good solution um since that time not only at that company uh did no one really talk about lava I mean I brought it up because I was aware of it at the time um but externally any side projects I've been on I've really never had anyone propose using it so do you think there's something not at the technical level but like at the social level that we should be doing to make this a more common part of stacks either across the board or when we're working on applications that deal with private Keys specifically yeah great question so what you know what processes should we put in place of what tools are out there there's a lot of projects that are working on preventative measures like Ci flows that warn you if there's known vulnerabilities or some code scanning to see if there's something funny looking like eval and those are great and fantastic and you can use them in conjunction here like one example is socket.dev that's a friend's company and they're doing great scanning work but it's all preventative at the beginning that's not the way the security of your operating system works right it's it's making sure that all your applications are are safe I mean I was very surprised that that no one else was working on runtime protections besides the gorick folks which we partner on on building lava moon yeah I think more people need to just know that there's a solution that exists and you can actually do something about this uh hi so I had a question um about about the auto policy generation can you explain the logic behind that a little bit Yeah so it um we are using static analysis here for convenience and not for the security layer uh static analysis is can be faulty it'll it'll miss things and it's generally imperfect but here we use it to generate the policy so you don't have to write it all by hand and then we enforce it with the law of moat kernel which is not relying on static analysis but yeah basically what it's doing is you give it your entry point it's walking through all the requires and imports and walking through your graph it's you know converts the code to an AST it looks and analyzes it for references sees when there's Global references sees when there's Imports and it'll actually follow the Imports to where they're used so it can give you just the minimal things that you need like only using the read power of the file system instead of the right power for example I was wondering if you can talk a little bit about like the limitations of lava mode specifically like if even if you grant access to like a specific function or feature to a package like they can still I guess use that feature in a malicious way yeah I was wondering like what else we should watch out for even if we use love remote yeah absolutely um so it will look at your modules love mode we'll look at your modules and generate a policy and if it sees that you know network access is used there it'll put that in the policy but if it's something that's not supposed to have network access then it we rely on the user the security engineer to catch that now it's most likely you don't have a supply chain attack in your app right now but you might have one in the future so every time you change your dependencies you can just run that thing generate a new policy and you'll see the diff of your policy and that's a lot less to review some other things there is a slight performance impact for compute but if you're relying on network or disk which is usually what you're bound when you're Computing then it doesn't make a difference for you it is very cool how you solve the problem with um running insecure code with the width and the proxy and I was wondering if there is any difference with doing it with a web worker a web worker yeah you can use iframes and web workers and you can use in on node.

js you can use the VM package but what these what those create are what we call Realms so you actually have a slide for it it's it does work but it's not very good for backwards compatibility yes when you use oh I'm not up on the screen we we have a lot of jargon when we're talking about this JavaScript language security stuff but we use this term realm to refer to like a window frame and so an iframe is another realm and they're different in a couple of subtle ways um one is inside of the VM or the iframe or the webworker um capital A array is not the same as the capital array on the outside we call this problem the identity discontinuity problem and it breaks things like instance of so an array from the inside is not an instance of array on the outside and so um this is fine you can deal with this problem but it is really bad for backwards compatibility and that was a primary requirement for lava mode because this was not built into metabouse from the beginning I built it afterwards and rewriting the app from scratch was not an option 33 there is a proposal to in ecmat DC 32 39 sorry to introduce compartments natively in JavaScript I would like to know if you guys are behind that proposal and what do you think about the curing state yeah great um so yeah we're trying to take some of the things that we built here like the the car compartment API and actually get it standardized into the JavaScript language at the tc39 JavaScript standards body I I'm not up to date on what the status is um but it seems to be finding its way in via the loader API so that when you load modules you load them in a special compartment thanks for your talk I I would like to ask if you can share some supply chain attacks I might have actually been detected at Mid Ms since you started using it oh great question we have not detected any supply chain attacks the the day-to-day battles at metamask are primarily phishing um but the problem with the supply chain attack is even if it's uh more rare a little less common it could take down the whole wallet and that's why this protect this uh this protective system is so important I think we have time for another question yeah um my name is my question for you is why not use quick quick yes with a awesome instead of uh success pronogoric uh were you asking about wasm modules yeah why not use Quick yes we any Western Union compatibility I didn't catch the whole question but wasn't modules have been designed to be um sort of self-contained and not have ambient Authority not have access by default to Network and and disk so that is fantastic I'm so glad they designed those things that way blockchain companies use some some what some engines that I have some special add-ons that you can enable networking on file system access sorry I couldn't understand the question sorry uh so there were some engines in the market that supports add-ons that give you the connection to tensorflow file system and networking I heard some cool things like tensorflow in there but I still can't make out the whole question maybe you could ask someone next to you to repeat it for whatever reason I I'm not able to hear it uh I I don't know if I'll go about your question but I'm a bit closer so uh he was asking about um inside wasm or the wasm connections are there any contain connections to tensorflow or what's the last one file system or networking all three oh yes okay so how do wasm modules connect to the powers they need like disk access and network access great question um so much like with the compartments you have to pass them in and make them accessible on the like foreign function list that you expose to the awesome I'm not a waslam expert so I can't answer perfectly but you you do have to you know go in and put them there they don't get it by default uh I have a follow-up question um well not directly related but we were hacking on snaps over the weekend and um I was just wondering like the interface in which lava mode interacts with ses and um and that JavaScript engine because uh no I mean just on the high level I was having a hard time differentiating where lava mode ended and SES started yeah uh great question um so uh we have these compartments from SAS uh SAS is giving us primarily lockdown and compartments there's a few other features I didn't cover today um and then I in lava mode composed those by putting the compartments around the packages you also mentioned metamath snaps this is a plug-in system we're building for metamask to extend the functionality and create new user experiences for minimaz but because we're putting uh outside code inside the wallet we have to make sure it's safe and so we're also using SAS compartments to limit their powers like limiting network access Etc thank you so much

Automatic transcript — names and jargon may be misspelled.