Slide 1

Slide 1 text

Blockchain Security oalieno

Slide 2

Slide 2 text

Introduction to Blockchain

Slide 3

Slide 3 text

Blockchain A → B $3 C → A $2 ⋮ • 去中⼼化的記帳本 • 去中⼼化:⼤家都有⼀份⼀模⼀樣的記帳本備份 • 記帳本:記錄誰給誰多少錢 A → B $3 C → A $2 ⋮ Alice Bob

Slide 4

Slide 4 text

Blockchain • Alice 要給 Bob 1 塊錢 • 記錄⼀筆交易,並廣播給其他所有⼈ A → B $3 C → A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A → B $1

Slide 5

Slide 5 text

Blockchain • Bob 可以偽造⼀筆交易,廣播給所有⼈ A → B $3 C → A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A → B $100

Slide 6

Slide 6 text

Blockchain • 因此每⼀筆帳必須簽章 • 將錢從 A 轉出去的帳,要有 A 簽章才有效 A → B $3 C → A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A 簽章 C 簽章 C 簽章 A 簽章

Slide 7

Slide 7 text

Blockchain • 但是就算有簽章,Bob 可以輕易的複製同⼀份交易再廣播出去 A → B $3 C → A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A 簽章 C 簽章 C 簽章 A 簽章 A → B $3 A 簽章

Slide 8

Slide 8 text

Blockchain • 所以簽章的內容必須包含⼀個 id 或 timestamp 之類的 TX 0 : A → B $3 TX 5 : C → A $2 ⋮ TX 0 : A → B $3 TX 5 : C → A $2 ⋮ Alice Bob A 簽章 C 簽章 C 簽章 A 簽章

Slide 9

Slide 9 text

如何達成共識 • ⼤家都在廣播交易 • 怎麼決定誰先誰後,並保證⼤家的記帳本都長得⼀樣? TX 0 : A → B $3 TX 5 : C → A $2 ⋮ TX 0 : A → B $3 TX 5 : C → A $2 ⋮ Alice Bob A 簽章 C 簽章 C 簽章 A 簽章 TX 6 : A → B $1 TX 6 : B → C $1 A 簽章 B 簽章

Slide 10

Slide 10 text

誰有記帳權 • ⼤家決定出⼀個⼈來記帳 • 每次會記好幾個交易的帳,稱為⼀個區塊 ( Block ),不會只記⼀個交易 • 先算出哪個 Nonce 會讓整個 Block 的 Hash 開頭是 0x00 的⼈記帳 TX 0 : A → B $3 TX 5 : C → A $2 ⋮ A 簽章 C 簽章 Nonce 0x1234 Hash 0x00abcd Alice

Slide 11

Slide 11 text

誰有記帳權 • 要 Hash 的東⻄包括前⼀個 Block 的 Hash,形成⼀連串的 Block Chain • 並且記帳的⼈能獲得獎勵,所以⼤家都會搶著記帳 TX 0 : A → B $3 Reward A $10 ⋮ A 簽章 Nonce 0x1234 Hash 0x00abcd Hash of Previous Block Alice

Slide 12

Slide 12 text

Blockchain TX 0 : A → B A 簽章 TX 5 : C → A C 簽章 Hash of Block 0 ⋮ TX 0 : B → D B 簽章 TX 7 : A → C A 簽章 Hash of Block 1 ⋮ Hash Hash Block 1 Block 2 Nonce Nonce

Slide 13

Slide 13 text

分岔 ( fork ) • 剛好兩個⼈都算出正確的 Nonce 挖出區塊怎麼辦 • 看誰的鍊比較長誰就是主鏈 Block 2 Block 2 Block 3 Block 4 Block 1

Slide 14

Slide 14 text

51% 攻擊 • 當某個礦⼯有全網 51% 以上的算⼒,那他挖的那條鏈就會是最長鍊 • 他可以故意排除或竄改交易順序 • 但因為有簽章,所以他還是不能亂轉他沒有的錢,也不能憑空⽣錢 • 2018 年 5 ⽉,Bitcoin Gold ( BTG ) 就被 51% 攻擊了,損失 1800 萬美⾦

Slide 15

Slide 15 text

51% 攻擊 • 先轉帳 $1000 到⽬標交易所 • 等 10 個區塊 confirmation 後,交易所認可該筆交易 • 駭客便可以將錢從交易所領出來換成法幣 Block 2 Block 11 Block 1 ... Block 2 Block 11 ... Block 12 轉帳到交易所 沒有轉帳到交易所

Slide 16

Slide 16 text

51% 攻擊 • 同時間,駭客⽤他的 51% 算⼒偷偷算更長的⼀條鍊 • 該條鏈裡⾯沒有他轉帳到交易所的那筆交易 • 等他從交易所領出錢錢後,就把更長的鏈廣播給⼤家 • 這樣他的幣還在,同時⼜領了法幣出來,直接翻倍 Block 2 Block 11 Block 1 ... Block 2 Block 11 ... Block 12 轉帳到交易所 沒有轉帳到交易所

