การวิเคราะห์การโจมตี BlockSec DeFi ชุดที่ 4 ความเข้าใจผิด: การวิเคราะห์เหตุการณ์การโจมตีด้วยสัญญา Me
การเงินแบบกระจายอำนาจ (DeFi) เป็นรูปแบบโครงการที่ได้รับความนิยมในระบบนิเวศของบล็อกเชน การรักษาความปลอดภัยเป็นสิ่งสำคัญอย่างยิ่ง ตั้งแต่ปีที่แล้ว มีเหตุการณ์ด้านความปลอดภัยเกิดขึ้นหลายสิบครั้ง
ในฐานะทีมวิจัยระยะยาว (https://blocksecteam.com) ที่เกี่ยวข้องกับความปลอดภัยของ DeFi BlockSec ได้ค้นพบเหตุการณ์ด้านความปลอดภัยของ DeFi จำนวนมากโดยอิสระ และผลการวิจัยได้รับการเผยแพร่ในการประชุมด้านความปลอดภัยชั้นนำ (รวมถึง USENIX Security, CCS และ หมวกสีดำ). ในช่วงเวลาต่อไป เราจะวิเคราะห์เหตุการณ์ด้านความปลอดภัยของ DeFi อย่างเป็นระบบและวิเคราะห์สาเหตุที่แท้จริงเบื้องหลังเหตุการณ์ด้านความปลอดภัย
รีวิวที่ผ่านมา:
(3)[BlockSec DeFi Attack Analysis Series 2] แจกทุกอย่าง: ค่าธรรมเนียม Sushiswap ถูกขโมย
[BlockSec DeFi Attack Analysis Series 3] ขโมยท้องฟ้าและเปลี่ยนวัน: การวิเคราะห์เชิงลึกของเหตุการณ์การโจมตี Akropolis
0xffffffff. คำนำ
เมื่อเวลา 03:40 น. ของวันที่ 21 กรกฎาคม 2021 ตามเวลาปักกิ่ง ระบบตรวจจับการโจมตีของเราตรวจพบธุรกรรมที่ผิดปกติ เราพบว่านี่เป็นเหตุการณ์ที่โทเค็นเงินฝืด (โทเค็นเงินฝืด) กลไก KEANU ถูกใช้เพื่อโจมตีช่องโหว่ของกลไกการคำนวณรางวัลของสัญญา Memestake ที่ปรับใช้โดย Sanshu Inu ในที่สุดผู้โจมตีก็ทำ กำไรประมาณ 56 ETH ต่อคน การวิเคราะห์โดยละเอียดดังต่อไปนี้:
คำแนะนำในการอ่าน:
หากคุณยังใหม่กับ DeFi (Ethereum) คุณสามารถอ่านได้ตั้งแต่เริ่มต้น แต่บทความค่อนข้างยาว ดังนั้นหากคุณอ่านไม่ออก อย่าลืมให้ความสนใจก่อนที่จะออกไป
หากคุณมีความเข้าใจที่ดีขึ้นเกี่ยวกับโครงการรวบรวม DeFi เช่น Akropolis คุณสามารถเริ่มต้นได้โดยตรงจาก "การวิเคราะห์การโจมตี 0x2"
0x0 บทนำเบื้องต้น
ตั้งแต่ต้นปีนี้ Dogecoin (DOGE) และ Shiba Inucoin (SHIB) ได้รับความสนใจอย่างกว้างขวาง ขณะเดียวกัน เหรียญ meme อื่น ๆ ที่เกี่ยวข้องก็ได้รับความนิยมเช่นกันซึ่งได้กระตุ้นให้กลุ่มโครงการจำนวนมากพัฒนา meme ของตนเอง เหรียญและให้บริการเหรียญ meme รอบเหรียญ meme บริการที่ Sanshu Inu เป็นสมาชิก Sanshu Inu ไม่เพียงแต่ออกเหรียญ Meme SANSHU เท่านั้น แต่ยังสร้างสัญญา Memestake เพื่อเป็นแหล่งรวมการทำฟาร์มสำหรับเหรียญ Meme อีกด้วย ตราบใดที่ผู้ใช้จำนำเหรียญมีมใน Memestake พวกเขาจะได้รับโทเค็น Mfund เป็นรางวัล
ในทางกลับกัน เหรียญมีมจำนวนมากเป็นโทเค็นเงินฝืด กล่าวคือ การออกโทเค็นดังกล่าวจะค่อยๆ ลดลง ภาวะเงินฝืดของเหรียญ meme บางส่วนเกิดขึ้นได้จากการหักเหรียญบางส่วนเพื่อทำลายและแจกจ่ายทุกครั้งที่ผู้ใช้ทำธุรกรรมโอน (โอน) ซึ่งจะทำให้จำนวนโทเค็นที่ได้รับจริงจากผู้รับน้อยกว่าการชำระเงินจริง ตามปริมาณผู้จ่าย โทเค็นเงินฝืด KEANU ที่เกี่ยวข้องในครั้งนี้ใช้รูปแบบนี้
หลักการทั่วไปของการโจมตีคือการลดจำนวน KEANU ที่มีอยู่โดยการควบคุม Memestake เพื่อดำเนินการถ่ายโอน KEANU หลายครั้งเข้าและออก เพื่อใช้ช่องโหว่ในฟังก์ชันการคำนวณรางวัลเพื่อทำให้ Memestake ส่ง Mfund จำนวนมากไปยัง ผู้โจมตี
0x1 การวิเคราะห์โค้ด
เพื่อความสะดวกในการทำความเข้าใจ ก่อนอื่นเราจะแนะนำสัญญาทางกายภาพสองรายการที่เกี่ยวข้องกับการโจมตีนี้: สัญญา KeanuInu ของโทเค็น KEANU และสัญญา Memestake
สัญญาของคีนูอินุ
ตามที่กล่าวไว้ข้างต้น เมื่อ KeanuInu รับรู้ถึงการโอนโทเค็น KEANU มันจะหักเปอร์เซ็นต์ของเหรียญสำหรับการทำลายและแจกจ่ายซ้ำ และสัดส่วนของการทำลายจะถูกตั้งค่าเป็นค่าคงที่ - 2% ดังที่แสดงในรูป เมื่อเรียกใช้ฟังก์ชัน Transfer() และ TransferFrom() ของ KeanuInu จำนวนการโอนที่แสดงในการเรียกใช้ฟังก์ชันจะไม่สอดคล้องกับจำนวนที่บันทึกไว้ในบันทึกเหตุการณ์การปล่อยhttp://tx.blocksecteam.com:8080/เนื่องจากความซับซ้อนของการเรียกใช้งานโค้ดจริงจะไม่แสดงที่นี่ เพื่อนๆ ที่สนใจสามารถตรวจสอบการติดตั้งสัญญาได้ที่ etherscan.io ตามที่อยู่ของสัญญาที่ให้ไว้ในภาคผนวกในภายหลัง นอกจากนี้ ภาพหน้าจอสองภาพข้างต้นมาจากเครื่องมือวิเคราะห์ธุรกรรมที่เราพัฒนาขึ้นเอง ซึ่งขณะนี้อยู่ในช่วงเบต้าแบบเปิด ยินดีต้อนรับสู่คลิก
ลองดู. วิธีที่เครื่องมือของเรารวมการเรียกฟังก์ชันเข้ากับบันทึกเหตุการณ์ที่สร้างขึ้นระหว่างกระบวนการนั้นมีประโยชน์มากกว่าสำหรับการวิเคราะห์ปัญหาต่างๆ เช่น โทเค็นเงินฝืด
สัญญาเมมสเตค
รูปด้านล่างคือฟังก์ชันการฝากเงินของ MemeStake ฟังก์ชันจะเรียกใช้ updatePool ก่อนเพื่ออัปเดตสถานะของ Fund Pool จากนั้นจึงโอนโทเค็นของผู้ใช้ไปที่ตัวมันเอง เมื่อ _amount ที่เข้ามามีค่ามากกว่า 0 การโอนจะดำเนินการในบรรทัดที่ 1295 ของรหัส
อย่างไรก็ตาม เนื่องจากลักษณะเงินฝืดของโทเค็น KEANU แม้ว่าจำนวนเงินที่ส่งผ่านเมื่อเรียกฟังก์ชัน safeTransferFrom คือ _amount จำนวนเงินที่โอนไปยังกลุ่มกองทุนจริง ๆ จะน้อยกว่า _amount และในการวิเคราะห์โค้ด เราสังเกตเห็นว่าปลายทางของการโอนคือตัวคุณเอง กล่าวคือ สำหรับ MemeStake เงินฝากของผู้ใช้ทั้งหมดในสกุลเงินใดสกุลเงินหนึ่ง (เช่น โทเค็น KEANU) เป็นของ MemeStake
ในบรรทัดที่ 1296 หลังการโอน MemeStake จะลงทะเบียนเงินฝากของผู้ใช้ แต่การลงทะเบียนที่นี่ยังคงเป็น _amount (และจำนวนการโอนจริงน้อยกว่า _amount) ดังนั้นจำนวนเงินฝากจริงของผู้ใช้จึงน้อยกว่าจำนวนผู้ใช้ที่ลงทะเบียน
สุดท้าย ในบรรทัดที่ 1299 จะเห็นว่าพารามิเตอร์ user.rewardDebt ยังคำนวณตาม (มากกว่ามูลค่าจริง) user.amount
รูปด้านล่างคือฟังก์ชันการถอนของ MemeStake ฟังก์ชันจะตรวจสอบก่อนว่า user.amount มียอดคงเหลือเพียงพอหรือไม่ แต่เนื่องจาก user.amount นั้นมีค่ามากกว่าค่าจริง การตรวจสอบที่นี่จึงไม่ถูกต้อง ถัดไป ฟังก์ชัน updatePool จะถูกเรียกใช้เพื่ออัปเดตสถานะของกองทุนรวม
ในบรรทัดที่ 1321 ฟังก์ชันการถอนจะหักยอดคงเหลือที่ลงทะเบียนใน user.amount ก่อน จากนั้นจึงเรียกใช้ฟังก์ชันการโอนเพื่อโอนโทเค็นกลับไปยังผู้ใช้ เช่นเดียวกับฟังก์ชันการฝากเงินก็มีปัญหาเกี่ยวกับตรรกะตรงนี้เช่นกัน เนื่องจาก การโอนแต่ละครั้งจะทำให้เกิดเงินฝืด ดังนั้น จำนวนเงินที่โอนไปยังผู้ใช้จะน้อยกว่าจำนวนเงินที่โอนจริง
สุดท้าย ดูที่ฟังก์ชัน updatePool ของ MemeStake ก่อนอื่น จะเห็นได้จากบรรทัดที่ 1255 ว่าการโทรแต่ละครั้งจะบันทึก blockNumber ที่อัปเดตล่าสุด หากบล็อกที่เรียกในครั้งนี้เหมือนกับการอัปเดตครั้งล่าสุด ก็จะส่งกลับโดยตรง กล่าวคือ updatePool จะอัปเดตแต่ละรายการเท่านั้น บล็อกสถานะกองทุนรวม
pool.accMfundPerShare += mFundReward / token.balanceOf(MemeStake)
ถัดไป ในบรรทัดที่ 1259 จะได้รับยอดคงเหลือของ MemeStake ในสัญญาโทเค็น (ตามที่กล่าวไว้ข้างต้น ทุกครั้งที่ผู้ใช้ฝากเงิน โทเค็นจะถูกโอนไปยัง MemeStake) สุดท้าย ในบรรทัดที่ 1275 ยอดคงเหลือนี้จะถูกใช้เป็นตัวส่วนในการคำนวณรางวัลสำหรับการฝากและถอนแต่ละครั้งของกองทุนรวม (นั่นคือ พารามิเตอร์ pool.accMfundPerShare) มีการคำนวณดังนี้:
rewardMfund = user.amont * pool.accMfundPerShare / 1e18 - user.rewardDebt。
กลับมาที่การถอน เรามาดูกันว่าโทเค็นรางวัลการฝากและถอนเงิน Mfund ถูกโอนอย่างไร ขั้นแรก ในบรรทัดที่ 1325 ของฟังก์ชันการถอนเงินในรูปด้านบน ให้คำนวณว่าผู้ใช้มีโทเค็น Mfund ที่รอดำเนินการซึ่งยังไม่ได้ออกหรือไม่ สูตรการคำนวณคือ:
user.rewardDebt = user.amount * pool.accMfundPerShare / 1e18
และ rewardDebt คำนวณดังนี้ (บรรทัดที่ 1325 ในรูป):
ดังนั้นจึงไม่ใช่เรื่องยากที่เราจะสร้างการโจมตีที่เป็นไปได้จากโค้ด:
ประการแรก ภายในการทำธุรกรรม กลุ่มกองทุนของ MemeStake จะถูกระบายออกโดยการเรียกใช้ฟังก์ชันฝากและถอนซ้ำๆ การดำเนินการนี้ใช้ประโยชน์จากปัญหาโค้ดสามประการ:
ประการแรก user.amount จะถูกเรียกเก็บเงินมากกว่ามูลค่าจริง ดังนั้นการถอนทุกครั้งจึงจะสำเร็จ
ประการที่สอง เงินทุนของผู้ใช้ทั้งหมดใน MemeStake อยู่ในกลุ่มเดียวกัน ดังนั้นการโอนแต่ละครั้งจะเบิร์นโทเค็น KEANU ที่ฝากโดยผู้ใช้รายอื่นในกลุ่ม
ประการที่สาม เนื่องจาก updatePool ไม่ได้ทำการอัปเดตสถานะในบล็อกเดียวกัน มันจะไม่ส่งผลกระทบต่อพารามิเตอร์ pool.accMfundPerShare และจะไม่สร้างรางวัลโทเค็น Mfund
ถัดไป ในบล็อกถัดไป ให้เรียกใช้ฟังก์ชันการถอนโดยตรง
จากนั้นในบรรทัดที่ 1315 ของฟังก์ชันการถอน จำนวนรางวัล Mfund ที่คำนวณได้นั้นสูงมาก ส่งผลให้รางวัล Mfund จำนวนมาก
0x2 การวิเคราะห์การโจมตี
0x2 การวิเคราะห์การโจมตี
สาเหตุของช่องโหว่และวิธีใช้ประโยชน์จากช่องโหว่ดังกล่าวได้แนะนำไปแล้ว ต่อไป เราจะแนะนำวิธีที่ผู้โจมตีทำการโจมตีจริง
ดังที่แสดงในรูป การโจมตีสามารถแบ่งออกเป็น 4 ขั้นตอน ซึ่งขั้นตอนการโจมตีที่สำคัญคือ ขั้นตอนที่ 2 ซึ่งใช้ลักษณะของโทเค็นเงินฝืดเพื่อควบคุมการคำนวณรางวัลของ Memestakeขั้นตอนที่ 1 (การเตรียมการ) ขั้นแรก ผู้โจมตีจะสร้างและเริ่มต้นสัญญา 2 ฉบับ ซึ่งระหว่างนั้นสัญญาที่หนึ่งKEANUเพื่อดำเนินการตามสัญญาการลงทุนตามปกติ ผู้โจมตีได้ฝากเงินประมาณ 2,049B เข้าสู่ Memestake ผ่านสัญญา 1เพื่อปูทางสู่ขั้นตอนที่ 3 เพื่อรับรางวัล MFUND จำนวนมากสัญญาสอง
เพื่อจัดการกับสัญญาการคำนวณรางวัล Memestake การดำเนินการอนุมัติของโทเค็นที่เกี่ยวข้องจะดำเนินการก่อน0x00edในขั้นตอนที่สอง (การจัดการ) ผู้โจมตีจะยืมโทเค็น KEANU จำนวนมากจาก uniswapV2 ก่อน จากนั้นจึงฝากและถอนโทเค็น KEANU จำนวนมากไปยัง Memestake ผ่านสัญญา 2 ทำให้ Memestake ถูกบังคับให้แลกเปลี่ยนจำนวนมาก คีอานู. เนื่องจาก KEANU เป็นโทเค็นเงินฝืด แต่ละธุรกรรมจะเผาผลาญ 2% ของจำนวนธุรกรรม ส่งผลให้เงินฝากจริงของผู้ใช้ใน Memestake น้อยกว่าจำนวนผู้ใช้ที่ลงทะเบียน และการถอนจะถูกโอนไปยังผู้ใช้ตามจำนวนผู้ใช้ ( ดูรายละเอียดการวิเคราะห์โค้ด) ส่งผลให้การถือครองโทเค็น KEANU ลดลงอย่างต่อเนื่องในกลุ่ม Memestake และสุดท้ายคือ 1e-07 ดังแสดงในรูปด้านล่าง ธุรกรรมที่เกี่ยวข้องได้แก่
, ภาพหน้าจอของการทำธุรกรรมยังไม่เสร็จสมบูรณ์ โปรดคลิกลิงก์เพื่อดูด้วยตัวเองMfundขั้นตอนที่ 3 (กำไร) ผู้โจมตีเรียกฟังก์ชัน Memestake.updatePool() ก่อนผ่านสัญญา 2 และแก้ไข accMfundPerShare ของพูลที่ KEANU ตั้งอยู่ เนื่องจากค่านี้ขึ้นอยู่กับจำนวนของโทเค็น KEANU ที่ถือครองโดยพูล และนี่คือ ใน มันถูกจัดการในขั้นตอนที่สอง (ดูการวิเคราะห์รหัสด้านล่างสำหรับสูตรเฉพาะ) สิ่งนี้ทำให้สัญญา 2 ได้รับมากกว่ามูลค่าปกติในการถอนครั้งต่อไป0xa945(ประมาณ 61 ล้าน) โทเค็นนี้ใช้เป็นรางวัล ขั้นตอนที่ 3 เกิดขึ้นในการทำธุรกรรม
ในขณะเดียวกัน ผู้โจมตีก็เริ่มแลกเปลี่ยนส่วนหนึ่งของ MFund ที่ได้รับเป็นโทเค็น เช่น WETHTornado.Cashขั้นตอนที่ 4 (สิ้นสุด) ผู้โจมตีจะแลกเปลี่ยน MFund, KEANU และโทเค็นอื่น ๆ ที่ได้รับเป็น ETH และส่งผ่าน
โอนออกไป จนถึงตอนนี้การโจมตีสิ้นสุดลงแล้ว และผู้โจมตีได้กำไร 55.9484578158357 ETH (ที่อยู่ EOA ของผู้โจมตีและสัญญาการโจมตีที่ปรับใช้ยังคงมีโทเค็น SANSHU และ KEANU บางส่วนที่ไม่นับ) ประมาณ 100,000 ดอลลาร์สหรัฐ0x0333รูปต่อไปนี้แสดงที่อยู่การโจมตี
ภาพหน้าจอของการทำธุรกรรม ภาพหน้าจอของการทำธุรกรรมยังไม่สมบูรณ์ โปรดคลิกลิงก์ที่อยู่เพื่อดูรายละเอียด
เกี่ยวข้องกับการโจมตี
ที่น่าสนใจคือทั้งขั้นตอนที่ 2 และ 3 ของการโจมตีนั้นเกี่ยวข้องกับการทำธุรกรรมแฟลชบอท0x00edการทำธุรกรรมที่เกี่ยวข้องในขั้นตอนที่ 2
เนื่องจากการใช้ UniswapV2 flashloan และก่อนและหลังการทำธุรกรรม จึงเทียบเท่ากับการใช้ประมาณ 38ETH เพื่อซื้อ KEANU ซึ่งสร้างพื้นที่การเก็งกำไรขนาดใหญ่ ดังนั้น การทำธุรกรรมจึงถูกประกบโดยผู้โจมตีรายอื่น (การโจมตีแบบแซนวิช) กล่าวคือ ผู้โจมตีในเหตุการณ์นี้ก็ตกเป็นเหยื่อของเหตุการณ์แบบแซนวิชอีกเช่นกัน ผู้โจมตีแซนวิชทำกำไรได้ 3.2769697165652474ETH แต่ให้ผู้ขุด 2.405295771958891249ETH โดยมีกำไรสุทธิ 0.8716739446063562ETH0xa945ในขณะที่การทำธุรกรรมเกี่ยวข้องกับการโจมตีในขั้นตอนที่ 3
เนื่องจากมีการขาย MFunds จำนวนมากใน uniswap pool พื้นที่การเก็งกำไรจึงถูกสร้างขึ้น ดังนั้นมันจึงกลับมาทำงานและกลายเป็นธุรกรรม flashbots ผู้ค้นหาทำกำไรได้ 0.13858054192600666ETH ซึ่ง 0.099085087477094764ETH มอบให้กับนักขุด และกำไรสุทธิคือ 0.03949545444891189ETHคำแนะนำโดยละเอียดเกี่ยวกับแฟลชบอตและการโจมตีแบบแซนวิชสามารถพบได้ในบทแนะนำการโจมตีอื่นๆ ของเรา. เนื่องจากการนำ Flash Loan ไปใช้รวมกับ Swap ทั่วไปใน UniswapV2 โปรดดูเอกสารของเราสำหรับหลักการใช้งานที่เฉพาะเจาะจงและเหตุใดจึงมีพื้นที่การเก็งกำไรในขั้นตอนที่สองTowards A First Step to Understand Flash Loan and Its Applications in DeFi Ecosystem (SBC 2021).
0x3 สรุปและคำแนะนำด้านความปลอดภัย
0x3 สรุปและคำแนะนำด้านความปลอดภัย
ผู้โจมตีใช้ลักษณะของโทเค็นเงินฝืดเพื่อควบคุมจำนวนโทเค็นที่ถือครองโดยแพลตฟอร์ม ซึ่งส่งผลต่อการคำนวณและการกระจายโทเค็นรางวัล และทำให้ได้กำไร 55.9484578158357 ETH เหตุผลนี้คือแพลตฟอร์ม Sanshu Inu ขาดข้อพิจารณาด้านความปลอดภัยบางประการเมื่อแนะนำโทเค็นเงินฝืด ทำให้ผู้โจมตีสามารถใช้ประโยชน์จากมันได้
ดังนั้น คำแนะนำด้านความปลอดภัยของเราสำหรับฝ่ายโครงการที่เกี่ยวข้องมีดังนี้:
ก่อนที่โครงการจะเริ่มทำงาน จำเป็นต้องหาบริษัทรักษาความปลอดภัยที่มีคุณสมบัติเหมาะสมเพื่อทำการตรวจสอบความปลอดภัย เราจะเห็นว่าเนื่องจากแอตทริบิวต์เลโก้เงินของ defi สามารถรวมโครงการ defi จำนวนมากได้ตามต้องการ ซึ่งทำให้เกิดอิทธิพลร่วมกัน และนี่คือสาเหตุของเหตุการณ์ด้านความปลอดภัยที่เกิดขึ้นบ่อยครั้งในฟิลด์ defi ดังนั้น ประเด็นด้านความปลอดภัยที่ฝ่ายโครงการต้องให้ความสนใจไม่ได้จำกัดเฉพาะโครงการของตนเองเท่านั้น แต่ยังต้องพิจารณาถึงช่องโหว่ด้านความปลอดภัยที่มีอยู่ในกระบวนการโต้ตอบกับโครงการอื่นด้วย
ขับเคลื่อนด้วยเทคโนโลยีความปลอดภัยหลัก ทีมงานของ BlockSec ให้ความสำคัญกับความปลอดภัยของ DeFi การต่อต้านการฟอกเงินสกุลเงินดิจิทัล และการดูแลทรัพย์สินดิจิทัลบนพื้นฐานของการประมวลผลความเป็นส่วนตัว การให้บริการรักษาความปลอดภัยตามสัญญาและบริการรักษาความปลอดภัยสินทรัพย์ดิจิทัลสำหรับฝ่ายโครงการ DApp ทีมงานได้เผยแพร่เอกสารทางวิชาการด้านความปลอดภัยชั้นนำมากกว่า 20 ฉบับ (CCS, USENIX Security, S&P) และพันธมิตรของบริษัทได้รับรางวัลนักวิชาการด้านความปลอดภัยและความเป็นส่วนตัวที่มีอิทธิพลมากที่สุดในโลกของ AMiner (อันดับที่หกของโลกในปี 2554-2563) ผลการวิจัยได้รับรางวัลจาก CCTV, สำนักข่าว Xinhua News และรายงานของสื่อต่างประเทศ ค้นพบช่องโหว่ด้านความปลอดภัยและภัยคุกคาม DeFi จำนวนมากโดยอิสระ และได้รับรางวัลที่หนึ่งในโลกในการแข่งขันคอมพิวเตอร์เพื่อความเป็นส่วนตัวของสถาบันสุขภาพแห่งชาติ (SGX Track) ประจำปี 2562 ขับเคลื่อนด้วยเทคโนโลยี ทีมงานยึดมั่นในแนวคิดของการเปิดกว้างและ win-win และทำงานร่วมกับพันธมิตรในชุมชนเพื่อสร้างระบบนิเวศ DeFi ที่ปลอดภัย


