Tại sao nói rằng Hook là một "con dao hai lưỡi" của Uniswap V4?
Uniswap v4 dự kiến sẽ ra mắt trong thời gian tới. Lần này, đội ngũ Uniswap đã đặt ra những mục tiêu lớn lao, dự định giới thiệu nhiều tính năng hoàn toàn mới, bao gồm hỗ trợ số lượng vô hạn các bể thanh khoản cho mỗi cặp giao dịch và phí động, thiết kế đơn thể, kế toán chớp nhoáng, Hook, và hỗ trợ tiêu chuẩn token ERC1155. Với việc sử dụng lưu trữ tạm thời, Uniswap v4 dự kiến sẽ được phát hành sau khi nâng cấp Ethereum Cancun.
Trong số nhiều đổi mới, cơ chế Hook đã thu hút sự chú ý rộng rãi nhờ tiềm năng mạnh mẽ của nó. Nó hỗ trợ thực hiện mã cụ thể tại những điểm nhất định trong vòng đời của bể thanh khoản, nâng cao đáng kể khả năng mở rộng và tính linh hoạt của bể.
Tuy nhiên, cơ chế Hook cũng có thể là một con dao hai lưỡi. Mặc dù mạnh mẽ và linh hoạt, nhưng việc sử dụng Hook một cách an toàn cũng là một thách thức không nhỏ. Sự phức tạp của Hook không thể tránh khỏi việc mang lại những vectơ tấn công tiềm ẩn mới. Do đó, chúng tôi hy vọng thông qua một loạt bài viết, sẽ giới thiệu hệ thống về các vấn đề an toàn và rủi ro tiềm ẩn liên quan đến cơ chế Hook, nhằm thúc đẩy sự phát triển an toàn của cộng đồng, và tin rằng những hiểu biết này sẽ giúp xây dựng một Hook an toàn cho Uniswap v4.
Là tác phẩm mở đầu cho loạt bài viết này, bài viết này giới thiệu các khái niệm liên quan đến cơ chế Hook trong Uniswap v4 và tóm tắt các rủi ro an ninh mà cơ chế Hook có thể gặp phải.
Cơ chế của Uniswap V4
Trước khi đi sâu vào thảo luận, chúng ta cần có một hiểu biết cơ bản về cơ chế của Uniswap v4. Hook, kiến trúc đơn thể và kế toán chớp nhoáng là ba chức năng quan trọng để thực hiện các pool thanh khoản tùy chỉnh và tối ưu hóa định tuyến qua nhiều pool.
1.1 Ghim
Hook đề cập đến các hợp đồng hoạt động ở các giai đoạn khác nhau của vòng đời của các quỹ thanh khoản. Nhóm Uniswap mong muốn thông qua việc giới thiệu Hook, bất kỳ ai cũng có thể đưa ra quyết định cân bằng. Bằng cách này, có thể hỗ trợ gốc các khoản phí động, thêm lệnh giới hạn trên chuỗi, hoặc thông qua việc làm thị trường trung bình theo trọng số theo thời gian (TWAMM) phân tán các đơn hàng lớn.
Hiện tại có tám Hook callback, được chia thành bốn nhóm (mỗi nhóm bao gồm một cặp callback):
trướcKhởiTạo/sauKhởiTạo
trướcModifyPosition/sauModifyPosition
trướcHoán/ sauHoán
trướcDonate/sauDonate
1.2 Mô hình đơn, ghi sổ chớp nhoáng và cơ chế khóa
Kiến trúc đơn thể và ghi sổ chớp nhoáng nhằm tăng hiệu suất bằng cách giảm chi phí và đảm bảo hiệu quả. Nó giới thiệu một hợp đồng singleton mới, trong đó tất cả các pool thanh khoản đều được lưu trữ trong cùng một hợp đồng thông minh. Thiết kế đơn thể này phụ thuộc vào một PoolManager để lưu trữ và quản lý trạng thái của tất cả các pool.
Trong phiên bản đầu tiên của giao thức Uniswap, các thao tác như trao đổi hoặc thêm thanh khoản liên quan đến việc chuyển token trực tiếp, phiên bản v4 thì khác, ở chỗ nó đã giới thiệu cơ chế kế toán chớp nhoáng và khóa.
Cách thức hoạt động của cơ chế khóa như sau:
Một hợp đồng locker yêu cầu khóa trên PoolManager.
PoolManager sẽ thêm địa chỉ của hợp đồng locker vào hàng đợi lockData và gọi lại lockAcquired.
Hợp đồng locker thực hiện logic của nó trong callback. Trong quá trình thực hiện, sự tương tác giữa hợp đồng locker và pool có thể dẫn đến sự gia tăng tiền tệ không bằng 0. Tuy nhiên, khi kết thúc thực hiện, tất cả các gia tăng phải được thanh toán về 0. Ngoài ra, nếu hàng đợi lockData không rỗng, chỉ có hợp đồng locker cuối cùng mới có thể thực hiện thao tác.
PoolManager kiểm tra trạng thái của hàng đợi lockData và sự gia tăng tiền tệ. Sau khi xác thực, PoolManager sẽ xóa hợp đồng locker đó.
Tóm lại, cơ chế khóa ngăn chặn truy cập đồng thời và đảm bảo rằng tất cả các giao dịch đều có thể được thanh lý. Hợp đồng locker yêu cầu khóa theo thứ tự, sau đó thực hiện giao dịch thông qua callback lockAcquired. Trước và sau mỗi hoạt động trong pool sẽ kích hoạt callback Hook tương ứng. Cuối cùng, PoolManager sẽ kiểm tra trạng thái.
Phương pháp này có nghĩa là việc điều chỉnh hoạt động là số dư ròng nội bộ, thay vì thực hiện chuyển khoản ngay lập tức. Bất kỳ sự thay đổi nào sẽ được ghi lại trong số dư nội bộ của bể, trong khi chuyển khoản thực tế sẽ được thực hiện khi kết thúc hoạt động. Quy trình này đảm bảo không có mã thông báo nào chưa được thanh toán, từ đó duy trì tính toàn vẹn của quỹ.
Do sự tồn tại của cơ chế khóa, tất cả các tài khoản bên ngoài (EOA) không thể tương tác trực tiếp với PoolManager. Thay vào đó, mọi tương tác phải thông qua một hợp đồng. Hợp đồng này hoạt động như một khóa trung gian, cần yêu cầu khóa trước khi thực hiện bất kỳ thao tác nào với hồ.
Có hai tình huống tương tác hợp đồng chính:
Một hợp đồng locker nào đó đến từ kho mã chính thức hoặc được triển khai bởi người dùng. Trong trường hợp này, chúng ta có thể coi việc tương tác là thông qua bộ định tuyến.
Một hợp đồng locker nào đó được tích hợp vào cùng một hợp đồng với Hook, hoặc được điều khiển bởi một thực thể bên thứ ba. Trong trường hợp này, chúng ta có thể coi tương tác là thông qua Hook. Trong trường hợp này, Hook vừa đóng vai trò của hợp đồng locker, vừa chịu trách nhiệm xử lý callback.
Mô hình đe dọa
Trước khi thảo luận về các vấn đề an ninh liên quan, chúng ta cần xác định mô hình đe dọa. Chúng ta chủ yếu xem xét hai tình huống sau:
Mô hình đe dọa I: Hook bản thân là vô hại, nhưng có lỗ hổng.
Mô hình đe dọa II: Hook bản thân nó là độc hại.
Trong phần tiếp theo, chúng tôi sẽ thảo luận về các vấn đề bảo mật tiềm ẩn dựa trên hai mô hình đe dọa này.
2.1 Các vấn đề an ninh trong mô hình đe dọa I
Mô hình đe dọa I tập trung vào các lỗ hổng liên quan đến Hook chính nó. Mô hình đe dọa này giả định rằng nhà phát triển và Hook của họ không có ác ý. Tuy nhiên, các lỗ hổng đã biết hiện có trong hợp đồng thông minh cũng có thể xuất hiện trong Hook. Ví dụ, nếu Hook được triển khai như một hợp đồng có thể nâng cấp, thì nó có thể gặp phải các vấn đề liên quan tương tự như lỗ hổng UUPSUpgradeable của OpenZeppelin.
Xem xét các yếu tố trên, chúng tôi chọn tập trung vào các lỗ hổng tiềm ẩn đặc trưng của phiên bản v4. Trong Uniswap v4, Hook là một hợp đồng thông minh có khả năng thực hiện logic tùy chỉnh trước hoặc sau khi thực hiện các thao tác trong hồ bơi cốt lõi (bao gồm khởi tạo, sửa đổi vị trí, trao đổi và thu thập). Mặc dù Hook dự kiến sẽ thực hiện các giao diện tiêu chuẩn, nhưng nó cũng cho phép bao gồm logic tùy chỉnh. Do đó, phạm vi thảo luận của chúng tôi sẽ được giới hạn trong các logic liên quan đến giao diện Hook tiêu chuẩn. Sau đó, chúng tôi sẽ cố gắng xác định các nguồn gốc có thể của các lỗ hổng, chẳng hạn như Hook có thể lạm dụng các hàm Hook tiêu chuẩn này như thế nào.
Cụ thể, chúng ta sẽ tập trung vào hai loại Hook sau:
Loại hook đầu tiên, giữ tiền của người dùng. Trong trường hợp này, kẻ tấn công có thể tấn công hook này để chuyển tiền, gây ra tổn thất tài sản.
Loại hook thứ hai, lưu trữ dữ liệu trạng thái quan trọng mà người dùng hoặc các giao thức khác phụ thuộc vào. Trong trường hợp này, kẻ tấn công có thể cố gắng thay đổi trạng thái quan trọng. Khi người dùng khác hoặc các giao thức sử dụng trạng thái sai, có thể mang lại rủi ro tiềm tàng.
Xin lưu ý rằng các hook ngoài hai phạm vi này không nằm trong chủ đề thảo luận của chúng tôi.
Tổng thể, chúng tôi đã phát hiện 22 dự án liên quan (loại trừ các dự án không liên quan đến Uniswap v4). Trong số các dự án này, chúng tôi cho rằng có 8 dự án (36%) có lỗ hổng. Trong 8 dự án có lỗ hổng này, 6 dự án gặp vấn đề về kiểm soát truy cập, 2 dự án dễ bị tấn công từ các cuộc gọi bên ngoài không đáng tin cậy.
2.1.1 Vấn đề kiểm soát truy cập
Trong phần thảo luận này, chúng tôi chủ yếu tập trung vào các vấn đề có thể phát sinh từ các hàm callback trong v4, bao gồm 8 callback hook và callback lock. Tất nhiên, còn có những trường hợp khác cần xác minh, nhưng những trường hợp này khác nhau về thiết kế, nên không nằm trong phạm vi thảo luận của chúng tôi.
Các hàm này chỉ nên được gọi bởi PoolManager, không nên được gọi bởi các địa chỉ khác (bao gồm cả EOA và hợp đồng). Ví dụ, trong trường hợp phần thưởng được phân phát bởi khóa quỹ, nếu các hàm tương ứng có thể được bất kỳ tài khoản nào gọi, thì phần thưởng có thể bị nhận sai.
Do đó, đối với hook, việc thiết lập một cơ chế kiểm soát truy cập mạnh mẽ là vô cùng quan trọng, đặc biệt là khi chúng có thể được gọi bởi các bên khác ngoài chính bể. Bằng cách quản lý quyền truy cập một cách chặt chẽ, bể thanh khoản có thể giảm đáng kể rủi ro liên quan đến việc tương tác không được phép hoặc tương tác độc hại với hook.
2.1.2 Vấn đề xác thực đầu vào
Trong Uniswap v4, do có cơ chế khóa, người dùng phải nhận được một lock thông qua hợp đồng trước khi thực hiện bất kỳ thao tác nào trên pool. Điều này đảm bảo rằng hợp đồng hiện tại tham gia tương tác là hợp đồng locker mới nhất.
Mặc dù vậy, vẫn tồn tại một kịch bản tấn công có thể xảy ra, đó là các cuộc gọi bên ngoài không đáng tin cậy do việc xác thực đầu vào không đúng cách trong một số triển khai Hook dễ bị tấn công:
Đầu tiên, hook không xác thực quỹ mà người dùng dự định tương tác. Đây có thể là một quỹ độc hại chứa token giả mạo và thực hiện logic có hại.
Thứ hai, một số hàm hook quan trọng cho phép các cuộc gọi từ bên ngoài.
Các cuộc gọi bên ngoài không đáng tin cậy cực kỳ nguy hiểm, vì chúng có thể dẫn đến nhiều loại tấn công khác nhau, bao gồm cả tấn công tái nhập mà chúng ta đã biết.
Để tấn công các hook dễ bị tổn thương này, kẻ tấn công có thể đăng ký một bể tiền độc hại cho token giả của mình, sau đó gọi hook để thực hiện các thao tác trong bể tiền. Khi tương tác với bể tiền, logic token độc hại chiếm lấy luồng điều khiển để thực hiện các hành vi xấu.
2.1.3 Biện pháp phòng ngừa đối với mô hình đe dọa I
Để tránh các vấn đề bảo mật liên quan đến hook, việc thực hiện kiểm soát truy cập cần thiết đối với các hàm nhạy cảm bên ngoài/công cộng và xác thực các tham số đầu vào để xác thực các tương tác là rất quan trọng. Ngoài ra, bảo vệ chống tái nhập có thể giúp đảm bảo rằng hook không bị thực thi lại trong quy trình logic tiêu chuẩn. Bằng cách thực hiện các biện pháp bảo vệ an toàn thích hợp, quỹ có thể giảm thiểu rủi ro liên quan đến các mối đe dọa như vậy.
2.2 Vấn đề an ninh trong mô hình đe dọa II
Trong mô hình đe dọa này, chúng tôi giả định rằng nhà phát triển và hook của họ là độc hại. Do phạm vi liên quan rất rộng, chúng tôi chỉ tập trung vào các vấn đề an ninh liên quan đến phiên bản v4. Do đó, điều quan trọng là hook được cung cấp có thể xử lý việc chuyển tiền hoặc ủy quyền tài sản mã hóa của người dùng hay không.
Do phương pháp truy cập hook quyết định quyền hạn có thể được cấp cho hook, chúng tôi chia hook thành hai loại:
Hook ủy thác: hook không phải là điểm vào. Người dùng phải tương tác với hook thông qua router (có thể được Uniswap cung cấp).
Hook độc lập: hook là điểm vào, cho phép người dùng tương tác trực tiếp.
2.2.1 Hook lưu ký
Trong trường hợp này, tài sản tiền điện tử của người dùng (bao gồm token gốc và các token khác) được chuyển nhượng hoặc ủy quyền cho router. Do PoolManager thực hiện kiểm tra số dư, hook độc hại khó có thể trực tiếp đánh cắp những tài sản này. Tuy nhiên, vẫn tồn tại các bề mặt tấn công tiềm ẩn. Ví dụ, cơ chế quản lý phí của phiên bản v4 có thể bị kẻ tấn công thao túng thông qua hook.
2.2.2 Hook độc lập
Khi Hook được sử dụng như một điểm vào, tình huống trở nên phức tạp hơn. Trong trường hợp này, vì người dùng có thể tương tác trực tiếp với hook, hook đã có được nhiều quyền lực hơn. Về lý thuyết, hook có thể thực hiện bất kỳ thao tác nào mong muốn thông qua sự tương tác này.
Trong phiên bản v4, việc xác minh logic mã là rất quan trọng. Vấn đề chính là liệu có thể thao túng logic mã hay không. Nếu hook có thể nâng cấp, điều này có nghĩa là một hook có vẻ an toàn có thể trở nên độc hại sau khi nâng cấp, từ đó tạo ra rủi ro lớn. Những rủi ro này bao gồm:
Đại lý có thể nâng cấp (có thể bị tấn công trực tiếp);
Có logic tự hủy. Có thể bị tấn công trong trường hợp gọi đồng thời selfdestruct và create2.
2.2.3 Biện pháp phòng ngừa cho mô hình đe dọa II
Điều quan trọng là đánh giá xem hook có phải là độc hại hay không. Cụ thể, đối với hook được quản lý, chúng ta nên chú ý đến hành vi quản lý chi phí; trong khi đối với hook độc lập, điểm chú ý chính là liệu chúng có thể nâng cấp hay không.
Kết luận
Trong bài viết này, chúng tôi sẽ tóm tắt ngắn gọn các cơ chế cốt lõi liên quan đến vấn đề an toàn của Hook trong Uniswap v4. Sau đó, chúng tôi sẽ trình bày hai mô hình đe dọa và tóm tắt ngắn gọn các rủi ro an toàn liên quan.
Trong các bài viết tiếp theo, chúng tôi sẽ phân tích từng mô hình đe dọa.
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
Phân tích rủi ro an toàn của cơ chế Hook Uniswap v4
Tại sao nói rằng Hook là một "con dao hai lưỡi" của Uniswap V4?
Uniswap v4 dự kiến sẽ ra mắt trong thời gian tới. Lần này, đội ngũ Uniswap đã đặt ra những mục tiêu lớn lao, dự định giới thiệu nhiều tính năng hoàn toàn mới, bao gồm hỗ trợ số lượng vô hạn các bể thanh khoản cho mỗi cặp giao dịch và phí động, thiết kế đơn thể, kế toán chớp nhoáng, Hook, và hỗ trợ tiêu chuẩn token ERC1155. Với việc sử dụng lưu trữ tạm thời, Uniswap v4 dự kiến sẽ được phát hành sau khi nâng cấp Ethereum Cancun.
Trong số nhiều đổi mới, cơ chế Hook đã thu hút sự chú ý rộng rãi nhờ tiềm năng mạnh mẽ của nó. Nó hỗ trợ thực hiện mã cụ thể tại những điểm nhất định trong vòng đời của bể thanh khoản, nâng cao đáng kể khả năng mở rộng và tính linh hoạt của bể.
Tuy nhiên, cơ chế Hook cũng có thể là một con dao hai lưỡi. Mặc dù mạnh mẽ và linh hoạt, nhưng việc sử dụng Hook một cách an toàn cũng là một thách thức không nhỏ. Sự phức tạp của Hook không thể tránh khỏi việc mang lại những vectơ tấn công tiềm ẩn mới. Do đó, chúng tôi hy vọng thông qua một loạt bài viết, sẽ giới thiệu hệ thống về các vấn đề an toàn và rủi ro tiềm ẩn liên quan đến cơ chế Hook, nhằm thúc đẩy sự phát triển an toàn của cộng đồng, và tin rằng những hiểu biết này sẽ giúp xây dựng một Hook an toàn cho Uniswap v4.
Là tác phẩm mở đầu cho loạt bài viết này, bài viết này giới thiệu các khái niệm liên quan đến cơ chế Hook trong Uniswap v4 và tóm tắt các rủi ro an ninh mà cơ chế Hook có thể gặp phải.
Cơ chế của Uniswap V4
Trước khi đi sâu vào thảo luận, chúng ta cần có một hiểu biết cơ bản về cơ chế của Uniswap v4. Hook, kiến trúc đơn thể và kế toán chớp nhoáng là ba chức năng quan trọng để thực hiện các pool thanh khoản tùy chỉnh và tối ưu hóa định tuyến qua nhiều pool.
1.1 Ghim
Hook đề cập đến các hợp đồng hoạt động ở các giai đoạn khác nhau của vòng đời của các quỹ thanh khoản. Nhóm Uniswap mong muốn thông qua việc giới thiệu Hook, bất kỳ ai cũng có thể đưa ra quyết định cân bằng. Bằng cách này, có thể hỗ trợ gốc các khoản phí động, thêm lệnh giới hạn trên chuỗi, hoặc thông qua việc làm thị trường trung bình theo trọng số theo thời gian (TWAMM) phân tán các đơn hàng lớn.
Hiện tại có tám Hook callback, được chia thành bốn nhóm (mỗi nhóm bao gồm một cặp callback):
trướcKhởiTạo/sauKhởiTạo
trướcModifyPosition/sauModifyPosition
trướcHoán/ sauHoán
trướcDonate/sauDonate
1.2 Mô hình đơn, ghi sổ chớp nhoáng và cơ chế khóa
Kiến trúc đơn thể và ghi sổ chớp nhoáng nhằm tăng hiệu suất bằng cách giảm chi phí và đảm bảo hiệu quả. Nó giới thiệu một hợp đồng singleton mới, trong đó tất cả các pool thanh khoản đều được lưu trữ trong cùng một hợp đồng thông minh. Thiết kế đơn thể này phụ thuộc vào một PoolManager để lưu trữ và quản lý trạng thái của tất cả các pool.
Trong phiên bản đầu tiên của giao thức Uniswap, các thao tác như trao đổi hoặc thêm thanh khoản liên quan đến việc chuyển token trực tiếp, phiên bản v4 thì khác, ở chỗ nó đã giới thiệu cơ chế kế toán chớp nhoáng và khóa.
Cách thức hoạt động của cơ chế khóa như sau:
Một hợp đồng locker yêu cầu khóa trên PoolManager.
PoolManager sẽ thêm địa chỉ của hợp đồng locker vào hàng đợi lockData và gọi lại lockAcquired.
Hợp đồng locker thực hiện logic của nó trong callback. Trong quá trình thực hiện, sự tương tác giữa hợp đồng locker và pool có thể dẫn đến sự gia tăng tiền tệ không bằng 0. Tuy nhiên, khi kết thúc thực hiện, tất cả các gia tăng phải được thanh toán về 0. Ngoài ra, nếu hàng đợi lockData không rỗng, chỉ có hợp đồng locker cuối cùng mới có thể thực hiện thao tác.
PoolManager kiểm tra trạng thái của hàng đợi lockData và sự gia tăng tiền tệ. Sau khi xác thực, PoolManager sẽ xóa hợp đồng locker đó.
Tóm lại, cơ chế khóa ngăn chặn truy cập đồng thời và đảm bảo rằng tất cả các giao dịch đều có thể được thanh lý. Hợp đồng locker yêu cầu khóa theo thứ tự, sau đó thực hiện giao dịch thông qua callback lockAcquired. Trước và sau mỗi hoạt động trong pool sẽ kích hoạt callback Hook tương ứng. Cuối cùng, PoolManager sẽ kiểm tra trạng thái.
Phương pháp này có nghĩa là việc điều chỉnh hoạt động là số dư ròng nội bộ, thay vì thực hiện chuyển khoản ngay lập tức. Bất kỳ sự thay đổi nào sẽ được ghi lại trong số dư nội bộ của bể, trong khi chuyển khoản thực tế sẽ được thực hiện khi kết thúc hoạt động. Quy trình này đảm bảo không có mã thông báo nào chưa được thanh toán, từ đó duy trì tính toàn vẹn của quỹ.
Do sự tồn tại của cơ chế khóa, tất cả các tài khoản bên ngoài (EOA) không thể tương tác trực tiếp với PoolManager. Thay vào đó, mọi tương tác phải thông qua một hợp đồng. Hợp đồng này hoạt động như một khóa trung gian, cần yêu cầu khóa trước khi thực hiện bất kỳ thao tác nào với hồ.
Có hai tình huống tương tác hợp đồng chính:
Một hợp đồng locker nào đó đến từ kho mã chính thức hoặc được triển khai bởi người dùng. Trong trường hợp này, chúng ta có thể coi việc tương tác là thông qua bộ định tuyến.
Một hợp đồng locker nào đó được tích hợp vào cùng một hợp đồng với Hook, hoặc được điều khiển bởi một thực thể bên thứ ba. Trong trường hợp này, chúng ta có thể coi tương tác là thông qua Hook. Trong trường hợp này, Hook vừa đóng vai trò của hợp đồng locker, vừa chịu trách nhiệm xử lý callback.
Mô hình đe dọa
Trước khi thảo luận về các vấn đề an ninh liên quan, chúng ta cần xác định mô hình đe dọa. Chúng ta chủ yếu xem xét hai tình huống sau:
Mô hình đe dọa I: Hook bản thân là vô hại, nhưng có lỗ hổng.
Mô hình đe dọa II: Hook bản thân nó là độc hại.
Trong phần tiếp theo, chúng tôi sẽ thảo luận về các vấn đề bảo mật tiềm ẩn dựa trên hai mô hình đe dọa này.
2.1 Các vấn đề an ninh trong mô hình đe dọa I
Mô hình đe dọa I tập trung vào các lỗ hổng liên quan đến Hook chính nó. Mô hình đe dọa này giả định rằng nhà phát triển và Hook của họ không có ác ý. Tuy nhiên, các lỗ hổng đã biết hiện có trong hợp đồng thông minh cũng có thể xuất hiện trong Hook. Ví dụ, nếu Hook được triển khai như một hợp đồng có thể nâng cấp, thì nó có thể gặp phải các vấn đề liên quan tương tự như lỗ hổng UUPSUpgradeable của OpenZeppelin.
Xem xét các yếu tố trên, chúng tôi chọn tập trung vào các lỗ hổng tiềm ẩn đặc trưng của phiên bản v4. Trong Uniswap v4, Hook là một hợp đồng thông minh có khả năng thực hiện logic tùy chỉnh trước hoặc sau khi thực hiện các thao tác trong hồ bơi cốt lõi (bao gồm khởi tạo, sửa đổi vị trí, trao đổi và thu thập). Mặc dù Hook dự kiến sẽ thực hiện các giao diện tiêu chuẩn, nhưng nó cũng cho phép bao gồm logic tùy chỉnh. Do đó, phạm vi thảo luận của chúng tôi sẽ được giới hạn trong các logic liên quan đến giao diện Hook tiêu chuẩn. Sau đó, chúng tôi sẽ cố gắng xác định các nguồn gốc có thể của các lỗ hổng, chẳng hạn như Hook có thể lạm dụng các hàm Hook tiêu chuẩn này như thế nào.
Cụ thể, chúng ta sẽ tập trung vào hai loại Hook sau:
Loại hook đầu tiên, giữ tiền của người dùng. Trong trường hợp này, kẻ tấn công có thể tấn công hook này để chuyển tiền, gây ra tổn thất tài sản.
Loại hook thứ hai, lưu trữ dữ liệu trạng thái quan trọng mà người dùng hoặc các giao thức khác phụ thuộc vào. Trong trường hợp này, kẻ tấn công có thể cố gắng thay đổi trạng thái quan trọng. Khi người dùng khác hoặc các giao thức sử dụng trạng thái sai, có thể mang lại rủi ro tiềm tàng.
Xin lưu ý rằng các hook ngoài hai phạm vi này không nằm trong chủ đề thảo luận của chúng tôi.
Tổng thể, chúng tôi đã phát hiện 22 dự án liên quan (loại trừ các dự án không liên quan đến Uniswap v4). Trong số các dự án này, chúng tôi cho rằng có 8 dự án (36%) có lỗ hổng. Trong 8 dự án có lỗ hổng này, 6 dự án gặp vấn đề về kiểm soát truy cập, 2 dự án dễ bị tấn công từ các cuộc gọi bên ngoài không đáng tin cậy.
2.1.1 Vấn đề kiểm soát truy cập
Trong phần thảo luận này, chúng tôi chủ yếu tập trung vào các vấn đề có thể phát sinh từ các hàm callback trong v4, bao gồm 8 callback hook và callback lock. Tất nhiên, còn có những trường hợp khác cần xác minh, nhưng những trường hợp này khác nhau về thiết kế, nên không nằm trong phạm vi thảo luận của chúng tôi.
Các hàm này chỉ nên được gọi bởi PoolManager, không nên được gọi bởi các địa chỉ khác (bao gồm cả EOA và hợp đồng). Ví dụ, trong trường hợp phần thưởng được phân phát bởi khóa quỹ, nếu các hàm tương ứng có thể được bất kỳ tài khoản nào gọi, thì phần thưởng có thể bị nhận sai.
Do đó, đối với hook, việc thiết lập một cơ chế kiểm soát truy cập mạnh mẽ là vô cùng quan trọng, đặc biệt là khi chúng có thể được gọi bởi các bên khác ngoài chính bể. Bằng cách quản lý quyền truy cập một cách chặt chẽ, bể thanh khoản có thể giảm đáng kể rủi ro liên quan đến việc tương tác không được phép hoặc tương tác độc hại với hook.
2.1.2 Vấn đề xác thực đầu vào
Trong Uniswap v4, do có cơ chế khóa, người dùng phải nhận được một lock thông qua hợp đồng trước khi thực hiện bất kỳ thao tác nào trên pool. Điều này đảm bảo rằng hợp đồng hiện tại tham gia tương tác là hợp đồng locker mới nhất.
Mặc dù vậy, vẫn tồn tại một kịch bản tấn công có thể xảy ra, đó là các cuộc gọi bên ngoài không đáng tin cậy do việc xác thực đầu vào không đúng cách trong một số triển khai Hook dễ bị tấn công:
Đầu tiên, hook không xác thực quỹ mà người dùng dự định tương tác. Đây có thể là một quỹ độc hại chứa token giả mạo và thực hiện logic có hại.
Thứ hai, một số hàm hook quan trọng cho phép các cuộc gọi từ bên ngoài.
Các cuộc gọi bên ngoài không đáng tin cậy cực kỳ nguy hiểm, vì chúng có thể dẫn đến nhiều loại tấn công khác nhau, bao gồm cả tấn công tái nhập mà chúng ta đã biết.
Để tấn công các hook dễ bị tổn thương này, kẻ tấn công có thể đăng ký một bể tiền độc hại cho token giả của mình, sau đó gọi hook để thực hiện các thao tác trong bể tiền. Khi tương tác với bể tiền, logic token độc hại chiếm lấy luồng điều khiển để thực hiện các hành vi xấu.
2.1.3 Biện pháp phòng ngừa đối với mô hình đe dọa I
Để tránh các vấn đề bảo mật liên quan đến hook, việc thực hiện kiểm soát truy cập cần thiết đối với các hàm nhạy cảm bên ngoài/công cộng và xác thực các tham số đầu vào để xác thực các tương tác là rất quan trọng. Ngoài ra, bảo vệ chống tái nhập có thể giúp đảm bảo rằng hook không bị thực thi lại trong quy trình logic tiêu chuẩn. Bằng cách thực hiện các biện pháp bảo vệ an toàn thích hợp, quỹ có thể giảm thiểu rủi ro liên quan đến các mối đe dọa như vậy.
2.2 Vấn đề an ninh trong mô hình đe dọa II
Trong mô hình đe dọa này, chúng tôi giả định rằng nhà phát triển và hook của họ là độc hại. Do phạm vi liên quan rất rộng, chúng tôi chỉ tập trung vào các vấn đề an ninh liên quan đến phiên bản v4. Do đó, điều quan trọng là hook được cung cấp có thể xử lý việc chuyển tiền hoặc ủy quyền tài sản mã hóa của người dùng hay không.
Do phương pháp truy cập hook quyết định quyền hạn có thể được cấp cho hook, chúng tôi chia hook thành hai loại:
Hook ủy thác: hook không phải là điểm vào. Người dùng phải tương tác với hook thông qua router (có thể được Uniswap cung cấp).
Hook độc lập: hook là điểm vào, cho phép người dùng tương tác trực tiếp.
2.2.1 Hook lưu ký
Trong trường hợp này, tài sản tiền điện tử của người dùng (bao gồm token gốc và các token khác) được chuyển nhượng hoặc ủy quyền cho router. Do PoolManager thực hiện kiểm tra số dư, hook độc hại khó có thể trực tiếp đánh cắp những tài sản này. Tuy nhiên, vẫn tồn tại các bề mặt tấn công tiềm ẩn. Ví dụ, cơ chế quản lý phí của phiên bản v4 có thể bị kẻ tấn công thao túng thông qua hook.
2.2.2 Hook độc lập
Khi Hook được sử dụng như một điểm vào, tình huống trở nên phức tạp hơn. Trong trường hợp này, vì người dùng có thể tương tác trực tiếp với hook, hook đã có được nhiều quyền lực hơn. Về lý thuyết, hook có thể thực hiện bất kỳ thao tác nào mong muốn thông qua sự tương tác này.
Trong phiên bản v4, việc xác minh logic mã là rất quan trọng. Vấn đề chính là liệu có thể thao túng logic mã hay không. Nếu hook có thể nâng cấp, điều này có nghĩa là một hook có vẻ an toàn có thể trở nên độc hại sau khi nâng cấp, từ đó tạo ra rủi ro lớn. Những rủi ro này bao gồm:
Đại lý có thể nâng cấp (có thể bị tấn công trực tiếp);
Có logic tự hủy. Có thể bị tấn công trong trường hợp gọi đồng thời selfdestruct và create2.
2.2.3 Biện pháp phòng ngừa cho mô hình đe dọa II
Điều quan trọng là đánh giá xem hook có phải là độc hại hay không. Cụ thể, đối với hook được quản lý, chúng ta nên chú ý đến hành vi quản lý chi phí; trong khi đối với hook độc lập, điểm chú ý chính là liệu chúng có thể nâng cấp hay không.
Kết luận
Trong bài viết này, chúng tôi sẽ tóm tắt ngắn gọn các cơ chế cốt lõi liên quan đến vấn đề an toàn của Hook trong Uniswap v4. Sau đó, chúng tôi sẽ trình bày hai mô hình đe dọa và tóm tắt ngắn gọn các rủi ro an toàn liên quan.
Trong các bài viết tiếp theo, chúng tôi sẽ phân tích từng mô hình đe dọa.