Slide 17

Slide 17 text

POW / POS / DPOS • ⽬前主流有三種不同的⽅式決定記帳權 • Proof of Work ( PoW ) • 透過計算⼀個複雜的問題來獲得記帳權 • Bitcoin ( BTC ), Ethereum ( ETH ), … • Proof of Stake ( PoS ) • 持幣數量越多的越有機會獲得記帳權 • Delegated Proof of Stake ( DPoS ) • 所有節點選舉出幾個超級節點來記帳 • 還有很多變種的 PoS 機制...

Slide 18

Slide 18 text

Ethereum

Slide 19

Slide 19 text

錢包 • 冷錢包 ( 硬體錢包 ) : 要交易的時候再插進電腦裡 • Ledger, Trezor 等 • 熱錢包 ( 軟體錢包 ) : 瀏覽器插件,或是 APP 之類的 • MetaMask, Trust Wallet 等

Slide 20

Slide 20 text

Ethereum Ropsten Network • 上課主要都是在 ropsten 測試網路中進⾏ • 不是真錢啊 • 要錢錢可以去下⾯幾個 faucet 領 • https://faucet.metamask.io/ • https://faucet.dimensions.network/ • https://faucet.ropsten.be/

Slide 21

Slide 21 text

Ethereum Address • Ethereum 的 Address 是把 public key 做 keccak256 之後再取後 20 bytes • 所以 private key 跟 address 是⼀對⼀的關係 • keccak256 就是 sha3 原本的名字,但是參數跟⽬前的 sha3 有點不同

Slide 22

Slide 22 text

Ethereum Virtual Machine ( EVM ) • 以太坊 ( Ethereum ) 除了存放交易們,還可以存放程式碼 • Ethereum Virtual Machine ( EVM ) • 去中⼼化的虛擬機 • 圖靈完備

Slide 23

Slide 23 text

智能合約 ( Smart Contract ) • ⼀個智能合約就像是⼀個物件導向中的 Class • 使⽤者可以創建智能合約,也就是存放程式碼到 Ethereum 上⾯ • 然後跟智能合約互動,也就是呼叫合約中的函式 • 智能合約的位址跟普通錢包的位址是在同⼀個空間 pragma solidity ^0.5.0; contract test { uint data; constructor () public payable { data = 1; } function money () public { msg.sender.transfer(1 ether); } }

Slide 24

Slide 24 text

Solidity • 存在 Ethereum 的其實是 bytecode,類似於 assembly code • Solidity 是⾼階的語⾔,透過編譯器編譯成 bytecode • 除了 Solidity 之外,還有另⼀種⾼階語⾔叫 Vyper • Solidity 語法類似 javascript,Vyper 語法類似 python

Slide 25

Slide 25 text

bytecode https://ethervm.io/ 0x608060405234801561001057600080fd5b5060043610610... PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x0010 JUMPI PUSH1 0x00 ...

Slide 26

Slide 26 text

Gas https://txstreet.com/ • 在 EVM 上⾯執⾏ bytecode 是要付費的 • 每個不同的 opcode 都會花費不同的 gas fee • 比如 ADD 會花費 3 gas • 那⼀個 gas 是多少錢?這是由交易發起⼈決定的 • 比如 gas price 設定成 10 gwei 的話,ADD 就會花費 30 gwei • Gas price 是給礦⼯的⼩費,給得越⾼你的交易能越快被驗證

Slide 27

Slide 27 text

單位 單位 價值多少 wei wei 1 kwei 1000 mwei 1000000 gwei 1000000000 twei 1000000000000 pwei 1000000000000000 ether 1000000000000000000 • 在 Ethereum 中最⼩單位是 wei

Slide 28

Slide 28 text

web3.js https://web3js.readthedocs.io/en/v1.3.0/ • Solidity 編譯成 bytecode 是放到 EVM 上執⾏的 • 可以看成後端 • 想要跟合約互動,我們在普通的電腦上⽤ web3.js • 可以看成前端 • 除了跟合約互動,web3.js 也可以查看 Ethereum Blockchain 上的資訊 • 也有 web3.py,就只是 python 版本的 • 還有另⼀個選擇是 ethers,號稱比 web3.js 更好⽤

Slide 29

Slide 29 text

Resources • Tutorial • cryptozombies • Online Judge • Ethernaut • Security Innovation Smart Contract CTF • Vulnerabilities • DASP Top 10 • SWC Registry

Slide 30

Slide 30 text

Smart Contract

Slide 31

Slide 31 text

Visibility Modifier 名稱 外部 此合約 ⼦合約 public ✓ ✓ ✓ private ✓ internal ✓ ✓ external ✓

Slide 32

Slide 32 text

