Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
[Crypto in CTF] Blockchain Security
Search
oalieno
October 31, 2020
Technology
450
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
[Crypto in CTF] Blockchain Security
https://github.com/oalieno/Crypto-Course/tree/master/Blockchain
oalieno
October 31, 2020
More Decks by oalieno
See All by oalieno
[Crypto in CTF] Classical Cipher
oalieno
0
490
[Crypto in CTF] Block Cipher Mode
oalieno
0
1.1k
[Crypto in CTF] HASH
oalieno
0
310
[Crypto in CTF] LFSR
oalieno
0
550
[Crypto in CTF] RSA
oalieno
0
780
[Crypto in CTF] Bleichenbacher RSA Signature Forgery
oalieno
0
650
滲透測試基本技巧與經驗分享
oalieno
2
1.2k
Other Decks in Technology
See All in Technology
SO-101×VLAによる3色キューブのピック&プレース
abeja
0
180
Master Dataグループ紹介資料
sansan33
PRO
1
4.8k
Flutterをカメラで動かしたかった話
sony
1
130
AWS ネットワーク構築でハマった(ハマりかけた) 5選とそこから得た教訓
nagisa53
4
200
Pavlokで始める電撃駆動開発
sgrsn
0
190
【CEDEC2026】『Relink』を拡張せよ - 『GRANBLUE FANTASY: Relink - Endless Ragnarok』の開発速度と品質を守るCI運用
cygames
PRO
0
150
[しろおび夏祭り2026] チャットするAIから、作業するAIへ - 使われ方の変化と、その裏側で起きていること
kk0n
0
1.7k
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
4.9k
認知負荷をGemini で溶かす — GKE 基盤「Orbit」における AI エージェントの実践
sansantech
PRO
1
290
Forza Horizon 6 のテレメトリ機能で 自動運転に使えそうな学習データを集める話
henjin0
0
160
名刺メーカーDevグループ 紹介資料
sansan33
PRO
0
1.2k
20260807_第6回_関東kaggler会LT_claw系bot xangiと始める、"寂しくない" kaggle
sugupoko
0
250
Featured
See All Featured
Done Done
chrislema
186
16k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1.1k
[SF Ruby Conf 2025] Rails X
palkan
2
1.3k
Design in an AI World
tapps
1
280
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
73
41k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
3
420
Designing Powerful Visuals for Engaging Learning
tmiket
1
480
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
Balancing Empowerment & Direction
lara
6
1.2k
Statistics for Hackers
jakevdp
799
230k
Navigating Team Friction
lara
192
16k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Transcript
Blockchain Security oalieno
Introduction to Blockchain
Blockchain A → B $3 C → A $2 ⋮
• 去中⼼化的記帳本 • 去中⼼化:⼤家都有⼀份⼀模⼀樣的記帳本備份 • 記帳本:記錄誰給誰多少錢 A → B $3 C → A $2 ⋮ Alice Bob
Blockchain • Alice 要給 Bob 1 塊錢 • 記錄⼀筆交易,並廣播給其他所有⼈ A
→ B $3 C → A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A → B $1
Blockchain • Bob 可以偽造⼀筆交易,廣播給所有⼈ A → B $3 C →
A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A → B $100
Blockchain • 因此每⼀筆帳必須簽章 • 將錢從 A 轉出去的帳,要有 A 簽章才有效 A
→ B $3 C → A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A 簽章 C 簽章 C 簽章 A 簽章
Blockchain • 但是就算有簽章,Bob 可以輕易的複製同⼀份交易再廣播出去 A → B $3 C →
A $2 ⋮ A → B $3 C → A $2 ⋮ Alice Bob A 簽章 C 簽章 C 簽章 A 簽章 A → B $3 A 簽章
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 簽章
如何達成共識 • ⼤家都在廣播交易 • 怎麼決定誰先誰後,並保證⼤家的記帳本都長得⼀樣? 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 簽章
誰有記帳權 • ⼤家決定出⼀個⼈來記帳 • 每次會記好幾個交易的帳,稱為⼀個區塊 ( Block ),不會只記⼀個交易 • 先算出哪個
Nonce 會讓整個 Block 的 Hash 開頭是 0x00 的⼈記帳 TX 0 : A → B $3 TX 5 : C → A $2 ⋮ A 簽章 C 簽章 Nonce 0x1234 Hash 0x00abcd Alice
誰有記帳權 • 要 Hash 的東⻄包括前⼀個 Block 的 Hash,形成⼀連串的 Block Chain
• 並且記帳的⼈能獲得獎勵,所以⼤家都會搶著記帳 TX 0 : A → B $3 Reward A $10 ⋮ A 簽章 Nonce 0x1234 Hash 0x00abcd Hash of Previous Block Alice
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
分岔 ( fork ) • 剛好兩個⼈都算出正確的 Nonce 挖出區塊怎麼辦 • 看誰的鍊比較長誰就是主鏈
Block 2 Block 2 Block 3 Block 4 Block 1
51% 攻擊 • 當某個礦⼯有全網 51% 以上的算⼒,那他挖的那條鏈就會是最長鍊 • 他可以故意排除或竄改交易順序 • 但因為有簽章,所以他還是不能亂轉他沒有的錢,也不能憑空⽣錢
• 2018 年 5 ⽉,Bitcoin Gold ( BTG ) 就被 51% 攻擊了,損失 1800 萬美⾦
51% 攻擊 • 先轉帳 $1000 到⽬標交易所 • 等 10 個區塊
confirmation 後,交易所認可該筆交易 • 駭客便可以將錢從交易所領出來換成法幣 Block 2 Block 11 Block 1 ... Block 2 Block 11 ... Block 12 轉帳到交易所 沒有轉帳到交易所
51% 攻擊 • 同時間,駭客⽤他的 51% 算⼒偷偷算更長的⼀條鍊 • 該條鏈裡⾯沒有他轉帳到交易所的那筆交易 • 等他從交易所領出錢錢後,就把更長的鏈廣播給⼤家
• 這樣他的幣還在,同時⼜領了法幣出來,直接翻倍 Block 2 Block 11 Block 1 ... Block 2 Block 11 ... Block 12 轉帳到交易所 沒有轉帳到交易所
POW / POS / DPOS • ⽬前主流有三種不同的⽅式決定記帳權 • Proof of
Work ( PoW ) • 透過計算⼀個複雜的問題來獲得記帳權 • Bitcoin ( BTC ), Ethereum ( ETH ), … • Proof of Stake ( PoS ) • 持幣數量越多的越有機會獲得記帳權 • Delegated Proof of Stake ( DPoS ) • 所有節點選舉出幾個超級節點來記帳 • 還有很多變種的 PoS 機制...
Ethereum
錢包 • 冷錢包 ( 硬體錢包 ) : 要交易的時候再插進電腦裡 • Ledger,
Trezor 等 • 熱錢包 ( 軟體錢包 ) : 瀏覽器插件,或是 APP 之類的 • MetaMask, Trust Wallet 等
Ethereum Ropsten Network • 上課主要都是在 ropsten 測試網路中進⾏ • 不是真錢啊 •
要錢錢可以去下⾯幾個 faucet 領 • https://faucet.metamask.io/ • https://faucet.dimensions.network/ • https://faucet.ropsten.be/
Ethereum Address • Ethereum 的 Address 是把 public key 做
keccak256 之後再取後 20 bytes • 所以 private key 跟 address 是⼀對⼀的關係 • keccak256 就是 sha3 原本的名字,但是參數跟⽬前的 sha3 有點不同
Ethereum Virtual Machine ( EVM ) • 以太坊 ( Ethereum
) 除了存放交易們,還可以存放程式碼 • Ethereum Virtual Machine ( EVM ) • 去中⼼化的虛擬機 • 圖靈完備
智能合約 ( 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); } }
Solidity • 存在 Ethereum 的其實是 bytecode,類似於 assembly code • Solidity
是⾼階的語⾔,透過編譯器編譯成 bytecode • 除了 Solidity 之外,還有另⼀種⾼階語⾔叫 Vyper • Solidity 語法類似 javascript,Vyper 語法類似 python
bytecode https://ethervm.io/ 0x608060405234801561001057600080fd5b5060043610610... PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1
ISZERO PUSH2 0x0010 JUMPI PUSH1 0x00 ...
Gas https://txstreet.com/ • 在 EVM 上⾯執⾏ bytecode 是要付費的 • 每個不同的
opcode 都會花費不同的 gas fee • 比如 ADD 會花費 3 gas • 那⼀個 gas 是多少錢?這是由交易發起⼈決定的 • 比如 gas price 設定成 10 gwei 的話,ADD 就會花費 30 gwei • Gas price 是給礦⼯的⼩費,給得越⾼你的交易能越快被驗證
單位 單位 價值多少 wei wei 1 kwei 1000 mwei 1000000
gwei 1000000000 twei 1000000000000 pwei 1000000000000000 ether 1000000000000000000 • 在 Ethereum 中最⼩單位是 wei
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 更好⽤
Resources • Tutorial • cryptozombies • Online Judge • Ethernaut
• Security Innovation Smart Contract CTF • Vulnerabilities • DASP Top 10 • SWC Registry
Smart Contract
Visibility Modifier 名稱 外部 此合約 ⼦合約 public ✓ ✓ ✓
private ✓ internal ✓ ✓ external ✓
State Modifier 名稱 保證沒有寫入 storage 保證沒有讀取 storage view ✓ pure
✓ ✓
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; } }
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
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 的加減乘除
Random Number • 在 EVM 中基本上沒辦法產⽣安全的 random number • 能⽤的隨機來源只有
block.timestamp, block.difficulty , block.blockhash • 但是像下⾯這個例⼦,只要部署另⼀個合約,呼叫前計算⼀下,就可以 算出⼀樣的隨機數了,因為在同⼀個 block • ⽬前最好的⽅法還是呼叫外部的中⼼化伺服器來取得隨機數 function dice() public payable { if (block.timestamp % 2 == 1) { win = true; } }
呼叫合約函式 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
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
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 把合約裡⾯的錢掏空
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); _; }
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)); } }
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)
ERC721 https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721 • 另⼀個代幣標準,也叫做 Non-Fungible Token ( NFT ) •
每個代幣都是獨⼀無⼆的,像是蒐集郵票⼀樣 • CryptoKitties 是 NFT 的⼀個著名的例⼦
None