คำเตือนความเสี่ยง: ระวังความเสี่ยงจากการระดมทุนที่ผิดกฎหมายในนาม 'สกุลเงินเสมือน' 'บล็อกเชน' — จากห้าหน่วยงานรวมถึงคณะกรรมการกำกับดูแลการธนาคารและการประกันภัย
ข่าวสาร
ค้นพบ
ค้นหา
เข้าสู่ระบบ
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt
BTC
ETH
HTX
SOL
BNB
ดูตลาด
หมอกช้า: การวิเคราะห์กระบวนการทั้งหมดของ Lendf.Me ที่ถูกขโมยและคำแนะนำในการป้องกัน
慢雾科技
特邀专栏作者
2020-04-19 09:23
บทความนี้มีประมาณ 2480 คำ การอ่านทั้งหมดใช้เวลาประมาณ 4 นาที
จากการวิเคราะห์ทางสถิติเบื้องต้นของระบบต่อต้านการฟอกเงิน (AML) ของ SlowMist การสูญเสียสะสมของ Lendf.Me

หมายเหตุบรรณาธิการ: บทความนี้มาจากเทคโนโลยีหมอกช้า (ID: SlowMist)หมายเหตุบรรณาธิการ: บทความนี้มาจาก

เทคโนโลยีหมอกช้า (ID: SlowMist)

พิมพ์ซ้ำโดยได้รับอนุญาตจาก Odaily

WETH: 55159.02134,
WBTC: 9.01152,
CHAI: 77930.93433,
HBTC: 320.27714,
HUSD: 432162.90569,
BUSD: 480787.88767,
PAX: 587014.60367,
TUSD: 459794.38763,
USDC: 698916.40348,
USDT: 7180525.08156,
USDx: 510868.16067,
imBTC: 291.3471

จากการวิเคราะห์ทางสถิติเบื้องต้นของระบบต่อต้านการฟอกเงิน (AML) ของ SlowMist การสูญเสียสะสมของ Lendf.Me ที่ถูกโจมตีอยู่ที่ประมาณ 24,696,616 ดอลลาร์สหรัฐ สกุลเงินและจำนวนเงินที่ถูกขโมยมีดังนี้:

ต่อไปนี้คือขั้นตอนการวิเคราะห์โดยละเอียด:

รายละเอียดการโจมตี

ชื่อเรื่องรอง

รายละเอียดการโจมตี

ที่อยู่ของผู้โจมตีที่โจมตี Lendf.Me ในครั้งนี้คือ 0xa9bf70a420d364e923c74448d9d817d3f2a77822 และผู้โจมตีโจมตี Lendf.Me โดยใช้สัญญา 0x538359785a8d5ab1a741a0ba94f26a800759d91d

โดยดูหนึ่งในธุรกรรมของผู้โจมตีบน Etherscan: https://etherscan.io/tx/0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b

เราพบว่าผู้โจมตีฝากเงิน 0.00021593 imBTC เป็นครั้งแรก แต่ประสบความสำเร็จในการถอน 0.00043188 imBTC จาก Lendf.Me และจำนวนเงินที่ถอนออกไปเกือบสองเท่าของจำนวนที่ฝาก แล้วผู้โจมตีได้รับยอดเงินเป็นสองเท่าจากธุรกรรมระยะสั้นได้อย่างไร สิ่งนี้ทำให้เราต้องวิเคราะห์การกระทำแต่ละอย่างอย่างลึกซึ้งในการทำธุรกรรมเพื่อดูว่าเกิดอะไรขึ้น

เมื่อดูธุรกรรมบน bloxy.info เราสามารถรู้ขั้นตอนการทำธุรกรรมทั้งหมดได้

ทันทีหลังจากนั้น ในระหว่างการเรียกใช้ฟังก์ชัน supply() ครั้งที่สอง ผู้โจมตีจะเริ่มการเรียกใช้ฟังก์ชันการถอนเงิน() ของ Lendf.Me ในสัญญาของเขาเอง และถอนเงินสดออกในที่สุด

