2. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 2
OutlineOutline
· MotivationMotivation
· Introduction to SolidityIntroduction to Solidity
· Gas and Transaction LimitsGas and Transaction Limits
· TheDAO AttackTheDAO Attack
· WeaknessesWeaknesses
· Attacks to the Parity WalletAttacks to the Parity Wallet
· Testing and Bug ReportingTesting and Bug Reporting
3. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 3
Bugs Occur in All SoftwareBugs Occur in All Software
[SCSec-6]
A 2003 study commissioned by the NIST found that
software bugs cost the US economy $59.5 billion annually.
In smart contracts, they’re easily monetized.
4. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 4
The Need for Secure CodeThe Need for Secure Code
· Ethereum and other complex blockchain systems are highlyEthereum and other complex blockchain systems are highly
experimentalexperimental
- Require a new philosophy behind development
- Unstable with a lot of potential to go wrong
●
Like programming hardware or financial services rather than
mobile/web
· People can drain millions from contract accountsPeople can drain millions from contract accounts
- Several exploits from on even the best of the best teams in the
space.
· ““Disneyland for Hackers”!Disneyland for Hackers”!
[DevDecal-3]
5. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 5
What’s the Difference?What’s the Difference?
· Security refers to preventing exploit on the protocol orSecurity refers to preventing exploit on the protocol or
application layersapplication layers
· Everything on a Blockchain is public! (code + data)Everything on a Blockchain is public! (code + data)
- Blockchain can be thought of as a server, where server-side code is
completely exposed to the clients on the protocol (network nodes)
and clients on DApps (users)
- Imagine taking your private, permissioned database and having to
make it public, and distributed, yet secure!
· Big tradeoff of Ethereum vs. Bitcoin -> Turing CompletenessBig tradeoff of Ethereum vs. Bitcoin -> Turing Completeness
of the EVMof the EVM
- Attack surface is a problem on Ethereum
[DevDecal-3]
6. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 6
Patching ProblemPatching Problem
· Smart contracts are immutableSmart contracts are immutable
- Once deployed, the discovered bugs cannot be patched.
- Must write robust code prior to mainnet deployment
- Compare to current state of software engineering
●
Continuous Deployment, Integration Tests, etc.
· People can have their own instances of a contract deployed (i.e.People can have their own instances of a contract deployed (i.e.
multi-sig wallet)multi-sig wallet)
- There’s no built in way to govern that each person upgrade or
selfdestruct into a new instance once an exploit happens.
· The future might be whole organizations governed by smartThe future might be whole organizations governed by smart
contract codecontract code
- So there’s clearly a need for proper security
[DevDecal-3]
7. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 7
What to Do?What to Do?
· Better testing methods for smart contractsBetter testing methods for smart contracts
- TDD is often argued with as it’s never a guarantee of security,
but then again, nothing is truly secure
· Formally verifiable smart contractsFormally verifiable smart contracts
- Mathematically prove why the smart contract works
· Smart contract code auditsSmart contract code audits
- Get multiple sources to audit code before going live
· Easier smart contract languages with safety built inEasier smart contract languages with safety built in
· Have very careful programmers write code on this platformHave very careful programmers write code on this platform
[SCSec-3]
8. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 8
Introduction to SolidityIntroduction to Solidity
9. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 9
Overall PictureOverall Picture
· Smart contracts: user-defined programs running on top ofSmart contracts: user-defined programs running on top of
a blockchaina blockchain
Contracts
Code
Storage
Data
Users
Money
Decentralized Consensus
“Blockchain”
[SCSec-3]
10. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 10
Contract Programming ModelContract Programming Model
· Contract classContract class
- Create an object of this
class by making a
transaction
· Define functions you canDefine functions you can
callcall
[SCSec-3]
11. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 11
Ethereum LanguagesEthereum Languages
Ethereum VM Bytecode
Stack Language
Lower-Level Language
Serpent Solidity
Functional, macros,
looks like scheme
Types,
looks like Javascript
Looks like python
Looks like Forth.
Defined in Yellowpaper
Vyper
(Upcoming)
[SCSec-3]
Discontinued
Security-focused
12. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 12
Solidity Should Look FamiliarSolidity Should Look Familiar
· Syntax looks like JavaScriptSyntax looks like JavaScript
- Contracts look like classes/objects
· Static typingStatic typing
- bool, uint8, uint16, ... uint256, int8, ...
int256
- Most types can be cast e.g. bool(x)
· Complex typesComplex types
- Address, string, byte[]
- mapping(keyType => valueType)
[SCSec-3]
13. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 13
Some NotesSome Notes
· Member variables can be marked publicMember variables can be marked public
- Getter methods automatically provided
· Functions must be marked payable to accept fundsFunctions must be marked payable to accept funds
· Member variables go to storage by defaultMember variables go to storage by default
- Method variables go to memory
· Fallback function()Fallback function()
- Called if no function specified (e.g. send)
- Called if non-existent function called
· See:See:
https://solidity.readthedocs.io/en/develop/solidity-in-depth.htmlhttps://solidity.readthedocs.io/en/develop/solidity-in-depth.html
[SCSec-3]
14. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 14
Gas and Transaction LimitsGas and Transaction Limits
15. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 15
Gas in EthereumGas in Ethereum
· All miners and full nodes must evaluate all transactionsAll miners and full nodes must evaluate all transactions
- limit computation cost
· All miners must store all stateAll miners must store all state
- limit storage use
· Short-cut the halting problemShort-cut the halting problem
- There is an upper GAS_LIMIT on blocks, so all programs will halt
- Gas limit = 8,000,000 gas (as of May, 2019)
[SCSec-3]
16. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 16
Gas Cost of EVM OperationsGas Cost of EVM Operations
opcodes gas cost
Basic operations ADD, MUL, PUSH, JUMP 2-10
Storage read (uint256) SLOAD 200
Storage write (uint256) SSTORE 5000
Storage write (from zero) SSTORE 20000
Storage zeroize SSTORE 5000 +
-15000 (refund)
Contract call CALL, CODECALL, etc. 700
Transaction overhead n/a 21000
Contract creation n/a 32000
Contract destruction SELFDESTRUCT 5000 +
-24000 (refund)
[SCSec-3]
See https://github.com/djrtwo/evm-opcode-gas-costs and EIP 150
18. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 18
START_GAS and GAS_PRICESTART_GAS and GAS_PRICE
1.1. If START_GAS GAS_PRICE > caller.balance → halt⨉ GAS_PRICE > caller.balance → haltIf START_GAS GAS_PRICE > caller.balance → halt⨉ GAS_PRICE > caller.balance → halt
2.2. Deduct START_GAS GAS_PRICE from caller.balance⨉ GAS_PRICE > caller.balance → haltDeduct START_GAS GAS_PRICE from caller.balance⨉ GAS_PRICE > caller.balance → halt
3.3. Set GAS = START_GASSet GAS = START_GAS
4.4. Run code, deducting from GASRun code, deducting from GAS
5.5. For negative values, add to GAS_REFUNDFor negative values, add to GAS_REFUND
●
GAS only decreases
6.6. After termination, add GAS_REFUND to caller.balanceAfter termination, add GAS_REFUND to caller.balance
· Out-of-gas exceptionOut-of-gas exception
- State reverts to previous value
- Except that START_GAS * GAS_PRICE is still deducted
[SCSec-3]
19. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 19
Economics of GasEconomics of Gas
· Miners choose transactions based on GAS_PRICEMiners choose transactions based on GAS_PRICE
· In theory, they should not care which opcodes are usedIn theory, they should not care which opcodes are used
- In practice, some “overpriced” opcodes may be preferred
· Maximum GAS_LIMIT per blockMaximum GAS_LIMIT per block
- Miners can slowly raise it, each block votes
[SCSec-3]
22. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 22
slock.it: a Blockchain + IoT companslock.it: a Blockchain + IoT compan yy
· Example use case:Example use case:
1)AirBnB user submits
payment to the Ethereum
blockchain
2)Slock Home Server
(Ethereum client)
receives the transaction
3)Power switch connected
to Home Server receives
“unlock” command,
unlocks the door
[SCSec-6]
23. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 23
Slock.it Built the DAO to Raise FundsSlock.it Built the DAO to Raise Funds
· ““DAO”: Decentralized Autonomous OrganizationDAO”: Decentralized Autonomous Organization
- Coined by Vitalik in 2013
· TheDAO built by slock.it to raise funds for their companyTheDAO built by slock.it to raise funds for their company
· Main idea: a decentralized hedge fund (Main idea: a decentralized hedge fund (یسکیریششپیییوصییندوقیسکیریششپیییوصییندوق))
- Investors contribute funds, receive ownership “tokens”
- Investors jointly decide how to spend funds, by voting in proportion
to tokens
· Many additional mechanisms:Many additional mechanisms:
- “Splitting” to prevent hostile takeover
- Reward disbursing
[SCSec-6]
31. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 31
· June 12: slock.it developers announce that a bug is found, but no funds at risk
· June 17 (Morning): attacker drains of the DAO’s Ether ($50M) over 24 hrs⅓ of the DAO’s Ether ($50M) over 24 hrs
- Attacker’s funds were trapped in a subcontract for 40 days (July 27)
· June 17 (Evening): Eth Foundation proposes a “Soft Fork” to freeze the funds
· June 28: researchers publish a flaw in the Soft Fork Proposal
· July 15 (Morning): Eth Foundation proposes a “Hard Fork” to recover funds
· July 15 (Evening): “Ethereum Classic” manifesto published on github
· July 19: “Hard Fork” moves funds from attacker’s contract to recovery contract
- Ethereum Classic blockchain survives and is traded on exchanges
· Both Ethereum and Ethereum Classic are both around, reached new peaks
Timeline and Aftermath of The DAOTimeline and Aftermath of The DAO
AttackAttack
[SCSec-6]
34. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 34
Fallback FunctionFallback Function
· A contract can have exactly one unnamed functionA contract can have exactly one unnamed function
- This function cannot have arguments and cannot return anything
- Even though the fallback function cannot have arguments, one
can still use msg.data to retrieve any payload supplied with the
call.
· The function is executed on a call to the contractThe function is executed on a call to the contract
- if none of the other functions match the given function identifier
- or if no data was supplied at all → e.g. send()
· To receive ether for this function, we must mark it asTo receive ether for this function, we must mark it as
payable.payable.
[DevDecal-3]
35. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 35
Function Invocation in SolidityFunction Invocation in Solidity
· Direct callDirect call
- contract Alice { function ping(uint) returns (uint) }
- contract Bob { function pong(Alice c){ c.ping(42); } }
· Transfer: send Ether to a payable addressTransfer: send Ether to a payable address
- After the ether has been transferred, executes the recipient’s fallback.
- Fails if the balance of the current contract is not large enough or if the Ether transfer is rejected by
the receiving account.
- The transfer function reverts on failure.
· Send: old way of sending ether from the running contract to some recipientSend: old way of sending ether from the running contract to some recipient (low level)(low level)
- After the ether has been transferred, executes the recipient’s fallback.
- If the execution fails, the current contract will not stop with an exception, but send will return false.
· Call: invokes a function (of another contract, or of itself), and transfers Ether to the calleeCall: invokes a function (of another contract, or of itself), and transfers Ether to the callee
(low level)(low level)
- c.call.value(amount)(bytes4(keccak256("ping(uint256)")),n)
- The called function is identified by the first 4 bytes of its hashed signature, amount
determines how many wei have to be transferred to c, and n is the actual parameter of ping.
[AttackSurvey]
36. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 36
DelegatecallDelegatecall
· delegatecalldelegatecall (low level)(low level) is identical to a message call (internalis identical to a message call (internal
transaction) apart from the fact that the code at targettransaction) apart from the fact that the code at target
address is executed in the context of the calling contract andaddress is executed in the context of the calling contract and
msg.sender and msg.value do not change their valuesmsg.sender and msg.value do not change their values
- A contract can dynamically load code from a different address at
runtime with delegatecall
- Storage, current address and balance still refer to the calling
contract, only the code is taken from the address we called
· Very useful for implementing libraries and modularizing codeVery useful for implementing libraries and modularizing code
- But opens doors to vulnerabilities as your contract is allowing
anyone to do whatever they want with their state
[DevDecal-3]
37. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 37
Exception Disorder (Nested Calls)Exception Disorder (Nested Calls)
· Why exceptions are raised?Why exceptions are raised?
- Execution runs out of gas
- Call stack reaches its limit
- Command throw is executed
· Consequence: Side effects (+Ether transfers) are reverted.Consequence: Side effects (+Ether transfers) are reverted.
- Nested direct calls / transfer:
●
Every side effect is reverted.
●
All the gas allocated by the originating transaction is consumed.
- Nested calls with at least one call/delegatecall/send:
●
Side effects of direct calls are reverted until the call is reached.
●
From that point the execution is resumed, with the call returning
false.
●
All the gas allocated by the call is consumed.
[AttackSurvey]
Advice: Use revert where possible!
38. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 38
Exception BehaviorException Behavior
Exception behavior Gas sent
recipient.send(100) returns 0 minimum
recipient.call.value(100).gas(25)() returns 0 25
recipient.foo.value(100)(“a1”) exception all of it
recipient.foo(“a1”) exception all of it
recipient.transfer(100) exception minimum
100 Amount in Ether
25 Amount in gas
“a1” Data argument
[SCSec-6]
39. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 39
Gassless SendGassless Send
· Sending ether viaSending ether via sendsend succeeds in two cases:succeeds in two cases:
- Recipient is a contract with an inexpensive (e.g. no state
update) fallback.
- Recipient is a user.
- Otherwise → out of gas!
[AttackSurvey]
40. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 40
Type CastsType Casts
· Type mismatch for c when pong is called?Type mismatch for c when pong is called?
- c is not a contract address → an exception is thrown (prior to
v0.4.0: no code is executed, and no exception is thrown!)
- c is the address of any contract having a function with the same
signature as Alice’s ping → then that function is executed.
- c is a contract with no function matching the signature of Alice’s
ping → c’s fallback is executed.
· Except in the first case (maybe?), no exception is thrown,Except in the first case (maybe?), no exception is thrown,
and the caller is unaware of the type mismatch!and the caller is unaware of the type mismatch!
[AttackSurvey]
41. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 41
ReentrancyReentrancy
· What happens?What happens?
- Ping is not reentrant → Out-of-gas, out of Ether, stack full → exception is thrown
- In all cases, only the effects of the last call are reverted, leaving all the previous transfers
of Ether valid!
· Solutions:Solutions:
- Solution 1: Reduce the sender’s balance before making the transfer of value
- Solution 2 (Best): use require(msg.sender.transfer(_value))
●
Revert vs. Require vs. Assert
[AttackSurvey]
42. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 42
Stack depth = 1024
Contract B:
function b() {
Alice.send(100);
// do some stuff
return “Hello “;
}
Stack Size Limit (Callstack Hazard!)Stack Size Limit (Callstack Hazard!)
Contract A:
function recurse(int i) {
if (i == 1023)
return B.b() + “World”;
else recurse(i+1);
return OK;
}
A.recurse(0) Stack depth = 0
A.recurse(1) Stack depth = 1
….
A.recurse(1023) Stack depth = 1023
Returns “Hello World!”
· Maximum call stack depth is 1024Maximum call stack depth is 1024
- External function calls fail if they exceed the maximum call stack of 1024, and
throw an exception.
- Low level functions send(), call(), callcode() and delegatecall() does not throw
an exception but rather return false!
· Suppose we call A.recurse(0). Does Alice get 100?Suppose we call A.recurse(0). Does Alice get 100?
43. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 43
EIP 150 (Hard Fork)EIP 150 (Hard Fork)
· Stack limit restriction is now replaced by a “softer” gas-Stack limit restriction is now replaced by a “softer” gas-
based restrictionbased restriction
- The hard fork limited the caller to allocate at most 63/64 of its
gas.
- The max block gas practically limits the call stack depth to
below 1024.
45. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 45
Generating RandomnessGenerating Randomness
· The execution of EVM bytecode is deterministicThe execution of EVM bytecode is deterministic
- All miners executing a transaction will have the same results.
- Many contracts generate pseudo-random numbers, where the initialization seed is chosen
uniquely for all miners.
· Solution 1: Hash / timestamp of some block that will appear in the blockchain atSolution 1: Hash / timestamp of some block that will appear in the blockchain at
a given time in the future.a given time in the future.
- Analysis shows that an attacker, controlling a minority of the mining power of the network,
could invest 50 bitcoins or less to significantly bias the probability distribution of the
outcome.
· Solution 2: timed commitment protocolsSolution 2: timed commitment protocols
- Each participant chooses a secret, and then communicates to the others a digest of it,
paying a deposit as a guarantee. Later on, participants must either reveal their secrets, or
lose their deposits.
- The pseudo-random number is then computed by combining the secrets of all participants.
[AttackSurvey]
46. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 46
Other WeaknessesOther Weaknesses
· Keeping secrets: Declaring a field as private does not guarantee itsKeeping secrets: Declaring a field as private does not guarantee its
secrecy.secrecy.
- Since the blockchain is public, everyone can inspect the contents of the
transactions, and infer the value of the fields.
- Suitable cryptographic techniques or timed commitments should be used.
· Immutable bugs: Once a contract is published on the blockchain, it canImmutable bugs: Once a contract is published on the blockchain, it can
no longer be altered!no longer be altered!
- if a contract contains a bug, there is no direct way to patch it!
· Ether lost in transfer: If some ether is sent to anEther lost in transfer: If some ether is sent to an orphanorphan address, it isaddress, it is
lost foreverlost forever
- Orphan: not associated to any user or contract
- Programmers have to manually ensure the correctness of the recipient addresses.
[AttackSurvey]
47. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 47
Other Weaknesses (2)Other Weaknesses (2)
· Unpredictable stateUnpredictable state
- Users cannot be sure that their transactions will be run in the same state the
contract was at the time of sending them.
- Because of the delay until tx submission, tx selection by miners is nondeterministic,
(temporary) forks
· Time constraintsTime constraints
- All transactions within a block share the same timestamp.
- However, the miner who creates the new block can choose the timestamp with a
certain degree of arbitrariness.
· More weaknesses are discussed in [DevDecal-3]More weaknesses are discussed in [DevDecal-3]
- Integer arithmetic pitfalls
- Force ether to a contract (selfdestruct)
- DoS with unexpected revert
- Short address attack
[AttackSurvey]
48. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 48
Attack on the Parity WalletAttack on the Parity Wallet
49. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 49
ParityParity
· Parity is an Ethereum client written in Rust programmingParity is an Ethereum client written in Rust programming
languagelanguage
- Rust is a multi-paradigm system programming language focused
on safety, especially safe concurrency. [Wikipedia]
- About 40% (3500+ nodes) of the Ethereum network nodes run
Parity and Parity Ethereum code. [Ethernodes.org in May 2019]
· Core development team is separate from the EthereumCore development team is separate from the Ethereum
FoundationFoundation
- A client, an EVM, a wallet, etc. in Rust
50. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 50
What Was the Parity Wallet?What Was the Parity Wallet?
· ““Parity Wallet” was aParity Wallet” was a
Solidity smart contract thatSolidity smart contract that
Parity created as part of itsParity created as part of its
wallet management feature.wallet management feature.
- It was a popular feature of
Parity
- Now, creating wallets is not
possible (only watching
existing wallets)
[SCSec-6]
51. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 51
The Parity Wallet ExploitsThe Parity Wallet Exploits
· 11stst
exploit (July 2017) 153,037 Ether (worth $30+ million) was stolenexploit (July 2017) 153,037 Ether (worth $30+ million) was stolen
from three wallet contracts.from three wallet contracts.
- A remaining $78 million worth of tokens (half the value being BAT and
ICONOMI) plus 377,105+ ETH ($72+ million) were recovered by a whitehat
rescue, and returned to their rightful owners.
· 22ndnd
exploit (November 2017) leading to $150M frozen funds.exploit (November 2017) leading to $150M frozen funds.
- “It was possible to turn the Parity Wallet library contract into a regular
multi-sig wallet and become an owner of it by calling the initWallet function.”
- “Subsequently a user deleted the library-turned-into-wallet, wiping out the
library code which in turn rendered all multi-sig contracts unusable and funds
frozen since their logic (any state-modifying function) was inside the library.”
- See: https://www.parity.io/security-alert-2/
52. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 52
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
Parity Wallet: Prototype Inheritance PatternParity Wallet: Prototype Inheritance Pattern
Wallet Library contract:
contract WalletLibrary {
address owner;
// called by constructor
function initWallet(address _owner) {
owner = _owner;
// ... more setup ...
}
function changeOwner(address _new_owner)
function () payable {
// ... receive money, log events, ...
}
function withdraw(uint amount);
}
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount)
returns (bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
// fallback function gets called if no
// other function matches
function () payable {
_walletLibrary.delegatecall(msg.data);
}
}
Multiple Wallet contracts, all refer to Wallet Library
Why? Reduces fees from duplicate data!
0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3
* Toy version of code
[SCSec-6]
53. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 53
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
1. Constructor is called, invokes initWallet1. Constructor is called, invokes initWallet
Wallet Library contract:
contract WalletLibrary {
address owner;
// called by constructor
function initWallet(address _owner) {
owner = _owner;
// ... more setup ...
}
function changeOwner(address _new_owner)
function () payable {
// ... receive money, log events, ...
}
function withdraw(uint amount);
}
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount)
returns (bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
// fallback function gets called if no
// other function matches
function () payable {
_walletLibrary.delegatecall(msg.data);
}
}
0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3
[SCSec-6]
54. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 54
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
2. The withdraw function invokes withdraw2. The withdraw function invokes withdraw
Wallet Library contract:
contract WalletLibrary {
address owner;
// called by constructor
function initWallet(address _owner) {
owner = _owner;
// ... more setup ...
}
function changeOwner(address _new_owner)
function () payable {
// ... receive money, log events, ...
}
function withdraw(uint amount);
}
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount)
returns (bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
// fallback function gets called if no
// other function matches
function () payable {
_walletLibrary.delegatecall(msg.data);
}
}
0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3
[SCSec-6]
55. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 55
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
Wallet contract:
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount) returns
(bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
}
3. The fallback function can invoke any method3. The fallback function can invoke any method
Wallet Library contract:
contract WalletLibrary {
address owner;
// called by constructor
function initWallet(address _owner) {
owner = _owner;
// ... more setup ...
}
function changeOwner(address _new_owner)
function () payable {
// ... receive money, log events, ...
}
function withdraw(uint amount);
}
contract Wallet {
address _walletLibrary;
address owner;
function Wallet(address _owner) {
_walletLibrary = ${hardcoded address};
_walletLibrary.delegatecall(
"initWallet(address)",
_owner);
}
function withdraw(uint amount)
returns (bool success) {
return _walletLibrary.delegatecall(
"withdraw(uint)",
amount);
}
// fallback function gets called if no
// other function matches
function () payable {
_walletLibrary.delegatecall(msg.data);
}
}
0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3
Attacker calls:
victim.call(“initWallet(address)”, attacker)
[SCSec-6]
56. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 56
Fixing the July 2017 Parity wallet bugFixing the July 2017 Parity wallet bug
New Library contract:
contract WalletLibrary {
address owner;
// called by constructor
function initWallet(address _owner) {
require(initialized == false);
initialized = true;
owner = _owner;
// ... more setup ...
}
function changeOwner(address _new_owner)
function () payable {
// ... receive money, log events, ...
}
function withdraw(uint amount);
}
0x863df6bfa4469f3ead0be8f9f2aae51c91a907b4
Old Wallet Library contract:
contract WalletLibrary {
address owner;
// called by constructor
function initWallet(address _owner) {
owner = _owner;
// ... more setup ...
}
function changeOwner(address _new_owner)
function () payable {
// ... receive money, log events, ...
}
function withdraw(uint amount);
}
0xa657491c1e7f16adb39b9b60e87bbb8d93988bc3
[SCSec-6]
57. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 57
The White Hat Recovery TeamThe White Hat Recovery Team
[SCSec-6]
58. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 58
The Parity Wallet July ‘17 stolen coins are still idleThe Parity Wallet July ‘17 stolen coins are still idle
0xb3764761e297d6f121e79c32a65829cd1ddb4d32
59. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 59
Final Words and LessensFinal Words and Lessens
· Root cases:Root cases:
- Complex code in multiple contracts!
- The initialize function to set the owner of the contract, was missing the
check for previous initialization.
- Two internal functions in the library code was public!
- Code fix:
https://github.com/paritytech/parity-ethereum/commit/e06a1e8dd9cfd8bf5
d87d24b11aee0e8f6ff9aeb#diff-8ea4aa7c2ba715c683bc764337f51585
· Analysis and postmortem:Analysis and postmortem:
- In depth analysis of the event from IC3:
http://hackingdistributed.com/2017/07/22/deep-dive-parity-bug/
- Parity’s statement:
https://www.parity.io/the-multi-sig-hack-a-postmortem/
60. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 60
Testing and Bug ReportingTesting and Bug Reporting
61. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 61
How to Be Careful?How to Be Careful?
· Follow best practices in codingFollow best practices in coding
- Don’t write fancy code
- Use audited and tested code
- Keep contracts simple - more complexity = more attack vectors
- Keep updating with software and community
· Through testingThrough testing
- Write as many unit tests as possible
- Prepare for failure at any moment, in any contract or method
- Rollout carefully - bug bounties before ICO
· Beware of blockchain properties and discussed weaknessesBeware of blockchain properties and discussed weaknesses
- E.g. public vs. private, .send() vs. .call() vs .transfer()
· Avoid external calls (toAvoid external calls (to untrusted contract or account) when possible.untrusted contract or account) when possible.
[DevDecal-3]
62. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 62
Ethereum Bounty ProgramEthereum Bounty Program
63. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 63
Ethereum Bounty Program RewardsEthereum Bounty Program Rewards
(As of May 28, 2019)
64. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 64
Assert and RequireAssert and Require
· Use assert and require properlyUse assert and require properly
· require(condition) is meant to be used for input validationrequire(condition) is meant to be used for input validation
- Should be done on any user input, and throws if condition is
false.
· assert(condition) also throws if condition is falseassert(condition) also throws if condition is false
- Should be used only for internal errors or to check if your
contract has reached an invalid state.
· By following this paradigm, it would become possible to useBy following this paradigm, it would become possible to use
a formal analysis tool to verify that invalid situationsa formal analysis tool to verify that invalid situations
cannot be reached assuming valid inputs.cannot be reached assuming valid inputs.
[DevDecal-3]
65. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 65
Pragma StatementsPragma Statements
· Lock pragmas to specific compiler versionLock pragmas to specific compiler version
[DevDecal-3]
66. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 66
2-Party / N-Party Contracts2-Party / N-Party Contracts
· Beware of the possibility that some participants may “drop offline” andBeware of the possibility that some participants may “drop offline” and
never returnnever return
- Do not make refund or claim processes dependent on a specific party
performing a particular action with no other way of getting the funds.
· Example: Rock – Paper – ScissorsExample: Rock – Paper – Scissors
- Common mistake: not make a payout until both players submit their moves.
- Pitfall: a malicious player can make trouble by simply never submitting their
move!
· SolutionsSolutions
- Provide a way of circumventing non-participating participant. (e.g. time limit)
- Add an additional economic incentive for participants to submit information in
all of the situations in which they are supposed to do so. (e.g. deposits)
[DevDecal-3]
67. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 67
Responsible DisclosureResponsible Disclosure
· What do you do when you find a bug?What do you do when you find a bug?
- Responsible disclosure: a vulnerability or an issue is disclosed only after a period of
time that allows for the vulnerability or issue to be patched or mended.
· Steps:Steps:
- Give advance notice to those in position (or with a duty) to help
- Give enough time fox a fix: e.g. 90 days (Google Project Zero)
- Disclose the bug in coordination with the company after it is fixed.
· How should companies react to researchers?How should companies react to researchers?
- Proactive: build bug bounties, define disclosure processes
- Repay in kind!? (e.g., by banning or suing)
· See:See:
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Vhttps://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/V
ulnerability_Disclosure_Cheat_Sheet.mdulnerability_Disclosure_Cheat_Sheet.md
68. Start from here
Credit: https://www.slideshare.net/clubhack/anatomy-ofaresponsibledisclosurezerodayvulnerabilityinoraclebipublishervishal-karlo
69. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 69
Tools for Auditing and AnalysisTools for Auditing and Analysis
· solc (Solidity compiler)solc (Solidity compiler)
- Semantic checking finds potential mistakes at compilation time.
· Securify.ch, Oyente, Remix IDESecurify.ch, Oyente, Remix IDE
- Static analysis tools for smart contracts
· HydraHydra
- A “framework for cryptoeconomic contract security, decentralized
security bounties”
· PorosityPorosity
- A decompiler for Ethereum Smart-Contracts
· ManticoreManticore
- A dynamic binary analysis tool with EVM support
[DevDecal-3]
70. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 70
Tools for Auditing and Analysis (2)Tools for Auditing and Analysis (2)
· EthersplayEthersplay
- A Binary Ninja plugin for EVM
· OpenZeppellinOpenZeppellin
- A library for writing secure smart contracts on Ethereum
· SolographSolograph
- Visualization tool for Solidity control flow and call graph
· Truffle SuiteTruffle Suite
- A tool and framework for developing smart contracts. Includes
various tools for automated contract testing.
[DevDecal-3]
71. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 71
Questions?Questions?
Sadegh Dorri N.Sadegh Dorri N.
dorri@modares.ac.ir
http://www.modares.ac.ir/~dorri
72. Spring 2019 (1398) E-Commerce Security - Smart Contract Security 72
ReferencesReferences
· [DevDecal-3] Akash Khosla, “Smart Contract Security,” Blockchain Developers
(Decal) Course Lecture 3, Blockchain at Berkeley, Fall 2018. Link:
https://blockchain.berkeley.edu/courses/spring-2018-developers-decal/
· [SCSec-3] Andrew Miller, “Solidity programming,” Smart Contracts and
Blockchain Security Course Lecture 3, University of Illinois Urbana-Champaign,
Spring 2018. Link: http://soc1024.ece.illinois.edu/teaching/ece398sc/spring2018/
· [SCSec-6] Andrew Miller, “Smart Contract Disasters, Intro to Intro to Security,”
Smart Contracts and Blockchain Security Course Lecture 6, University of Illinois
Urbana-Champaign, Spring 2018. Link:
http://soc1024.ece.illinois.edu/teaching/ece398sc/spring2018/
· [AttackSurvey] Atzei N., Bartoletti M., Cimoli T., “A Survey of Attacks on
Ethereum Smart Contracts (SoK),” In Principles of Security and Trust (POST),
LNCS, vol 10204, Springer, Berlin, Heidelberg, 2017.