Smart Contract Security Tips - Joseph Chow
Devcon·Mon, Oct 9, 2017, 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 IPFS and more. https://archive.devcon.org/archive/watch/2/smart-contract-security-tips Through the use of examples, Joseph Chow walks us through some common things to avoid when developing and deploying smart contracts. Speaker(s): Joseph Chow Skill level: Advanced Track: Security Keywords: hack, attack, prevention, safety, community, prep, rollout, trust, calls 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 2 was held in Shanghai, China on Sep 19 - 21, 2016. 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
one line of code spurred a series of momentous events in blockchain history the line of code in red it was moved up to where the green line is and that was done to neutralize a re-entrant see exploit in the following line reward account dot payout which when performed on an attackers account would would lead to what happened to the DAO the description for this talk was before these momentous events and there's too much security advice to share not enough time that the BTC relay portion of this talk is omitted here's a bonus tip label your untrusted contracts so in the reward account dot payout account line already you can see that there are two accounts here and it's not as clear maybe immediately which account is untrusted so a better way to even rewrite this maybe is to reward account but payout untrusted account and then when people see that it can help help you be more aware of what might happen and as an additional tip message sender can also be untrusted so if it's always untrusted then you you definitely need to put a comment in your code that just to make people more aware the MELD allow simon Delarue be a and I start the committee resource for smart contract security tips we are grateful to seven others so far who have our listeners contributors in github the emphasis is on community because security is not just for a handful of developers to write about and the content needs to be aggregated and easy for people to find instead of being fragmented and scattered we start with some points about general philosophy before extending much further and getting more technical the first point is to prepare for failure the firt this is not about defeat or giving up this is to try to be ready for the unknown unknowns this can be very difficult to do but it is possible in some cases and the next slide is an example of this the second example the second point is to roll out carefully production a production system needs baking time in production the strongest swords are forged by repeatedly processing them in a process of putting them in fire and hammering them it takes time so for contracts they should be put through test nets and then a beta on maenette before a production launch on main net keeping contracts simple is an obvious tip but the process of simplification can lead to surprising results even in the system that already looks simple to stay up to date there's a bibliography at the repo for the community resource that everyone is welcome to contribute to be aware of blockchain properties is what the rest of this talk relates to as promised here's an example of preparing for failure the contract keeps track of its expected fund balance check invariants throws if the actual balance of the contract is smaller than the expected balance and this check invariance is called at the end of some of the key functions in the contract now the emergency call sends the balance to the workshop account only if the invariant is broken the invariant should not get broken but just in case it does the emergency call will send the funds away anyone can invoke the emergency call and the plan is to have a server call it every second if there is a breach that the contracts balance is smaller than what it expects the hope is that most of the funds can be sent to the workshop instead of being drained to an attacker contracts calling each other is powerful and can lead to emergent use cases but care must be taken for external calls that a contract makes the recommendation is to avoid calls to untrusted contracts as much as you can untrusted means any contract that you have not written this is because if you call someone else's contract they or one of their dependencies could accidentally call a malicious contract in the chain of contract calls all it takes is for one contract to make a mistake thus assume that untrusted contracts are malicious avoid calling do something or address call on an untrusted contract the key point is that after any untrusted call assume that the state of your contract has been manipulated here's a diagram to help there's a few things here but let's start at the foo function it decrements X and then it calls a an untrusted contract the fallback function of the untrusted contract executes and it can call foo this is an example of recursively entrance II it's important to realize that reentrant si can use any of the contracts public functions meaning an attacker can re-enter using the function G or bar this is why after the untrusted call the contract can't assume anything at all about the values of X or Y a second tip is to use sand and avoid call dot value if you've seen examples of vulnerable code especially regarding re-entrance e they all involve call dot value because using sand instead of call dot value does not give the attacker enough gas to do damage with reentrant see the attacker only gets 2300 gas with the great power comes great responsibility and that applies to call dot value and so the tip is to use scent and avoid call dot value perhaps the most mature best practice is to handle errors in raw calls Rock holes such as address thoughts and and address dot call return false if they fail this is unlike invoking a do something method which propagates an exception if it encounters one so the good example is to check check the result and the bad example is an unchecked send a tip that goes together with using send is to keep fallback functions simple the last fallback function is advised against because one it uses more than 23-hundred ass second it asks callers to break the tip of using sand and asks them to use the riskier call dot value a call depth attack can be used by an attacker to make all of your contracts calls to fail the theme the etherium virtual machine has what the yellow paper calls a contract a message called slash contract creation stack and it has a maximum depth of 1,024 an attacker can make recursive calls to bring the depth to 1023 call your function which brings the depth to 1024 and now all of your contracts calls will fail in this example simple example an attacker can force a recipient to lose their refund so the attacker recurse is to bring the depth to 1023 then calls withdraw refund using the address of a victim recipient and the depth is now at 1024 the refunds for the recipient will be set to zero this pointer doesn't work well to show that and when the victim calls withdraw a refund that the send will fail and then when the victim calls tries to withdraw their own refund the refund will already be set to zero so they can't get it back as an improvement the return value of send could be checked however a preferred solution is to write this contract so that message sender will pull their refund as opposed to the insecure contracts approach of pushing the refund to recipient this has had to be a quick presentation and there's plenty more information and examples such as pull over push denial of service against contracts and re-entrance e that can be found in the repo and wiki page to recap some of the main points for smart contract security are prepare for failure rollout carefully keep contracts simple and calling untrusted contracts is always dangerous the danger may seem small but if an attacker finds and exploits a bug in a compiler that is targeting the EVM they are likely to do much more damage if their untrusted code is executed then one where they only have a compiler bug to work with here are the links to a security resource of the community by the committee for the community I also have slides regarding denial of service and pull over push or can take two questions in the remaining three minutes any questions ok I can quickly go through a couple more so so quickly in this a denial of service against the contract there are many ways that pitfalls that you can encounter them one is an unexpected throw which is what this code example here is about but hitting the block s limit is another example iterating through an unbounded to raise another example misunderstanding gas refunds will also cause the same issue so in this example contract the the line with the throw means that a current leader that refuses payment will permanently be the leader and the throw cannot be removed in this case because otherwise some other person can do a call depth attack against bid and what that means is that they will get to be the current leader without having had to pay the previous leader so in this example you can just remove throw and for the final tip that we only have time for here is to change this into a pull over push system and so the left side is the auction contract that was shown this couple of slides ago this time instead of doing a sent to the recipient it just the contract just keeps track of the refunds that that are owed to whoever the highest bidder is and then on the right side is the pull method where everything works based off message sender and by doing this an attacker can basically only attack themselves so that's it you
Automatic transcript — names and jargon may be misspelled.