ที่นี่ เราสามารถพบได้อย่างง่ายดายว่าการเรียกใช้การถอน () ของผู้โจมตีเกิดขึ้นในฟังก์ชัน TransferFrom นั่นคือเมื่อ Lendf.Me เรียกฟังก์ชัน hook ของผู้ใช้โทเค็น ToSend() ผ่านการถ่ายโอนจาก เห็นได้ชัดว่าผู้โจมตีได้ป้อนสัญญา Lendf.Me อีกครั้งผ่านฟังก์ชัน supply() ทำให้เกิดการโจมตีซ้ำ ดังนั้นรายละเอียดเฉพาะของการโจมตีคืออะไร มาติดตามรหัสสัญญาของ Lendf.Me กันต่อไป

ชื่อเรื่องรอง

การวิเคราะห์รหัส

หลังจากการประมวลผลชุดหนึ่ง ฟังก์ชัน supply() ของ Lendf.Me จะเรียกใช้ฟังก์ชัน doTransferIn เพื่อฝากสกุลเงินที่ผู้ใช้ให้ไว้ในสัญญา จากนั้นจึงกำหนดข้อมูลบางอย่างของตัวแปรตลาด เมื่อมองย้อนกลับไปที่ขั้นตอนการโจมตีที่กล่าวมา ผู้โจมตีเรียกฟังก์ชันการถอน () เพื่อถอนเงินสดผ่าน reentrancy ในฟังก์ชันอุปทานที่สอง () กล่าวคือในฟังก์ชันอุปทานที่สอง () หลังจากบรรทัด 1590 การดำเนินการจะไม่ ดำเนินการก่อนการถอน () และรหัสหลังบรรทัด 1590 จะดำเนินการต่อไปหลังจากดำเนินการถอน () การดำเนินการที่นี่นำไปสู่การเพิ่มยอดเงินที่ถอนได้ของผู้โจมตี

ลองวิเคราะห์ฟังก์ชัน supply() ในเชิงลึก:

จากรูปด้านบน เราจะเห็นว่าในตอนท้ายของฟังก์ชัน supply() ยอดคงเหลือของตลาดและผู้ใช้จะได้รับการอัปเดต ก่อนหน้านั้น ยอดคงเหลือของผู้ใช้จะได้รับล่วงหน้าเมื่อเริ่มต้นฟังก์ชันและ บันทึกไว้ใน localResults.userSupplyCurrent ดังนี้:

โดยการกำหนดค่าให้กับตัวแปร localResults ข้อมูลการถ่ายโอนของผู้ใช้จะถูกเก็บไว้ชั่วคราวในตัวแปรนี้ก่อน จากนั้น ผู้โจมตีจึงเรียกใช้ฟังก์ชันการถอน () ในเวลานี้ มาดูโค้ดของฟังก์ชันการถอน () กัน:

มีสองประเด็นสำคัญที่นี่:

1. ที่จุดเริ่มต้นของฟังก์ชัน สัญญาจะได้รับตลาดสตอเรจและตัวแปร supplyBalance ก่อน

ตามตรรกะการถอนปกติ เมื่อดำเนินการถอน () เพียงอย่างเดียว ยอดคงเหลือของผู้ใช้จะถูกหักและอัปเดตตามปกติ แต่เนื่องจากผู้โจมตีฝังการถอน () ไว้ในอุปทาน () ยอดคงเหลือของผู้ใช้จึงอัปเดตในฟังก์ชันการถอน () หลังจาก ยอดคงเหลือ (supplyBalance) รหัสถัดไปที่จะดำเนินการในฟังก์ชัน supply() นั่นคือหลังจากบรรทัด 1590 ยอดคงเหลือของผู้ใช้จะได้รับการอัปเดตอีกครั้ง และค่าที่ใช้สำหรับการอัปเดตจะถูกบันทึกไว้ที่จุดเริ่มต้นของค่าก่อนหน้า ฟังก์ชัน supply() เงินฝากดั้งเดิมของผู้ใช้ใน localResults บวกค่าการเรียกครั้งแรกของผู้โจมตีไปยังฟังก์ชัน supply()

