[Hóng hớt hacking #3] Lỗ hổng của Vyper, Curve bị hack $59M

TH13🇻🇳
3 min readAug 1, 2023

--

Vào ngày 30/07/2023 cả cộng đồng blockchain chấn động với việc Vyper programing language có lỗ hổng và nạn nhân bị hack là Curve với tổng thiệt hại là hơn $59M.

What?

Vyper là ngôn ngữ lập trình được dùng để code smart contract tương thích với EVM blockchain giống như Solidity . Vyper được lấy cảm hứng từ Python nên syntax của nó cũng giống, việc này làm cho dev tiếp cận và học sẽ dễ.

Curve là giao thức DeFi trên các blockchain (chủ yếu là ETH), cung cấp thanh khoản cho giao dịch trao đổi giữa các stablecoin và token. Curve pool là tính năng chính, cho phép người dùng gửi tài sản vào pool và thực hiện giao dịchvới giá tốt nhất trong pool.

How?

Cuộc tấn công diễn ra trên các chain mà Curve deploy contract (bên lề là những dự án folk từ Curve cũng bị tấn công). Kết quả Curve thiệt hại hơn $59M trên những pool sử dụng phiên bản Vyper lỗi và thêm điều kiện là pool chứa ETH. Một số pool bị tấn công:

  • CRV/ETH pool
  • alETH/ETH pool
  • msETH/ETH pool
  • pETH/ETH pool

Theo Curve thì hiện tại có 1 pool có khả năng bị khai thác ở trên Arbitrum nhưng theo tui thì nó tạm thời safe vì pool này đang dùng WETH (khác biệt là không có raw_call để có thể reentrancy khai thác lỗ hổng. Tốt nhất user nên remove hết liquidity cho an toàn.

Trong transaction attack, attacker đã thực hiện gọi add_liquidity và rồi sau đó remove_liquidity, lợi dụng lúc remove thì pool sẽ gửi ETH cho attacker (chưa update hết state), lúc này y sẽ control logic và reentrancy vào pool để thực hiện add_liquidity một lần nữa. Do chưa update state trước đó nên khi add giữa chừng thì tính toán sai có lợi cho attacker.

1 ví dụ transaction attack

Câu hỏi đặt ra: Tại sao đã có decorator nonreentrancy bảo vệ của vyper nhưng vẫn có thể reentracy?

Why?

Curve được phát triển trên Vyper và bên trong compiler của Vyper những version cũ tồn tại lỗ hổng mà không được công bố (có lẽ dev chỉ nghĩ là fix bug bình thường).

commit xuất hiện lỗ hổng

Lỗ hổng xuất hiện từ commit của version 0.2.15 cho đến 0.3.0. Nguyên nhân của lỗ hổng có thể được tóm gọn như sau:

  • Trong lúc compiler vyper biên dịch thì nó sẽ đi tìm nonreentrancy decorator nếu có ở mỗi function (giống như modifier của solidity) để lưu key vào storage slot. Theo logic thông thường thì khi mình call function thì vm sẽ truy cập vào slot này set key true để không thể call function nào có decorator này nữa cho đến khi function thực hiện xong.
  • Nhưng thật nực cười compiler khi mỗi lần nó lưu storage slot thì increase slot +1 mà không check rằng key của nonreentrancy đã được lưu trước đó. Điều này làm cho mỗi function có nonreentrancy decorator độc lập không có trùng slot nhau gây ra hậu quả là không giúp contract bảo vệ được reentrancy
fixed commit

Affected Vyper version:

  • 0.2.15
  • 0.2.16
  • 0.3.0

Conclusion

Hãy luôn cập nhật những update đến từ tech stack mà mình sử dụng. Vendor thì hãy luôn alert cho user biết những bản release của mình để user nhanh chóng migrate tránh những vụ hack không đáng có.

Stay strong!!!

Web3 security luôn nhanh chóng phản ứng với thông tin mới nhất!!!

--

--