Sê-ri tấn công BlockSec DeFi thứ năm Giả mạo thực tế: Phân tích sự kiện tấn công nhóm huy động vốn từ cộng đồng DODO V2
BlockSec
2021-08-08 10:05
本文约6480字,阅读全文需要约26分钟
Bước vào khu rừng tăm tối của Ethereum, những kẻ tấn công và những kẻ buôn bán chênh lệch giá ẩn nấp ở khắp mọi nơi cũng phải sẵn sàng trở thành con mồi...

Tài chính phi tập trung (DeFi), với tư cách là một dạng dự án phổ biến trong hệ sinh thái chuỗi khối, tính bảo mật của nó đặc biệt quan trọng. Kể từ năm ngoái, hàng chục sự cố an ninh đã xảy ra.

Là một nhóm nghiên cứu dài hạn (https://blocksecteam.com) liên quan đến bảo mật DeFi, BlockSec đã độc lập phát hiện ra một số sự cố bảo mật DeFi và kết quả nghiên cứu đã được công bố trong các hội nghị bảo mật hàng đầu (bao gồm USENIX Security, CCS và Mũ đen). Trong thời gian tới, chúng tôi sẽ phân tích một cách có hệ thống các sự cố bảo mật DeFi và phân tích nguyên nhân gốc rễ đằng sau các sự cố bảo mật đó

Đánh giá trước đây:

(1) [Một trong loạt bài phân tích cuộc tấn công BlockSec DeFi] Tôi tự nói: Phân tích sự kiện tấn công ChainSwap

(2) [Chuỗi phân tích tấn công BlockSec DeFi 2] Cho đi mọi thứ: Phí Sushiswap bị đánh cắp

(3) [Chuỗi phân tích tấn công BlockSec DeFi 3] Đánh cắp bầu trời và thay đổi một ngày: Phân tích chuyên sâu về sự kiện tấn công Akropolis

tiêu đề cấp đầu tiên

0x0.Lời mở đầu

Vào rạng sáng ngày 9 tháng 3 năm 2021, giờ Bắc Kinh, một số nhóm huy động vốn từ cộng đồng V2 của DODO, một nền tảng giao dịch phi tập trung trên Ethereum, đã bị tấn công. Tuy nhiên, từ những phân tích sau đó, sự phát triển của vấn đề rõ ràng đã đi chệch hướng so với dự đoán của kẻ tấn công...

Nếu bạn là người mới sử dụng Ethereum và tình cờ thích đọc truyện, bạn có thể bắt đầu đọc từ 0x1 bên dưới. Nếu bạn thích phân tích tấn công đơn giản và trực tiếp, bạn có thể cuộn xuống 0x2 và bắt đầu đọc.

tiêu đề cấp đầu tiên

0x1. Đánh giá sự kiện

"Cuộc tấn công có thành công không? Nó thành công, nhưng không hoàn toàn." Đây có thể là miêu tả tâm lý của Xiao A khi đó

No code, no bug

tiêu đề phụ

Phân tích khái niệm 0x1.1

Nhóm gây quỹ cộng đồng DODO V2 đã được đề cập rất nhiều lần, vậy nó là gì? Nói một cách đơn giản, đó là một nhóm tiền, nhưng số tiền trong bài viết này không đề cập đến loại tiền pháp định mà chúng ta tiếp xúc hàng ngày, mà là các mã thông báo (mã thông báo ERC20) trên Ethereum. Khi loại nhóm quỹ này được khởi tạo, hai loại mã thông báo ERC20 có giá trị trên chuỗi sẽ được đặt làm cặp mã thông báo của nhóm này (hãy nhớ điểm này, chúng tôi sẽ kiểm tra sau) và sau đó người dùng có thể sử dụng các dịch vụ do các quỹ này cung cấp hồ bơi bình thường. Trong cuộc tấn công vào nhóm gây quỹ cộng đồng DODO V2 này, Little A đã sử dụng dịch vụ flashloan do nhóm cung cấp.

So với các khoản vay thông thường, flashloan có đặc điểm là vay một số tiền lớn mà không cần thế chấp và khôi phục trạng thái trước khi trả tiền. Nói một cách đơn giản, nó có thể trắng tay, nếu số tiền cho vay cuối cùng sau một lần hoạt động bị mất, bạn vẫn không thể bù đắp được cũng không sao, tất cả các trạng thái liên quan sẽ được khôi phục về trước khi cho vay, và cái thiệt duy nhất của người đi vay là ngoài thủ tục, ngoài phí thì có lẽ chỉ có thời gian. Logic của việc sử dụng các khoản vay chớp nhoáng cũng rất đơn giản, đó là người dùng vay tiền từ nhóm quỹ -> hoạt động trên số tiền đã vay -> trả lại tiền và những khoản này cần được hoàn thành trong một giao dịch.

Ok, sau khi tìm hiểu sơ qua về các khái niệm liên quan, chúng ta hãy xem hoạt động của Little A.

Hoạt động quyến rũ của 0x1.2 Xiao A

Bé A làm hai việc tiếp theo.

Điều đầu tiên là tạo hai hợp đồng mã thông báo ERC20. Nói thẳng ra, hai đồng tiền giả (vì chúng vô giá trị) được gọi là FDO và FUSDT. Sau khi tạo hai đồng tiền giả này, A sẽ gửi chúng vào nhóm Trong DODO sẽ bị tấn công.

Điều thứ hai Little A đã làm là sử dụng dịch vụ flashloan của quỹ huy động vốn từ cộng đồng DODO V2. Như đã đề cập ở trên, một phần logic của việc sử dụng các khoản vay chớp nhoáng là hoạt động dựa trên số tiền đã vay và nhân vật chính của bài viết này, Xiao A, đã giở trò đồi bại với liên kết này.

Little A nhận thấy rằng nhóm gây quỹ cộng đồng DODO V2 này có thể được khởi tạo lại một cách giả tạo và không có giới hạn. Sau đó, Little A đã khởi tạo lại nhóm sau khi cho vay tiền và cặp mã thông báo được đặt khi khởi tạo trở thành hai đồng tiền giả FDO/FUSDT do chính Little A tạo ra (đây là điểm thử nghiệm đã đề cập trước đây, hiện tại nó đã vượt qua thử nghiệm.) . Và Little A đã gửi trước một lượng đủ hai loại tiền giả vào nhóm này thông qua việc đầu tiên cậu ấy làm ở trên trước khi vay tiền, điều này khiến nhóm kiểm tra tình hình các khoản nợ của Little A, vì vậy Mã thông báo đã kiểm tra không còn nữa tiền thật trước đó, nhưng tiền giả do A gửi và số tiền là đủ. Bằng cách này, Little A đã sử dụng tiền giả để đặt ra tiền thật.

Chúng ta có thể thực hiện một sự tương tự đơn giản với quy trình trên và các chi tiết không được hiển thị. Có một ngân hàng, và ngân hàng này có thể được so sánh với nhóm quỹ được đề cập ở trên. Đồng thời, ngân hàng cũng có một sổ nhỏ để giữ tài khoản, nhưng trên trang chủ của sổ nhỏ có ghi [ngân hàng chỉ xử lý Nhân dân tệ, dự trữ là 100]. Đối với các loại tiền tệ khác, đô la Mỹ hoặc đồng Việt Nam. Người dùng cũng có thể gửi tiền vào đó, nhưng ngân hàng không quan tâm đến bạn, mặc dù nó sẽ giữ các tài khoản trong sổ nhỏ của nó, nhưng nó chỉ xem xét các bản ghi liên quan đến Nhân dân tệ khi kiểm tra.

Để tương tự vấn đề mà nhóm gây quỹ cộng đồng có thể được khởi tạo lại, nó có thể được hiểu theo cách này. Cuốn sổ nhỏ này có vấn đề, vấn đề là quy định trên trang chủ [ngân hàng chỉ xử lý Nhân dân tệ] được viết bằng bút chì, cuốn sổ nhỏ này được đặt ở cửa sổ, người ngoài có thể dùng tẩy và bút chì để thay đổi . Sau đó, vấn đề này đã được Little A phát hiện ra. Đầu tiên, cậu ấy gửi 100 đồng vào ngân hàng này và ngân hàng sẽ ghi lại [Little A gửi 100 đồng vào ngân hàng]. Sau đó, cô bé A đến ngân hàng để cho vay 100 Nhân dân tệ, và ngân hàng ghi lại [Tiểu A vay ngân hàng 100 Nhân dân tệ]. Lưu ý rằng ngân hàng sẽ kiểm tra việc vay và gửi Nhân dân tệ của tất cả người dùng và so sánh nó với số tiền dự trữ để xác nhận xem có người dùng nào đã vay Nhân dân tệ nhưng chưa hoàn trả hay không.

Vừa vay tiền xong, cậu bé A liền lấy bút chì và tẩy đã chuẩn bị sẵn, thay đổi quy định trên trang chủ của cuốn sổ nhỏ thành [Ngân hàng của chúng tôi chỉ xử lý đồng Việt Nam, với mức dự trữ là 100]. Sau đó, khi ngân hàng kiểm tra số tiền, do quy định đã thay đổi chỉ giao dịch bằng Đồng Việt Nam nên thấy số tiền Đồng Việt Nam dự trữ bằng với số tiền Đồng Việt Nam gửi của bé A, nghĩa là không ai nợ. tiền ngân hàng. Sau đó, Xiao A đã lấy Nhân dân tệ cho mượn và rời đi mà không nhìn lại.

Ý tưởng tấn công nhóm gây quỹ cộng đồng DODO V2 của Little A như đã đề cập ở trên, và việc tiếp theo Little A phải làm là biến ý tưởng của mình thành hành động thực tế. Cuộc tấn công mà bài viết này phân tích từ cấp độ mã hợp đồng là cuộc tấn công được đề cập ở trên, nhưng câu chuyện của chúng ta vẫn chưa kết thúc. Bạn nào không muốn đọc tiếp có thể kéo trực tiếp xuống phần phân tích tấn công của 0x2, còn các bác phán xét thì cho phép mình kể tiếp cho các bạn nghe.

0x1.3 Quá trình tấn công: Đường núi mười tám khúc cua

Lần 1. Bọ ngựa bắt ve, chim vàng anh đuổi theo

Hãy tiếp tục cuốn sách.

Bên dự án, tức là DODO, đã tạo nhiều nhóm có cùng logic và các nhóm này có cùng sơ hở. Nhóm mà Little A nhắm đến lần đầu tiên là nhóm (WSZO/USDT), WSZO và USDT là hai mã thông báo có giá trị (mã thông báo ERC20). Sau khi vui vẻ viết logic tấn công của mình vào một giao dịch, anh ta định nằm xuống và thu tiền, nhưng vào lúc này, đã xảy ra sự cố.

Chúng tôi biết rằng có một khoản phí giao dịch đối với các giao dịch trên Ethereum, do người dùng trả cho những người khai thác. Do đó, để tối đa hóa lợi ích của mình, các thợ mỏ sẽ kiểm tra phí giao dịch của từng giao dịch và sắp xếp chúng theo thứ tự khi họ đóng gói các giao dịch từ nhóm pending và chuẩn bị đưa vào chuỗi. chuỗi đầu tiên. Và vì cơ chế phi tập trung của Ethereum, luật rừng tối cũng được áp dụng ở đây. Những kẻ tấn công, chuyên gia chênh lệch giá hoặc những người chạy đầu tiên của các dự án DeFi (tài chính phi tập trung) đang ẩn nấp khắp nơi trên thế giới. Một khi chúng tìm thấy mục tiêu của mình, chúng sẽ tấn công chúng. Còn việc ai có thể thành công cuối cùng thì điều đó phụ thuộc vào việc ai trả phí giao dịch trong ngoài công nghệ và các yếu tố khác.

Trở lại với nhân vật chính, cậu bé A, cậu ta đã tìm ra sơ hở và định nhân cơ hội kiếm bộn tiền, nhưng hành động của cậu bé A đã bị một nhân vật khác—người máy vội vàng phát hiện, hãy gọi người máy vội vã này là Little B. Little B đã làm ầm lên về phí giao dịch, anh ấy đã tăng giá gas của giao dịch, do đó sẽ tăng phí giao dịch của giao dịch này. Điều này làm cho các công cụ khai thác đóng gói giao dịch của B nhỏ trước khi đóng gói giao dịch. Nói chung, loại hoạt động này của Little B được gọi là chạy trước. Khi đến lượt đóng gói giao dịch A nhỏ, WSZO và USDT trong nhóm WSZO/USDT trống rỗng, chỉ còn lại một đống vô giá trị (FDO/FUSDT).

Little A có thể đã nghĩ rằng thất bại lần này chỉ là một giao dịch chạy trước thông thường, vì vậy anh ta đã lặp lại mánh khóe cũ. Chỉ là lần này mục tiêu đã được thay đổi thành nhóm (ETHA/USDT) và để tránh bị cướp, Little A đã tăng giá gas của giao dịch trong giao dịch này. Nhưng điều bé A không biết là bé B đã trở thành mục tiêu của mình.

Với cùng một thói quen và cùng một phương pháp, bé A lại bị bé B cướp đi.

Lần thứ hai, Cheng Yaojin bị giết giữa chừng

Cho đến nay, Tiểu A đã may váy cưới cho Tiểu B trong hai lần tấn công, thậm chí còn tự mình mất phí giao dịch! Little A đã rất tức giận nên cậu ấy đã rút kinh nghiệm và đặt mục tiêu vào pool tiếp theo (wCRES/USDT). Và lần này bé A đã thành công vượt qua sự theo dõi của bé B. Mọi chuyện phát triển đến mức tưởng chừng như Tiểu A sắp thành công, nhưng thực tế là anh ấy thích đùa với Tiểu A.

Mặc dù cuộc tấn công thứ ba đã bỏ qua Little B, nhưng Little A đã không trực tiếp chuyển tiền đến địa chỉ của chính mình sau khi rút tiền thành công mà tạo một hợp đồng mới để nhận tiền. Ý tưởng của Little A là tạm thời cất giữ số tiền trong hợp đồng mới này trước, sau đó chuyển nó vào tài khoản của anh ấy. Tuy nhiên, có một lỗ hổng khác trong hợp đồng lưu trữ tạm thời số tiền bị đánh cắp của Little A, đó là bất kỳ ai cũng có thể rút (rút) số tiền trong hợp đồng từ hợp đồng này.

However, this contract had a loophole that allowed anyone to withdraw assets from it.

Tình cờ là lỗ hổng này đã bị phát hiện bởi một nhân vật khác (Little C). Do đó, khi Little A thực hiện một giao dịch để lấy lại số tiền đã bị đánh cắp từ hợp đồng này, cả hai người họ lại bị cướp, nhưng lần này người đi trước là Little C.

Thấy vậy, Little A vừa là kẻ tấn công, vừa là nạn nhân của một giao dịch chạy trước. Làn sóng này, nhỏ A có thể được coi là ăn cắp gà nhưng mất tiền.

Lần thứ 3. Bé A bướng bỉnh

Như đã đề cập trước đó, có nhiều nhóm có cùng lỗ hổng logic. Little A lại sẵn sàng tung ra đòn tấn công thứ 4. Lần này, mục tiêu được thay đổi thành pool (DODO/USDT). Lần này, bé A đã học được cách thông minh, một mặt thay thế hợp đồng tạm thời lưu trữ số tiền bị đánh cắp bằng một hợp đồng mới, mặt khác, bé A cũng kết hợp quy trình chuyển mã thông báo thành một giao dịch để tránh giao dịch thứ ba Trường hợp bị Little C cướp đi trong cuộc tấn công thứ hai. Nhưng lần này, Little A, người đã không va vào bức tường phía nam và không nhìn lại, cuối cùng đã thành công trong việc lấy tiền thật (DODO/USDT) bằng tiền giả (FDO/FUSDT).

Chương 4 điên cuồng cắn chính mình

Little A có hài lòng sau khi bốn cuộc tấn công cuối cùng thành công? Sự thật cho chúng ta biết câu trả lời là không.

Không biết tiểu A nghĩ như thế nào, có thể là trải qua tréo ngoe cuối cùng cũng thành công, cái này làm cho hắn quá kích động. Trong cuộc tấn công thứ năm này, mục tiêu của anh ta là pool (wCRES/USDT). Trông nó có quen không? Đúng rồi! Bể bơi này chính xác là bể mục tiêu của Tiểu A trong đợt tấn công thứ ba. Sau cuộc tấn công thứ ba, nhóm đã thay đổi từ nhóm (wCRES/USDT) thành nhóm (FDO/FUSDT), tức là nhóm tiền thật đã trở thành nhóm tiền giả. Vì vậy, trong đợt tấn công này, kết quả mà Tiểu A sử dụng cùng một thói quen tấn công thu được, chẳng qua là đổi tiền giả mới lấy tiền giả cũ...

Và hai đồng tiền giả này là do chính Xiao A làm ra. Có lẽ, Tiểu A vẫn là một người hoài niệm...

Câu chuyện về bé A của chúng ta cũng đến đây là hết. Có lẽ Ethereum là một khu rừng tối dành cho những kẻ tấn công và danh tính của thợ săn và con mồi không cố định trong đấu trường đặc biệt này. Hãy luôn nhớ rằng khi bạn nhìn vào vực thẳm, vực thẳm cũng nhìn vào bạn.

ok, bước tiếp theo là liên kết phân tích tấn công nghiêm trọng.

tiêu đề cấp đầu tiên

0x2.Phân tích tấn công

Để dễ hiểu, sau đây sẽ lấy cuộc tấn công thứ ba làm ví dụ để phân tích, và pool liên quan là (wCRES/USDT) pool

phân tích mã 0x2.1

Tất cả các chức năng được đề cập bên dưới đều lấy từ mã hợp đồng của nhóm quỹ (wCRES/USDT) và có liên quan đến cuộc tấn công này.

Hàm getVaultReserve 0x2.1.1

Đầu tiên hãy nhìn vào hàm getVaultReserve, chức năng của hàm này rất đơn giản, đó là khi người dùng gọi nó, nó sẽ trả về dự trữ của cặp token trong pool hiện tại.

Chức năng flashloan 0x2.1.2

Hình trên là chức năng flashloan của hợp đồng nhóm quỹ trong cuộc tấn công này. Có thể thấy khi người dùng gọi hàm này thì số lượng token tương ứng sẽ được chuyển đến địa chỉ được đại diện bởi tham số assetTo theo 2 tham số baseAmount và quoteAmount mà người dùng truyền vào. Đến đây thì link vay flashloan đã hoàn thành. Nhìn xuống mã, miễn là dữ liệu không trống, logic bên ngoài sẽ được kích hoạt. Và logic bên ngoài này được thực hiện bởi chính người gọi và việc thực hiện cuộc tấn công này chính xác là khi logic bên ngoài này được thực thi.

Hàm khởi tạo 0x2.1.3

Hình trên là hàm khởi tạo quan trọng nhất init trong cuộc tấn công này, có thể nhận thấy hàm này được gọi từ bên ngoài và điều quan trọng nhất là hàm này có 2 đặc điểm sau:

  • [Không yêu cầu quyền] Điều này có nghĩa là bất kỳ ai cũng có thể gọi chức năng này từ bên ngoài.

  • [Có thể được gọi nhiều lần] có nghĩa là hàm init có thể được gọi bất cứ lúc nào để khởi tạo lại nhóm ngoại trừ việc được gọi một lần khi nhóm được tạo.

Khi người gọi gọi hàm này, hai tham số baseTokenAddress và quoteTokenAddress được truyền vào sẽ được sử dụng để gán lại các biến _BASE_TOKEN_ và _QUOTE_TOKEN_ tương ứng. Và sự thay đổi của 2 biến này đồng nghĩa với việc cặp token của pool này cũng sẽ thay đổi theo. Và đây là lý do pool wCRES/USDT trở thành FDO/FUSDT.

Quá trình tấn công 0x2.2

Luồng của giao dịch tấn công được hiển thị trong hình bên dưới

[Sê-ri Tấn công DeFi BlockSec Phần 5] Kinh tởm sự thật: Phân tích sự kiện tấn công quỹ gây quỹ cộng đồng DODO V2

  • Phân tích luồng giao dịch có thể sử dụng các công cụ phân tích giao dịch của nhóm chúng tôi:https://tx.blocksecteam.com/

Step 0

  • Kẻ tấn công đầu tiên tạo ra 2 hợp đồng token ERC20 (FDO và FUSDT), có thể hiểu đơn giản là tạo ra 2 token giả mạo (vô giá trị). Và đã chuyển một số lượng lớn hai mã thông báo này đến địa chỉ của chính nó (0x368a6), mở đường cho các cuộc tấn công tiếp theo.

    [Sê-ri Tấn công DeFi BlockSec Phần 5] Kinh tởm sự thật: Phân tích sự kiện tấn công quỹ gây quỹ cộng đồng DODO V2

Step 1

  • Kẻ tấn công gọi hàm getVaultReserve của hợp đồng nhóm quỹ để lấy dự trữ hiện tại của wCRES và USDT trong nhóm để chuẩn bị cho cuộc tấn công tiếp theo.

Step 2

  • Theo dự trữ thu được ở Bước 1, kẻ tấn công gọi chức năng transferFrom của hai hợp đồng tiền giả để chuyển tiền giả (FDO và FUSDT) nhiều hơn một chút so với dự trữ sang hợp đồng nhóm quỹ (DLP), để đảm bảo rằng kiểm tra số dư của chức năng flashloan có thể vượt qua.

Step 3

  • Sau đó, kẻ tấn công gọi chức năng flashloan của hợp đồng nhóm quỹ (DLP) để cho vay tiền thật (wCRES và USDT) ít hơn một chút so với dự trữ nhóm quỹ.

Step 4

  • Sau khi chức năng flashloan chuyển wCRES và USDT đến địa chỉ hợp đồng do kẻ tấn công đặt trước, nó sẽ tự động gọi logic bên ngoài của kẻ tấn công. Kẻ tấn công đã gọi hàm khởi tạo init của nhóm wCRES/USDT trong quá trình triển khai logic bên ngoài và thay thế cặp mã thông báo của nhóm bằng FDO/FUSDT.

    [Sê-ri Tấn công DeFi BlockSec Phần 5] Kinh tởm sự thật: Phân tích sự kiện tấn công quỹ gây quỹ cộng đồng DODO V2

Step 5

  • Như hình bên dưới, sau khi chức năng flashloan thực thi logic bên ngoài, nó sẽ kiểm tra số dư mã thông báo (token) của pool hiện tại. Nhưng cần lưu ý rằng vì cặp mã thông báo của nhóm được thay thế bằng FDO/FUSDT, nên số dư được biểu thị bằng baseBalance và quoteBalance cũng là số dư của FDO và FUSDT.

  • Đồng thời, vì kẻ tấn công làStep 2 tiêu đề cấp đầu tiên

0x3. Tóm tắt và đề xuất bảo mật

Lý do chính cho cuộc tấn công này là chức năng init của nhóm gây quỹ cộng đồng DODO V2. Nhìn vào cách gọi của chức năng này, có thể thấy rằng logic thông thường phải là chức năng này chỉ có thể được gọi một lần khi nhóm được tạo lần đầu tiên, sau đó quyền truy cập phải được đặt và không thể gọi nó nhiều lần. Kẻ tấn công đã lợi dụng lỗ hổng có thể gọi hàm init nhiều lần để khởi tạo lại pool, kết hợp với flashloan để rút tiền thật trong pool bằng tiền giả, như vậy đã hoàn thành cuộc tấn công.

Do đó, đề xuất của chúng tôi cho các bên liên quan của dự án như sau:

  • Làm tốt công tác rà soát thẩm quyền đối với các chức năng chính của hợp đồng dự án, để tránh tổn thất do sử dụng sai các chức năng cốt lõi do yêu cầu thẩm quyền thấp.

  • tiêu đề cấp đầu tiên

0x4.Tham khảo

tiêu đề phụ

Các địa chỉ bên ngoài và địa chỉ hợp đồng liên quan đến bài báo

Các giao dịch được đề cập trong bài viết này

cuộc tấn công đầu tiên

cuộc tấn công thứ hai

cuộc tấn công thứ ba

cuộc tấn công thứ tư

cuộc tấn công thứ năm

BlockSec
作者文库