State Modifier 名稱 保證沒有寫入 storage 保證沒有讀取 storage view ✓ pure ✓ ✓

Slide 33

Slide 33 text

Custom Modifier contract Test { address private owner; modifier onlyOwner() { require(msg.sender == owner); _; } function setOwenr(address _owner) onlyOwner public { owner = _owner; } function getOne() pure { return 1; } function getOwner() view returns(address) { return owner; } }

Slide 34

Slide 34 text

Underflow / Overflow function withdraw(uint _amount) public { require(balances[msg.sender] - _amount > 0); msg.sender.transfer(_amount); balances[msg.sender] -= _amount; } • uint 往下減會 underflow • uint 其實就是 uint256,256 bits = 32 bytes • uint 的 0 往下減會變成 2256 - 1

Slide 35

Slide 35 text

Safemath function withdraw(uint _amount) public { require(balances[msg.sender].sub(_amount) > 0); msg.sender.transfer(_amount); balances[msg.sender] = balances[msg.sender].sub(_amount); } • 使⽤ OpenZeppelin 寫好的 SafeMath.sol 函式庫 • 幫你安全的處理 uint 的加減乘除

Slide 36

Slide 36 text

Random Number • 在 EVM 中基本上沒辦法產⽣安全的 random number • 能⽤的隨機來源只有 block.timestamp, block.difficulty , block.blockhash • 但是像下⾯這個例⼦,只要部署另⼀個合約,呼叫前計算⼀下,就可以 算出⼀樣的隨機數了,因為在同⼀個 block • ⽬前最好的⽅法還是呼叫外部的中⼼化伺服器來取得隨機數 function dice() public payable { if (block.timestamp % 2 == 1) { win = true; } }

Slide 37

Slide 37 text

呼叫合約函式 https://www.4byte.directory/ contract A { function test (uint value) public {} } • 假設我們想要呼叫 A 合約的 test 函式 • 送⼀個交易給合約 A,data 欄位填該函式的 function siganture • function signature 是 keccak256('函式名稱(型態們)') 的前 4 bytes • 這個例⼦中就是 keccak256('test(uint)') 的前 4 bytes

Slide 38

Slide 38 text

Fallback / Receive contract Test { fallback () external payable {} receive () external payable {} function normal_function () public {} } • fallback 和 receive 是兩個特殊的函式 • 有⼈呼叫合約,但 data 欄位是空的 • 就會執⾏ receive • 如果沒有 receive,就會執⾏ fallback • 如果 data 欄位提供的 function signature 沒有找到 match • 執⾏ fallback

Slide 39

Slide 39 text

Reentrancy Attack function withdraw(uint _amount) public payable { require(balances[msg.sender] >= _amount); msg.sender.call{value: _amount}(""); balances[msg.sender] -= _amount; } • 當合約送錢給其他地址,該地址可能會是另⼀個合約 • 送錢給另⼀個合約,其實就是呼叫他的 receive / fallback • 那我們在 receive / fallback 裡⾯再去呼叫 withdraw ⼀次 • 因為 balances 還沒扣,所以第⼀⾏的 require 還是成立 • 就可以⼀直 transfer 把合約裡⾯的錢掏空

Slide 40

Slide 40 text

require / revert / assert • require, revert 會 refund 剩下的 gas fee • assert 會把剩下的 gas fee 都吃掉,不還你 modifier onlyOwner() { require(msg.sender == owner); _; } modifier onlyOwner() { if (msg.sender != owner) { revert(); } _; } modifier onlyOwner() { assert(msg.sender == owner); _; }

Slide 41

Slide 41 text

delegatecall https://swcregistry.io/docs/SWC-112#proxysol • delegatecall 跟 call ⼀樣可以呼叫另⼀個合約 • 但是他會使⽤原本合約的 storage • 下⾯的例⼦中,callee 是惡意的話,可以接把 owner 改掉 contract Proxy { address owner; constructor() public { owner = msg.sender; } function forward(address callee, bytes _data) public { require(callee.delegatecall(_data)); } }

Slide 42

Slide 42 text

ERC20 https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol • ⼀個代幣的標準,只要 inheritance ERC20 合約,就可以發代幣 • 代幣是存在於合約上的 • transfer 可以把⾃⼰的代幣轉給別⼈ • approve 可以授權別⼈花你的代幣 • transferFrom 可以花別⼈的代幣 function transfer(address _to, uint256 _value) returns (bool success) function transferFrom(address _from, address _to, uint256 _value) returns (bool success) function approve(address _spender, uint256 _value) returns (bool success)

Slide 43

Slide 43 text

ERC721 https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721 • 另⼀個代幣標準,也叫做 Non-Fungible Token ( NFT ) • 每個代幣都是獨⼀無⼆的,像是蒐集郵票⼀樣 • CryptoKitties 是 NFT 的⼀個著名的例⼦

Slide 44

Slide 44 text

No content