ภายใต้การดำเนินการดังกล่าว แม้ว่ายอดคงเหลือของผู้ใช้จะถูกหักหลังจากการถอนออก ตรรกะของฟังก์ชัน supply() ถัดไปจะเขียนทับค่าเมื่อผู้ใช้ไม่ได้หักจำนวนเงินที่ถอนออกอีกครั้ง ทำให้ผู้โจมตีดำเนินการถอนเงิน แต่ แทนที่จะหักยอดกลับทำให้ยอดเพิ่มขึ้น ด้วยวิธีนี้ ผู้โจมตีสามารถถอนเงินสดเป็นจำนวนเท่าทวีคูณจนกว่า Lendf.Me จะว่างเปล่า

เมื่อมีการเชื่อมต่อหลายสัญญา จำเป็นต้องตรวจสอบความปลอดภัยของรหัสและความปลอดภัยทางธุรกิจของสัญญาหลายฝ่าย และพิจารณาประเด็นด้านความปลอดภัยอย่างเต็มที่ภายใต้การรวมกันของสถานการณ์ทางธุรกิจต่างๆ

  • เพิ่มกลไกการล็อคให้กับวิธีการดำเนินธุรกิจที่สำคัญ เช่น: ReentrancyGuard ของ OpenZeppelin

  • เมื่อพัฒนาสัญญา ให้ใช้รูปแบบการเขียนของการเปลี่ยนแปลงตัวแปรของสัญญานี้ก่อน แล้วจึงทำการเรียกภายนอก

  • ก่อนที่โครงการจะออนไลน์ ทีมรักษาความปลอดภัยบุคคลที่สามที่ยอดเยี่ยมจะได้รับเชิญให้ดำเนินการตรวจสอบความปลอดภัยอย่างครอบคลุมเพื่อค้นหาปัญหาด้านความปลอดภัยที่อาจเกิดขึ้นให้ได้มากที่สุด

  • เมื่อมีการเชื่อมต่อหลายสัญญา จำเป็นต้องตรวจสอบความปลอดภัยของรหัสและความปลอดภัยทางธุรกิจของสัญญาหลายฝ่าย และพิจารณาประเด็นด้านความปลอดภัยอย่างเต็มที่ภายใต้การรวมกันของสถานการณ์ทางธุรกิจต่างๆ

  • สัญญาควรตั้งค่าสวิตช์หยุดชั่วคราวให้มากที่สุดเท่าที่จะเป็นไปได้ เพื่อตรวจจับและหยุดการขาดทุนในเวลาที่เกิดเหตุการณ์ "หงส์ดำ"

  • การรักษาความปลอดภัยเป็นแบบไดนามิก และแต่ละฝ่ายในโครงการจำเป็นต้องจับภาพข่าวกรองภัยคุกคามที่อาจเกี่ยวข้องกับโครงการของตนเองอย่างทันท่วงที และตรวจสอบความเสี่ยงด้านความปลอดภัยที่อาจเกิดขึ้นโดยทันที

สัญญาควรตั้งค่าสวิตช์หยุดชั่วคราวให้มากที่สุดเท่าที่จะเป็นไปได้ เพื่อตรวจจับและหยุดการขาดทุนในเวลาที่เกิดเหตุการณ์ "หงส์ดำ"

OpenZeppelin ReentrancyGuard

安全
ยินดีต้อนรับเข้าร่วมชุมชนทางการของ Odaily
กลุ่มสมาชิก
https://t.me/Odaily_News
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
บัญชีทางการ
https://twitter.com/OdailyChina
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
สรุปโดย AI
กลับไปด้านบน
จากการวิเคราะห์ทางสถิติเบื้องต้นของระบบต่อต้านการฟอกเงิน (AML) ของ SlowMist การสูญเสียสะสมของ Lendf.Me
ดาวน์โหลดแอพ Odaily พลาเน็ตเดลี่
ให้คนบางกลุ่มเข้าใจ Web3.0 ก่อน
IOS
Android