Hey everyone, my name is Martin, thank you for having me. Today I will be talking about the seven phases of smart contract hacking. In this talk my idea is not to jump and dive into technical parts of what it means to hack smart contracts, but actually I want to give a little bit of perspective and try to talk about the bigger picture of what does it actually mean to hack smart contracts. So if you're a pentester, if you're a bug hunter, perhaps working in application security or other realms of information security, you can jump into the Ethereum ecosystem and start helping us secure the entire platform. So a little bit of background about myself, I'm Martin, I'm a security researcher at Open Zeppelin, one of the leading companies in smart contract audits in Ethereum. I'm a systems engineer, I'm doing a master's degree in cyber security and cyber defense at the University of Buenos Aires, and I used to work as a pentester mainly on application security, infrastructure, mobile applications, web applications at a big four. And then I jumped into being a security researcher here at Open Zeppelin. Well let's say again that you're a pentester, you might be a bug hunter, a white hat hacker, perhaps working in other realms of information security, but you're interested in blockchains and smart contracts, you have heard about them, because to be honest we have hit the headlines a couple of times. There has been many hacks in the latest months around smart contracts in Ethereum. So as you see, many hacks and in my opinion we need more and more security experts to jump into the field and to help us secure the entire ecosystem. So this talk is mainly aimed at you. And the question is if you can hack a smart contract, right? What knowledge do you have already that can help you out here in the smart contract world and that you can start applying today to start hacking smart contracts? And well the answer is yes, that you do have some knowledge, because you do know which are the seven phases, let's say, of a typical security engagement. And when I say seven, I don't mean to be strict with these phases that we will be talking about. It's just a way of organizing the talk, but perhaps when you do bug hunting, some phases you might skip them or you might do others, but the idea is to outline our work as security auditors or bug hunters or white hackers in these seven phases, so we can have a common language to talk about this. Well, these are the seven phases that I have, that we will be talking about. First, scoping, then reconnaissance, identification of vulnerabilities, exploiting these vulnerabilities that we have found. What does it actually mean to do post-exploitation in the smart contract world? And we'll be asking ourselves whether that's an actual thing or not. And then we'll be briefly covering reporting fixes and retests. So you might be already familiar with these phases. The idea of today is to see how these phases apply in the smart contract world and whether we can start drawing some parallels between these phases and the ones that you are used to applying. So let's get started. Let's talk about scoping. If you come from the, let's say, application security world or maybe doing pen testing for infrastructure exposed on the internet, you might be familiar with the fact that you have IP addresses, right? When you are scoping your work, you will be given IP addresses that will help you understand the systems that you are about to audit or to assess. In the Ethereum case, we also have addresses. In this case, we have Ethereum addresses. I know they are not the same. I know there are many differences between them, but the idea is to start drawing, as I said before, some parallels between the worlds. So we can think of these addresses as ways of allocating resources, let's say, in the first case on a network and in the other case on the blockchain. When you are working on smart contracts, you will not only have one Ethereum address, but you can have many Ethereum addresses that are related to each other. And you may not even have Ethereum addresses, but actually you can have domain names, right? As in the classic world, you have the DNS that will help you resolve from human readable names to actual IP addresses. In Ethereum, we have the Ethereum nice service, which will help you translate human readable domain names like johndoe.eth to Ethereum addresses, such as the one there. But sometimes, most times actually, you won't have... perhaps you won't have an Ethereum address or many addresses. You might only have Solidity source code. And Solidity is the smart contract language that we use nowadays. There might be others, but Solidity is the smart contract language that is high level and that can help you code smart contracts in an easy way, let's say. So you might be given a repository with these files or you can actually find that source code in Etherscan, which is the main explorer for the Ethereum blockchain. And at this point, engagement will become something like a white box engagement, right? You will have access to the source code, but there are ways, as we will see later, to actually deploy these contracts and to start poking around with them as a living program. So there are two ways, perhaps, of approaching the assessment. So if you want to go to Etherscan, you can find the verified source code there. This is, for instance, the source code for DAI, one of the main stable coins in the Ethereum ecosystem. And you can go to its address and retrieve the source code there. But if you don't have the code, you can actually decompile the EVM bytecode and try to read it in a nicer way using EVM, right? So this is a decompiler for Solidity code and will help you understand what's behind this sometimes difficult to parse EVM bytecode and will give you a more readable way to understand it. So again, you might have the source code, but if you don't and you only have an Ethereum address, you can use this decompiler that can help you out. Well, once we are done with this scoping phase, we move on to the second one, which is reconnaissance. In reconnaissance, we basically want to understand what's in there, right? So we might be given, as I said before, a list of files. And we are not only talking about one, two, three, but many, many and several files that you might be given. And sometimes the names of these files don't even make much sense at the beginning, right? So we see here like files named flap, flip, flop. And that is not so self-explanatory, to be honest. So we need to start looking deeper into the files and to actually understand what they are doing. But when we look deeper into the files, we will see Solidity code, right? This is what actual Solidity looks like. Just a brief example for those that are not familiar with it. It looks like another object-oriented language. At the beginning, the syntax is similar. As you go deeper and deeper into Solidity, you might start seeing several differences with other languages. But again, the first look of Solidity looks like another object-oriented language. But if you go to actual files, to actual Solidity files today being used in Ethereum, you will see that sometimes developers are not that clear with their intentions of the code, and you will see that functions have weird names, some variable names are not that clear, and you cannot make much sense out of the things that you are reading in the code, right? So it might be a bit disorganized or repetitive, or the function names might not be the best, as we see in these cases. But luckily, there are tools and there are things that we can start doing in this reconnaissance phase that can help us get more familiar with the code and understand what it's trying to do. So in this case, what we want is, we want to understand the architecture, the interactions between the contracts, we want to see where the contracts expose functions, because we need to use them as entry points for attacks, we need to see the inheritance chains of this contract, and many other things, right? But I want to make a special point on intention. We as, let's say, auditors or bug hunters looking at Ethereum smart contracts, we need to understand the intention of the code, right? Intention is not usually the same as implementation, so we need to find the differences between intention and implementation, and actually start digging bugs in that sense. So special attention to the intention of the code, not only what it's actually doing, but what it intends to do. For these three last points, for the roles of a system, the integration points, and intention, the work in reconnaissance becomes a bit of a manual work, and reading documentation, reading the code, reading pull requests, perhaps talking to developers, from those things we can start understanding these points, right? But for the others, there are tools that can actually help us in a really nice way, as we are about to see. So if you want to see some things about inheritance chains, for example, you can use EtherScan, we can use Surya, Slyther, which are tools that can help us print these kind of diagrams of inheritance, and can help us understand how do contracts relate to each other in a code base. Slyther, that is a static analyzer, can also help us see which are the exposed functions of a contract, so we can see whether it has many public functions, which are these public functions, to which contracts do they belong, and if there are private functions in those contracts related to these public functions. So Slyther can help us explore this. There are also IDE plugins, such as in Visual Studio Code you have the Solidity Auditor plugin, which is super useful, and as you see here in the GIF, it can help you track, for instance, function calls. Starting from a public function call, you can go all the way down to the private calls, and see whether in this way you can track different bugs in the code. And another thing that is super useful, that I at least myself find useful, are diagrams. So these diagrams are things that you can actually draw yourself, put together yourself, and can help you out really to find several bugs in the code. So give it a shot, try it out, please don't go so crazy on it, but again can help you understand the relationships between different contracts and functions and dynamics of the system. So that's about it with reconnaissance. We have seen tools, we have seen manual things that you can use, and now let's get on to one of the most interesting parts, I guess, which is vulnerability identification. So this is one of the main objectives of our assessment, is to actually find vulnerabilities in the code. And if you're a beginner with it, I wouldn't recommend you to start trying to hack smart contracts in crazy new ways. I would suggest that you start with the basics. So you might read the Mastering Ethereum book, you can read online databases of known attacks, we have the SWC registry which classifies vulnerabilities and with different test cases. Of course not all vulnerabilities, not all weaknesses in smart contracts, but the most common ones are there, and you can go ahead and read them and start learning which are the basics of smart contract security. But if you like learning as playing, like learning by doing, you can play the Ethernode by OpenZeppelin, which is a kind of a capture the flag challenge, a set of challenges actually, and it's super fun and can help you understand how to hack smart contracts and learn about security in that way. One thing that also always surfaces when we talk about vulnerability identification in smart contracts is this difference between automated and manual work, right? I think this also happens in, for instance, application security, where you might have scanners that can help you out identify vulnerabilities in an application, but also people or pen testers, hackers, tend to also do some manual work. So I guess it's always about complementing the automated and manual work. You shouldn't fully lean towards one or another, but doing both automated and manual work to find out these vulnerabilities. So in the automated realm, we find many tools that can help us out in Ethereum for smart contracts insolidity, or perhaps you don't even need for some of these tools, the source code, you can only have the EVM bytecode. We have Slyther, Manticore, Keyedna, Mithril, Veris, Solpacale, and many more. I won't dive deeper into this. The program analysis world is extremely interesting and it's a whole world on its own. The idea of this talk is just to briefly present them. And to also mention that, of course, the automated tools, while they are good, they might have bugs, right? They might not always work as expected, they might produce false positives, and they might not even find the most critical bugs. So last year, we ended up publishing a post when we found a critical vulnerability in the MakerDAO contracts. And we realized that many of the tools weren't capable of finding that type of bug. And the forum post became really interesting when the authors of these tools jumped in and started explaining the improvements that they were applying in the tools to actually find the bug. And I think that right now, many of these tools are already capable of finding this bug that we found at MakerDAO. So the automated tool world is always moving forward and coming up with new ways of finding vulnerabilities, and that's super cool. But also, we do manual work, right? In this case, we focus on the business logic and the intention of the code. And this actually means that, at least in my experience, most of the most critical bugs that I have found in smart contracts come actually from business logic and not from, let's say, solidity common patterns. So by understanding the business logic of the contracts, you can actually start highlighting these differences between implementation and intention and start coming up with different attack vectors to break the contract. Special care should be paid to sensitive functions. And when I say sensitive, I mean functions that may have convoluted and mixed logic, functions that, let's say, handle decimals, arise signatures, which are usually not so straightforward to do in solidity. So usually developers need to come up with different hacks to implement, let's say, handling decimals. So there might be bugs there. Dangerous math, functions making external calls to untrusted contracts is also something that we should be paying attention to. And uses of assembly or low-level calls in solidity is usually a good source of vulnerabilities that I have seen in my years doing smart contract audits. So again, some of these are really important things that we should be paying attention to when we are assessing smart contracts in a manual way. But there are more, right? So we can also pay attention to the interactions with external dependencies. And in this case, let's say, other protocols, price oracles, decentralized exchanges, are points of interaction that sometimes can trigger different dynamics, different functionalities or unexpected things in the system that we are trying to break. Another thing to pay attention to is the impact of these dynamics, of novel dynamics, extreme unexpected ones, that perhaps the developers didn't take into account when they were developing the system and we should be paying attention to. So for instance, flash loans have been the big new thing recently in DeFi and Ethereum. With the introduction of flash loans, we have found that many projects ended up having problems in their dynamics, in their incentives, just because flash loans were available to everyone in the ecosystem. Having a clogged network is also something to take into account when we are analyzing smart contracts. What happens if the network is highly congested and transactions cannot go through? What happens if the price of ETH goes down by half and how would this project that I'm analyzing would react to that? Another cool thing going on right now in Ethereum is front-running, back-running and transaction ordering. So there are lots of bots right now in mainnet playing with front-running and back-running and these are things, really interesting things, that we should also take into account if we are trying to find vulnerabilities. How would the project, the contract we are seeing, react to these kind of things? Well, once we have found vulnerabilities, it's time for us to exploit them. Another fun part of doing security research is actually exploit the things that we found. To do exploiting, what we want is first to have a reproducible attack vector and that means to have some way of sharing with the client, sharing with the bug bounty report that we are about to submit, that we have a reproducible attack vector and we are proving actually that there is a vulnerability and that can be exploited under a certain scenario. And we also need to understand the impact that actually exploiting this would have in the system. And for the impact, to be honest, we usually also need to see or to actually to understand how would the system work and how the system reacts to our exploit and what is the actual impact in the business logic of the system. So we need some knowledge, business logic related knowledge, to the system that we are assessing. To do exploiting, my recommendation is to also try your exploits in a local testing environment. You shouldn't do that at mainnet, of course. So you can first spin up a local node. You can do that with ganache or with geth. Geth allows you to have a development mode so your test will run faster. And with ganache, there is a cool feature that you can do is to actually fork mainnet. And so you can point ganache to a, let's say, a full node, fork mainnet into your local environment and actually run your exploits as if they were to be run on mainnet, but you will be like causing no damage to any project out there. To interact with nodes, you can use, if you are hacking on javascript, you can use web3js or ethers, but I think that web3 is also available for python. And if you are wanting to do bigger things that perhaps it would be too difficult to only do with web3js or with ethers, you can use biddler or truffle, which are kind of frameworks or task runners that can help you do more crazy and bigger things with your exploits. These are the ones that I personally use and the ones I recommend. But of course, there might be others out in the space that can help you out too. If you want to see some exploit examples actually using some of the tools that I just mentioned, we have published in the OpenSampling GitHub repository an exploit for the Uniswap vulnerability that was found by another auditing company, by Consensus Intelligence, last year, and that we ended up publishing a proof-of-concept exploit on how that vulnerability can be exploited for some kind of tokens in Uniswap pools. And the exploit is readily available there and is public and for you to see and run it in your local machines. Interestingly, this exploit was actually, I don't know if this particular exploit, but the vulnerability was later exploited in the wild in some real Uniswap pools. I have also published myself some exploits examples in my GitHub repository. And in February this year, for example, we also at OpenSampling published a way to backdoor non-c-safe wallets, one of the most popular wallets in the space, during deployment. And in this post, I'm leaving you the link there, in this post we are actually publishing the proof-of-concept exploit on how to backdoor non-c-safe wallets during deployment. But also we have the possibility to reproduce real exploits in Ethereum. So you can see here a transaction, an execution trace of a transaction that actually stole more than 24k USDC last week on a project in Ethereum. On mainnet this is real and the attack not only was made up of this single transaction but many transactions and caused a lot of fund losses in this project. So you can actually see these transactions because transactions are public in Ethereum. You can see the interactions between the contracts and you can even go ahead and reproduce these real exploits on your local environments. So that is something pretty cool. Well, moving on, after exploiting we can begin talking about post-exploitation, right? So the big question here that I've been asking myself when preparing this talk is if this is even a thing, right? So in the application security world perhaps you might be thinking of pivoting, opening a shell, moving to other systems, jumping around the network, but perhaps in the smart contract world that is not possible or it is not that easy to draw a parallel between the smart contract and other worlds. So again, we shouldn't think of having a shell here but perhaps we can start thinking about, when thinking about post-exploitation, we can try to extend or elevate access to the smart contracts. We can cause further consequences in our components or even in other protocols by going beyond the exploited system that we are assessing, right? So in that sense there might be some parallels between in this post-exploitation phase. So let's go to an example to better see what I mean by post-exploitation here. So let's see a compromised oracle case. In this case, let's imagine a platform that is selling collectibles, is selling these kitties and you pay ETH and it will give you away some kitties depending on how much ETH you have paid. But this platform actually uses the price in ETH of these kitties but uses a price oracle to fetch the price in ETH, right? The price oracle is basically another set of contracts where the price in ETH of these kitties is registered by someone. But in this case, if you can end up finding a vulnerability in the price oracle and you can compromise the price oracle, you can actually compromise the system that is relying on that oracle, right? Because you can set, for instance, the price in ETH of this collectible to zero, you can send a transaction to buy all kitties and you can steal away all kitties in this platform. And that is not also true for a single platform that relies on this oracle, but it's also true for all platforms that are actually relying on this price oracle. This is an actual problem that I think that we have nowadays in Ethereum. The more projects that are relying on a single oracle or just a small number of oracles, the greater the incentives, the economic incentives to attack a price oracle, to compromise it and to basically pound every single project depending on it. So this is basically what I mean with post exploitation. We can compromise an oracle and by doing that we can move on to other projects and execute attacks in them as well. Moving on, we have this last phases which is about reporting, doing fixes, retests and I believe that there are many similarities with other information security realms. So I don't think I should dive deeper into this. Of course we do reporting, of course we review the fixes for our clients, of course we do retests to make sure they haven't reintroduced the vulnerability and have actually fixed the things that we have reported. So we do all of that, that is basically the same. But one thing that we should be highlighting here is that in the Ethereum world most, if not all, but most security reports are public. That is something that you don't see in other worlds. That is something that, for instance, me working as a pen tester for banks in my previous job, I wouldn't have even imagined that I could at some point make public a report, right? But in the Ethereum world that is true, you can do that, of course agreeing that with the client, but I think everyone is encouraged to actually public their security reports because in that way we can all improve the ecosystem, we can all learn about the best security practices, which things might not be the best for some types of projects, and also to have perspectives of other security auditors in the space and learn from each other and make everything in the open and as transparent as possible. So we have public security reports and you can go to, for instance, our blog at OpenZeppelin and many other companies as well are publishing their reports and you can read them and learn tons about smart contract hacking and security and research just by reading those public security reports. So that is something that I wanted to highlight because I think it's super valuable in the space. Well, and to end this talk I wanted to leave you with a little surprise, right? I don't think today I have covered many things on the technical side just because I wanted to, as I told you at the beginning, I wanted to give you the bigger picture of what does it mean to hack smart contracts and how do we structure our engagements. But if you actually want to look at code and run some exploits and try to break smart contracts, I think you might find this super useful and entertaining. It's time for you to start hacking smart contracts so you can start applying all these learnings from these phases that I have been telling you about. You can go to my github repository, it's already public, and you can start hacking a set of smart contracts that is based on a governance system using flash loans and token snapshots, all things and features super popular nowadays in the FIFA space. And here you have an example on how that can be severely broken and you can be the one attacking it and breaking it. So please have fun with it and hope to get some feedback on that if you happen to play it. So thank you very much, you can contact me on telegram, on twitter, on github and all these platforms. You can find me as Tim Chavate and you can learn more about information security related to smart contracts in our forum, in our blog at Open Zeppelin. I'm happy to help you out with anything related to this and please ping me if you find this interesting. So thank you!