เมื่อวันที่ 8 ธันวาคม 2023 OpenZeppelin ได้เผยแพร่การแจ้งเตือนด้านความปลอดภัยที่สำคัญแก่ชุมชนอย่างเป็นทางการ การแจ้งเตือนชี้ให้เห็นว่าเมื่อใช้มาตรฐาน ERC-2771 กับวิธีการคล้าย Multicall ในการบูรณาการโครงการ อาจมีความเสี่ยงที่จะถูกโจมตีด้วยการปลอมแปลงที่อยู่ตามอำเภอใจ
SharkTeam ดำเนินการวิเคราะห์ทางเทคนิคของเหตุการณ์นี้ทันทีและสรุปข้อควรระวังด้านความปลอดภัย เราหวังว่าโครงการต่อ ๆ ไปจะสามารถเรียนรู้จากสิ่งนี้และร่วมกันสร้างแนวป้องกันความปลอดภัยสำหรับอุตสาหกรรมบล็อกเชน
1. การวิเคราะห์ธุรกรรมการโจมตี
เนื่องจากมีธุรกรรมการโจมตีหลายรายการที่เกี่ยวข้องกับช่องโหว่นี้ เราจึงเลือกธุรกรรมการโจมตีรายการใดรายการหนึ่งเพื่อการวิเคราะห์
ที่อยู่ของผู้โจมตี:
0xFDe0d1575Ed8E06FBf36256bcdfA1F359281455A
ธุรกรรมการโจมตี:
0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6
กระบวนการโจมตี:
1. อันดับแรก. ผู้โจมตี (0xFDe0d157) ใช้ 5 WETH เป็นครั้งแรกเพื่อแลกเป็นประมาณ 3, 455, 399, 346 TIME
2. ต่อจากนั้น ผู้โจมตี (0xFDe0d157) ได้สร้างพารามิเตอร์ calldata ที่เป็นอันตราย และเรียกฟังก์ชัน [Forwarder].execute
3. เมื่อเรียกใช้ฟังก์ชัน [Forwarder].execute calldata ที่เป็นอันตรายจะทริกเกอร์ฟังก์ชัน multicall ของสัญญา TIME ต่อจากนั้น ข้อมูลการโทรที่เหลือจะถูกนำมาใช้เพื่อทริกเกอร์ฟังก์ชันเบิร์นของสัญญา TIME เพื่อทำลายโทเค็น TIME ในพูล
2. การวิเคราะห์ช่องโหว่
ก่อนอื่น การโจมตีนี้เกี่ยวข้องกับหลายแง่มุมเป็นหลัก: ERC 2771, การโทรหลายสาย และข้อมูลการโทรที่สร้างขึ้นอย่างระมัดระวัง เราสามารถค้นหาการสืบทอดที่เกี่ยวข้องได้จากสัญญาโทเค็น TIME:
1. ERC 2771 มอบความสามารถในการมี msg.sender เสมือน ช่วยให้ผู้ใช้สามารถมอบหมายให้บุคคลที่สาม [Forwarder] ทำธุรกรรมเพื่อลดต้นทุนค่าน้ำมัน เมื่อมีการส่งธุรกรรม ที่อยู่ msg.sender จะถูกเพิ่มลงใน calldata
สัญญาโทเค็น 2.TIME สืบทอด ERC2771Context เมื่อ [Forwarder] เรียกสัญญา _msgSender() จะตรวจสอบข้อมูลการโทรและเลื่อนไปทางขวา โดยตัดทอน 20 ไบต์สุดท้ายตาม msg.sender ที่คาดไว้
3.Multicall เป็นวิธีการที่แปลงการเรียกใช้ฟังก์ชันเดียวเป็นหลายฟังก์ชันที่เรียกว่าตามลำดับในสัญญาเดียวกัน ยอมรับอาร์เรย์ของการโทรที่ผู้ใช้เข้ารหัสและดำเนินการตามสัญญาของตัวเอง ฟังก์ชันนี้จะวนซ้ำผ่านอาร์เรย์การโทรและดำเนินการ delegatecall() ในแต่ละการดำเนินการ ช่วยให้ผู้ใช้สามารถรวมชุดการดำเนินการของตนเองและดำเนินการตามลำดับในธุรกรรมเดียวกัน โดยไม่ต้องกำหนดชุดการดำเนินการบางอย่างในโปรโตคอลล่วงหน้า วัตถุประสงค์หลักคือเพื่อประหยัดน้ำมัน
4. สำหรับ calldata ที่สร้างขึ้นอย่างระมัดระวัง ผู้โจมตีจะเรียกใช้ฟังก์ชัน [Forwarder].execute และส่งผ่านพารามิเตอร์ที่เกี่ยวข้อง
เราจัดรูปแบบค่าข้อมูลตามลำดับในลักษณะที่อ่านได้และได้รับ:
ผู้โจมตี (0x FDe 0 d 157) รับค่าข้อมูลใหม่ผ่านการดำเนินการออฟเซ็ตของ calldata ปัจจุบัน และส่งค่าไปยังฟังก์ชัน multicall (bytes []) ข้อมูลใหม่ 4 ไบต์แรกคือตัวเลือกของฟังก์ชันเบิร์น (uint 256) และพารามิเตอร์จำนวนคือ 62227259510000000000000000000
5. ในฟังก์ชัน multicall(bytes[]) ให้เรียกใช้ฟังก์ชัน burn (uint 256) ผ่านทาง delegatecall ในบรรทัด 0x 20 ที่อยู่ 0x760dc1e043d99394a10605b2fa08f123d60faf84 จะถูกเพิ่มในตอนท้ายเมื่อสร้าง calldata ที่อยู่นี้สอดคล้องกับกลุ่มสภาพคล่อง TIME-ETH บน Uniswap v2 ซึ่งเป็น msg.sender ที่คาดไว้ข้างต้น
6. เหตุใด msg.sender ที่กล่าวถึงตอนนี้จึงกลายเป็นที่อยู่พูลสภาพคล่องของ TIME-ETH เหตุผลก็คือ msg.sender เป็นที่อยู่สัญญา [Forwarder] ในตอนต้น เพื่อตรวจสอบว่าเป็น [Forwarder ที่เชื่อถือได้หรือไม่ หากเป็น [Forwarder ที่เชื่อถือได้] ให้ตั้งค่า msg.sender เป็น 20 ไบต์สุดท้ายของ calldata
3. คำแนะนำด้านความปลอดภัย
สาเหตุของการโจมตีนี้: ใน ERC-2771 [Forwarder] ไม่ได้ออกแบบมาสำหรับการโทรหลายสาย ผู้โจมตีเพิ่มพารามิเตอร์ที่เกี่ยวข้องในฟังก์ชัน _msgSender() ให้กับการโทรภายนอกของ multicall ซึ่งก็คือฟังก์ชัน [Forwarder].execute ของเหตุการณ์นี้ ในฟังก์ชัน multicall บางฟังก์ชันจะเพิ่มพารามิเตอร์ที่เกี่ยวข้องใน _msgSender() อีกด้วย ทำให้ผู้โจมตีสามารถปลอมแปลง _msgSender() ได้ ดังนั้น ผู้โจมตีสามารถเลียนแบบการเรียกไปยังที่อยู่ที่กำหนดเองได้ โดยใช้การเรียกหลายสายเพื่อเรียกฟังก์ชันที่เกี่ยวข้อง ในที่สุด โทเค็น TIME ในพูลจะถูกทำลายผ่านการอนุญาต
เพื่อตอบสนองต่อเหตุการณ์นี้ สามารถใช้มาตรการบรรเทาและป้องกันดังต่อไปนี้:
1. ใช้เวอร์ชันใหม่หลังจากแก้ไขข้อบกพร่อง Multicall เวอร์ชันใหม่ของ OpenZeppelin มีความยาวส่วนต่อท้ายบริบทของข้อมูลบริบท ERC 277 1 ซึ่งใช้เพื่อระบุความยาวส่วนต่อท้ายบริบทที่คาดหวังของ ERC-2771 ดังนั้นการโทรใดๆ จาก [Forwarder] ที่เชื่อถือได้จะได้รับการยอมรับและปรับให้เข้ากับการเรียกใช้ฟังก์ชันย่อยแต่ละครั้ง
ต่อไปนี้เป็นแผนภูมิเปรียบเทียบระหว่างเวอร์ชันข้อบกพร่องและเวอร์ชันที่อัปเดต:
2. ห้ามสัญญาใด ๆ ที่จะเรียก multicall เพื่อป้องกันไม่ให้ [Forwarder] ใช้งาน ยกตัวอย่าง ThirdWeb วิธีนี้เปรียบเทียบกับโซลูชันของ OpenZeppelin OpenZeppelin ยังคงอนุญาตให้ multicall ผ่านสัญญา ต่อไปนี้เป็นแผนภูมิเปรียบเทียบเวอร์ชันข้อบกพร่องที่เกี่ยวข้องของ ThirdWeb และเวอร์ชันที่อัปเดต
About Us
วิสัยทัศน์ของ SharkTeam คือการรักษาความปลอดภัยให้กับโลกของ Web3 ทีมงานประกอบด้วยผู้เชี่ยวชาญด้านความปลอดภัยที่มีประสบการณ์และนักวิจัยอาวุโสจากทั่วโลก ซึ่งมีความเชี่ยวชาญในทฤษฎีพื้นฐานของบล็อคเชนและสัญญาอัจฉริยะ ให้บริการต่างๆ เช่น การวิเคราะห์บิ๊กดาต้าบนเชน คำเตือนความเสี่ยงบนเชน การตรวจสอบสัญญาอัจฉริยะ การกู้คืนสินทรัพย์ crypto และบริการอื่น ๆ และได้สร้างการวิเคราะห์บิ๊กดาต้าบนเชนและแพลตฟอร์มเตือนความเสี่ยง ChainAegis แพลตฟอร์มดังกล่าวรองรับระดับของ การวิเคราะห์กราฟเชิงลึกและสามารถต่อสู้กับ Advanced Persistent Threat (APT) ในโลก Web3 ได้อย่างมีประสิทธิภาพ ได้สร้างความสัมพันธ์ความร่วมมือระยะยาวกับผู้เล่นหลักในด้านต่างๆ ของระบบนิเวศ Web3 เช่น Polkadot, Moonbeam, polygon, Sui, OKX, imToken, ChainIDE เป็นต้น
เว็บไซต์อย่างเป็นทางการ:https://www.sharkteam.org
Twitter:https://twitter.com/sharkteamorg