สรุป "Workshop: Hands-on Securing Smart Contract" จากงาน KBTG Inspire2
งาน KBTG Inspire2 จัดขึ้นวันที่ 26 มีนาคม 2565 ก็เป็นครั้งที่สองแล้วที่เราได้เข้าร่วมงานนี้แบบ online พอเห็นชื่อ session แล้วน่าสนใจ ก็เลยเข้าไปฟังจ้า
บางคนที่เคยอ่านบล็อกเรามาก่อนหน้านี้ จะมี session นึงในงาน Dev Mountain Tech Festival ที่ชื่อว่า Hacking The (Smart) Contract เนื้อหาจะไปในแนวทางเดียวกันเลย คือ เรื่อง Security ของ Smart Contract
แต่ใน session นี้จะทำให้เราเข้าเรื่อง Security ของ Smart Contract เพิ่มมากขึ้น ว่ามีอะไรบ้าง เราต้องทำอะไรบ้าง หลังจบจาก session speaker บอกว่าเราจะสามารถอ่าน smart contract แล้วดูว่าอันนี้ปลอดภัยได้ได้เอง
เบื้องหลังของ blockchain ทำงาน serve สิ่งที่เราต้องการ และเราจะต้องอุดช่องโหว่ เพื่อไม่ให้เสียทรัพย์ และใน session นี้จะเป็นการเรียนรู้เรื่อง Smart Contract
Agenda ในวันนี้
What is a smart contracts?
แอพเหล่านี้จะรันบน blockchain (หรือที่เขาเรียกกันว่า on-chain แหละ) ไม่ว่าจะเป็นเหล่า DeFi หรือ Dapps เช่น Uniswap, MakerDAO, AAVE, Yearn Finance เว็บซื้อขาย NFT อย่าง Opensea (ตัวอื่นคือไม่คุ้นโลโก้จริงๆ แหะๆ)
ใน session นี้นั้นจะกล่าวขึ้นการเขียน smart contract ของ Ethereum บน Testnet เนอะ ด้วยภาษา Solidity ซึ่งจริงๆแล้วสามารถเขียนได้หลายภาษา เช่น Vyper, C, C++ และ Rust เจ้าปูวแดงที่กำลังมาแรง
ต่อมาเขาทำการเปิด etherscan ซึ่งเว็บที่เอาไว้ตรวจสอบธุรกรรมที่เกิดขึ้นใน blockchain นั้นๆ แล้วก็สามารถดู smart contract ภายในนี้ได้ด้วยน้าา โดยจะเปิดของ rinkeby ซึ่งเป็นหนึ่งใน testnet ของ ethereum นั่นเอง
ในที่นี้ token ชื่อว่า Inspire Token ที่ถูก deploy จริงลง testnet
มาดูส่วนประกอบภายในโค้ดชุดนี้กันเถอะ~~
- Contract Source Code โค้ด smart contract ภาษา solidity
.
เมื่อเขียนโค้ดเสร็จแล้วทำการ deploy ลง node ต่างๆใน blockchain และการ audit ควรเริ่มจากภาษา solidity เพราะมี community ใหญ่ โดย Ethereum 2.0 จะมีการเพิ่ม execution layer ด้วย และไม่ได้รันผ่าน EVM
- Contract ABI : ทำให้แอพข้างล่าง หรือ client คุยกับ smart contract ได้ สามารถเรียก function ได้อย่างถูกต้อง และมี storage type ตัวแปรทุกตัวจะต้องกำหนด type ให้มันให้ชัดเจน เพื่อลดความผิดพลาด เพราะเมื่อเรา deploy แล้ว ไม่สามารถเปลี่ยนแปลงแก้ไขอะไรได้
- Contract Creation Code : EVM (Ethereum Virtual Machine) อ่านภาษา solidity ไม่รู้เรื่อง จึง compile solidity ก่อน ได้เลขฐาน 16 ออกมาให้ EVM สามารถอ่านตัวนี้ได้ มันจะคล้ายๆกับ java ที่รันบน jvm ที่ build once, run everywhere นั่นเอง
Why do we need to secure a smart contract?
ทำยังไงให้ smart contract ของเราปลอดภัย?
ใน etherscan นั้น ทุกคนสามารถเห็นและอ่านโค้ดได้ อีกทั้งยัง access หรือ execute ผ่าน metamark ได้ด้วย
เราสามารถตรวจสอบดูได้ว่ามีการ lock value ไปใน blockchain นี้เท่าไหร่
การที่มีข่าวโดน hack นั้น ตัว blockchain ไม่ได้โดนแฮก เนื่องจากการที่เราจะไป hack bloackchain หรือระยยได้นั้น จะต้องใช้เงินจำนวนมากในการโจมตีระบบ ซึ่ง Ethereum ค่า gas แพง แต่ถูก hack จากช่องโหว่ของ smart contract เพื่อดึงเงินในระบบแทน
เว็บ rekt.news รวบรวม smart contract หรือ project ที่ถูก hack ว่ามีทั้งสิ้นเท่าไหร่ บางส่วนได้เงินคืน บางส่วนไม่ได้เลยก็มี
Case Study : Uranium Finance
- Uranium Finance เป็นฟาร์มซิ่ง ตัว smart contract ยังไม่ได้ audit
- ฟาร์มเหรียญ RADS
- ตัว source code fork มาจาก Github แล้ว deploy เป็นของเราได้เลย เกิดอาการก็อปโค้ดแล้วไม่เข้าใจโค้ดที่เขียนในนั้น ตัวเลข 1000 ถูกเปลี่ยนเป็น 10000 ของ UniSwap มีค่า K เอาไปคำนวณ bounding curve เป็นสมการพาราโบลา
- LP ทำให้ balance แก้ balance ทำให้คำนวณค่าผิดพลาด เลขต่างกัน 100 เท่า
- การแฮก เอา 1 wei โยนเข้าไปใน pool แล้ว swap asset ออกมาได้
Case Study : Poly network
- $611 ล้านดอลล่าที่ถูกแฮกไป มากกว่า GDP ในบางประเทศเสียอีก
- ทำงานในรูปแบบ cross-chain protocol โอน asset ระหว่าง chain กัน มีคนกลางที่สามารถเชื่อถือได้ ชื่อว่า keeper ถ้าใครมีการส่ง transaction เข้ามา จะทำการสร้าง transaction ระหว่างกันที่ chain ปลายทาง เช่น จะโอน ETH จาก BSC ไป Ethereum จะส่งต่อกันโดยการ mint เหรียญใหม่ เป็น WETH
- ช่องโหว่เกิดจาก function check hash signature (เป็น one-way คือ input อะไรเข้าไป output จะ fix length และเป็นค่าเดิมเสมอ) ในการเขียน function บางอย่าง byte ที่ใช้ดึงมีจำนวนน้อยมากๆ ทำให้มีโอกาสชนกันได้
byte64(keccak256(abi.encodePacked(_method, "byte,bytes,uint64")))
เอาไว้ simulate private key ในการ sign transaction- hacker สร้าง function ตังนึง และ hash เข้าไป ทำให้ signature function มีความเหมือนกันได้ และ compromise private key (by pass) ดึงของออกจาก pool ได้เลย
- ยังโชคดีที่ hacker คืนเงินที่แฮกได้กลับมา และเขาได้เงินรางวัลจากการแฮกครั้งนี้กลับไป
Case Study : Treasure DAI
- เป็บเว็บที่มี model คล้ายๆแชร์ลูกโซ่ ขาย NFt และมีการทำ royality แบ่ง % ให้กับเจ้าของ และสามารถนำ NFT มา stake จะได้เหรียญ MAGIC กลับมา วนไปซื้อของใน marketplace ได้อีก
- โดนแฮกตรง function
BuyItem
จะทำการ check ว่า item ในตะกร้าราคาเท่าไหร่ และมีกี่ชิ้น เช่น ซื้อของราคา 1 ETH จำนวน 1 ชิ้น ถ้าซื้อโดยไม่จ่ายเงินได้ไหม? มีการ checkrequire(_quantity > 0, "Cannot buy zero");
Smart contract audit
เราจะให้เขา audit smart contract ของเรายังไง?
ถ้าอยากเป็น blockchain developer แต่ไม่มีความรู้เลย มีใครช่วยได้บ้าง อาจจะส่งให้ audit ดูให้ อาจจะ audit หลายรอบ และอาจจะมีราคาแพง
จะมีขั้นตอนดังนี้
- เตรียม smart contract ที่จะทำการส่งมอบให้ audit
- audit เอา code ไปอ่าน อาจจะเป็นแบบ manual หรือ automate ประมาณว่าเป็น bug worthy หรือ hacker สายขาว
- audit present finding ว่าเจอช่องโหว่อะไรล้าง ส่ง report เบื้องต้นให้
- developer ทำการแก้ไข แล้วส่งกลับไปให้ทาง audit ตรวจอีกที
- ถ้าไม่มี issue อะไรแล้ว จะมี final report มาให้ เป็นอันจบกระบวนการ
ใน PancakeSwap จะมี final report แนบไว้ในหน้าเว็บนะ เข้าใจว่าลิ้งนี้นะ
ปล. เห็นว่าเขามี Bug Bounty ด้วยแหะ
Smart contract weakness classification
ช่องโหว่มีแบบไหนบ้างนะ
Smart contract weakness classification (SWC) คือ scheme หรือ กฏของ dev ในด้าน security ใช้มาตรฐานในการ classify, identify, weakness
เป็นการรวมพลังของ software developer และ pentest ส่งช่องโหว่ให้เราแก้
ส่วน Common weaknesses enumeration (CWE) เป็น community base ที่เป็น software และ hardware
มี 6 อันที่เจอบ่อย
- SWC-100 : Function Default Visibility / CWE-170 : Improper Adherence to Coding Standards
public function ทุกคนเอาไปใช้ได้ แก้โดยใส่ internal
ตามไปด้านหลัง ไม่ได้ให้ยิงเข้ามาได้
- SWC-101 : Integer Overflow and Underflow / CWE-682 : Incorrect Calculation
ทำความเข้าใจเรื่อง overflow กับ underflow กันก่อน
overflow จะเหมือนเรามีรถ แล้วรถเก็บระยะทางผ่าน gate ว่าวิ่งไประยะทางเท่าไหร่แล้ว ถ้าค่าครบแล้ว มันจะ reset เป็น 0 ส่วน underflow จะถอยกลับมา
มีเปิด demo ให้ดู เป็นการเขียน smart contract ฝากประจำ lock เงินไว้ในระบบอย่างน้อย 1 week ถ้าเรา lock เวลาเพิ่ม เรียก increaseLockTime()
ถอนก็เรียกผ่าน withdraw()
จากนั้นเขาก็ compile และ deploy ให้ดู ฝากเงินผ่าน deposit()
รอ 1 วินาทีจึงจะถอนได้ เพราะตัว lock time ยังไม่หมดอายุ
แล้วก็ deploy Attrack
ใช้ timeblock เพื่อยิงเข้าไปต่อ แล้วก็ check balance แล้วเอา blocktime มาทำให้ overflow สุดท้ายเปลี่ยน locktime มาใส่ใหม่ ถอนได้เลย
อันนี้โค้ด
.
- SWC-107 : Reentrancy / CWE-841: Improper Enforcement of Behavioral Workflow
ใน blockchain เก็บ stage ว่าคนๆนี้มี ETH เท่าไหร่ ฝากเท่าไหร่ มี lock time เท่าไหร่ hacker ทำการยิงจาก contract A ไป B ยิงซํ้าและถอนจนหมดบัญชี โดยที่มันทำงานไม่จบได้
มี demo คือ deploy smart contract ใหม่ ฝากผ่าน attack
ฝากแค่ 1 ETH และถอนออกทันทีด้วย fallback()
ถ้าไม่มี function นั้นๆจะเข้า fallback ทั้งหมด (เหมือน switch case ที่เป็น default)
และถอนออกทันทีด้วย fallback()
ถ้าไม่มี function นั้นๆจะเข้า fallback ทั้งหมด (เหมือน switch case ที่เป็น default)
ใน Remix เราสามารถ debug ดูได้ด้วยน้าา
hacker จะทำการยิง recursion กับ withDraw()
selfdestruct
เป็นการทำลาย smart contract ทั้งหมด และโอน ETH ทั้งหมดที่เข้ามาที่เรา
อันนี้โค้ด ลองไปรันดูได้
.
- SWC-110 : Assert Violation / CWE-670 : Always-Incorrect Control Flow Implementation
เป็นการจงใจเขียนโค้ดผิด โดยใช้ assert เข้ามาช่วย
- SWC-112 : Delegate Call to Untrusted Callee / CWE-829 : Inclusion of Functionality from Untrusted Control Sphere
มี user context หรือรายละเอียด transaction นั้นๆที่ user ส่งไป และสามารถสวมรอยเป็นใครก็ได้ แก้โดย setCallee
กำหนดให้เป็น owner เท่านั้น
มี demo คือ preserve context + storage layout
pwn()
หรือ changeOwner
-> hackme ใช้ library ดูจาก constructor ก็ได้ เปลี่ยน owner หรือเจ้าของ contract ได้
แก้โดยว่าใคร call function นี้ได้บ้าง อันนี้ดูไว้เป็นกรณีศึกษาเนอะ
อันนี้แคปโค้ดมาไม่หมด เลยไม่ได้แปะ gist ไว้
- SWC-123 : Requirement Violation / CEW-573 : Improper Following of Specification by Caller
ทำ function ให้ทำงานถูกต้องแต่แรกจะดีกว่า
จริงๆมีเยอะ แต่เลือกอันที่เขานิยมแฮกกัน
Security techniques
tool ที่ช่วยเรา audit และตรวจสอบ smart contract
แล้วจะดูได้แบบไหน?
มี 3 เทคนิคในการดู คือ
- Static : การทำงานแบบ compiler (high to low) และ analyze syntax tree ว่าทำงานถูกต้องไหม เช่น compile ผ่าน
- Fuzzing : sudo random transaction ยิงแบบไหนให้พัง เหมือน tester ในการหา input หรือ parameter ให้พังก่อนขึ้น production จริง แต่ในที่นี้คือ bot ทำนะ
- Symbolic : formal validation public คำนวณผ่านสมการทางคณิตศาสตร์ เป็น trust table สร้างขึ้นมาโดยโปรแกรม เป็น verify propoties เพิ่มเติมให้ auto และ ลึกกว่า
สรุป static เร็วสุด โดยเอามาจาก building-secure-contracts
และทุกอย่างไม่มีอะไรปลอดภัย 100% อาจจะเป็น zero day ก็ได้ อยู่ที่จะมีคนเจอหรือเปล่า
Tool ที่จะนำมาใช้
- slither : ใช้
pipy
ในการ install หรือจะใช้บน VS Code ก็ได้
- echidna : ใช้ทำ fuzzing หา parameter กึ่งสุ่ม แนะนำให้ใช้ docker (คล้ายๆ VM เป็นการสร้าง container ขึ้นมาตัวนึง) รัน
- manticore : ใช้ docker ยิงไปยัง command แล้วให้มัน gen testcase ออกมาว่ามีช่องโหว่อะไรบ้าง แต่มีปัญหาหลายอย่าง เป็น symbolic execution tool นะ
- mythril : ใช้งานง่ายกว่า manticore คุมด้วยมาตรฐานของ SWC
สรุป ทุกคนสามารถโดนแฮกได้ ต้องรู้ตัวเองและป้องกันได้ ทำให้ความเสี่ยงของเราลดน้อยลง
Q & A
- reentrant ทำให้มีช่องโหว่ใน smart contract ได้จริงๆ
- fast loan มีช่องโหว่ในการทำ tokenomic ให้ถึง เงินออกจากระบบได้อย่างรวดเร็ว
ในงาน KBTG Inspire เราเข้าไปฟังแค่ session นี้เอง เพราะช่วงเช้าติดกิจกรรมอื่น แหะๆ
สามารถ support ค่ากาแฟเจ้าของบล็อกได้ที่ปุ่มแดงส้มสุดน่ารักที่มุมซ้ายล่าง หรือกดปุ่มตรงนี้ก็ได้จ้า
กด follow Twitter เพื่อได้รับข่าวสารก่อนใคร เช่น สปอย content ใหม่ หรือสรุป content เร็วๆในนี้จ้า
ติดตามข่าวสารและบทความใหม่ๆได้ที่
Subscribe ช่อง YouTube ของเราได้ที่
download แอพอ่านบล็อกใหม่ของเราได้ที่นี่