Phân tích sâu về lỗ hổng an ninh trong ngôn ngữ Move
Gần đây, khi chúng tôi nghiên cứu sâu về Aptos Moveevm, chúng tôi đã phát hiện ra một lỗ hổng tràn số nguyên mới. Quy trình kích hoạt lỗ hổng này khá thú vị, dưới đây chúng tôi sẽ tiến hành phân tích sâu và giới thiệu kiến thức nền tảng liên quan đến ngôn ngữ Move. Thông qua bài viết này, chúng tôi tin rằng độc giả sẽ có được hiểu biết sâu sắc hơn về ngôn ngữ Move.
Ngôn ngữ Move sẽ thực hiện xác minh đơn vị mã trước khi thực thi bytecode, quá trình này được chia thành 4 bước. Lỗ hổng được thảo luận trong bài viết này xuất hiện trong bước reference_safety.
Mô-đun reference_safety định nghĩa hàm chuyển giao được sử dụng để xác minh tính an toàn của các tham chiếu trong quá trình thực hiện. Nó chủ yếu kiểm tra xem có tồn tại tham chiếu treo, việc truy cập vào tham chiếu có thể thay đổi có an toàn hay không, và việc truy cập vào tham chiếu lưu trữ toàn cục có an toàn hay không.
Quá trình xác thực bắt đầu từ hàm nhập xác thực an toàn, hàm này sẽ gọi analyze_function. Trong analyze_function, mỗi khối cơ bản sẽ được xác thực. Khối cơ bản là một chuỗi mã, không có lệnh nhánh ngoại trừ điểm vào và điểm ra.
Ngôn ngữ Move xác định các khối cơ bản bằng cách duyệt mã byte, tìm tất cả các chỉ thị nhánh và chuỗi chỉ thị vòng lặp. Một ví dụ điển hình về khối mã IR Move có thể chứa 3 khối cơ bản, được xác định bởi các chỉ thị BrTrue, Branch và Ret.
Ngôn ngữ Move hỗ trợ hai loại tham chiếu: tham chiếu không thay đổi (&) và tham chiếu thay đổi (&mut). Tham chiếu không thay đổi được sử dụng để đọc dữ liệu, tham chiếu thay đổi được sử dụng để sửa đổi dữ liệu. Thiết kế này giúp duy trì an toàn mã và xác định các mô-đun đọc.
Quy trình chính của xác thực an toàn bao gồm: quét các chỉ thị bytecode của các khối cơ bản trong hàm, xác định tất cả các thao tác tham chiếu có hợp pháp hay không. Quá trình này sử dụng cấu trúc AbstractState, nó chứa đồ thị vay và các biến cục bộ, được sử dụng để đảm bảo tính an toàn của các tham chiếu trong hàm.
Trong quá trình xác minh, mã khối cơ bản sẽ được thực thi, tạo ra trạng thái sau (post state), sau đó trạng thái trước (pre state) và trạng thái sau sẽ được kết hợp để cập nhật trạng thái của khối, và điều kiện hậu khối sẽ được truyền đến các khối tiếp theo. Quá trình này tương tự như ý tưởng Sea of Nodes trong V8 turbofan.
Lỗi xuất hiện trong hàm join_. Khi tổng độ dài của các tham số và độ dài của biến cục bộ lớn hơn 256, do local là kiểu u8, sẽ xảy ra tràn số nguyên. Mặc dù Move có quá trình kiểm tra số lượng locals, nhưng trong mô-đun kiểm tra giới hạn chỉ kiểm tra locals, không bao gồm độ dài của tham số.
Lỗ hổng tràn số nguyên này có thể dẫn đến cuộc tấn công DoS. Bằng cách tạo ra một khối mã lặp và lợi dụng sự tràn để thay đổi trạng thái của khối, có thể khiến bản đồ locals mới khác với bản đồ trước đó. Khi thực hiện lại hàm execute_block, nếu chỉ thị cần truy cập chỉ mục không tồn tại trong bản đồ locals của AbstractState mới, sẽ dẫn đến DoS.
Chúng tôi phát hiện ra rằng trong mô-đun reference safety, các opcode MoveLoc/CopyLoc/FreeRef có thể đạt được mục tiêu này. Lấy ví dụ về hàm copy_loc, nếu LocalIndex không tồn tại sẽ dẫn đến panic, từ đó làm cho toàn bộ nút bị sập.
Để xác minh lỗ hổng này, chúng tôi đã viết một PoC. Khối mã trong PoC này chứa một lệnh nhánh vô điều kiện, mỗi khi thực hiện lệnh cuối cùng sẽ nhảy trở lại lệnh đầu tiên, do đó khối mã này sẽ gọi nhiều lần các hàm execute_block và join.
Bằng cách thiết lập các tham số phù hợp, chúng ta có thể làm cho độ sâu của locals map mới trở thành 8. Trong lần thực thi thứ hai của hàm execute_block, do độ sâu của locals không đủ, sẽ dẫn đến panic.
Lỗ hổng này nhắc nhở chúng ta rằng ngay cả những ngôn ngữ như Move nhấn mạnh tính an toàn cũng có thể tồn tại lỗ hổng. Chúng tôi khuyên các nhà thiết kế ngôn ngữ Move nên thêm nhiều mã kiểm tra hơn trong thời gian chạy để ngăn chặn các tình huống bất ngờ xảy ra. Hiện tại, ngôn ngữ Move chủ yếu thực hiện kiểm tra an toàn ở giai đoạn xác minh, nhưng điều này có thể vẫn chưa đủ. Một khi việc xác minh bị vượt qua, nếu giai đoạn chạy không có đủ biện pháp an toàn, có thể dẫn đến những vấn đề nghiêm trọng hơn.
Với tư cách là người dẫn đầu trong nghiên cứu an ninh ngôn ngữ Move, chúng tôi sẽ tiếp tục nghiên cứu sâu về các vấn đề an ninh của Move và sẽ chia sẻ nhiều phát hiện hơn trong tương lai.
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
12 thích
Phần thưởng
12
8
Chia sẻ
Bình luận
0/400
AirdropHunterXiao
· 3giờ trước
Đào hố đào hố lại có việc tốt rồi
Xem bản gốcTrả lời0
ChainSherlockGirl
· 11giờ trước
Ha! Lại một vở kịch lỗ hổng bảo mật on-chain, lần này là màn trình diễn lớn về tràn số nguyên trên Move ~ Theo phân tích của cá nhân tôi, có lẽ là nhà đầu tư lớn nào đó lại muốn nhân cơ hội để short.
Xem bản gốcTrả lời0
SerumSquirter
· 17giờ trước
Một vấn đề bảo mật nữa, quá tồi.
Xem bản gốcTrả lời0
rugged_again
· 17giờ trước
Lại ra khỏi hang rồi, chuồn thôi!
Xem bản gốcTrả lời0
LiquidatedDreams
· 17giờ trước
Ai còn chơi move nữa?
Xem bản gốcTrả lời0
DarkPoolWatcher
· 17giờ trước
aptos quả thật không đáng tin cậy, có rất nhiều lỗ hổng.
Xem bản gốcTrả lời0
MondayYoloFridayCry
· 17giờ trước
Lại đen move rồi sao? Tsk tsk tsk
Xem bản gốcTrả lời0
PretendingSerious
· 17giờ trước
Cái lỗ này quá rõ ràng, nền tảng phát triển không vững chắc.
Lỗ hổng bảo mật trong ngôn ngữ Move: Rủi ro tràn số nguyên và khuyến nghị phòng ngừa
Phân tích sâu về lỗ hổng an ninh trong ngôn ngữ Move
Gần đây, khi chúng tôi nghiên cứu sâu về Aptos Moveevm, chúng tôi đã phát hiện ra một lỗ hổng tràn số nguyên mới. Quy trình kích hoạt lỗ hổng này khá thú vị, dưới đây chúng tôi sẽ tiến hành phân tích sâu và giới thiệu kiến thức nền tảng liên quan đến ngôn ngữ Move. Thông qua bài viết này, chúng tôi tin rằng độc giả sẽ có được hiểu biết sâu sắc hơn về ngôn ngữ Move.
Ngôn ngữ Move sẽ thực hiện xác minh đơn vị mã trước khi thực thi bytecode, quá trình này được chia thành 4 bước. Lỗ hổng được thảo luận trong bài viết này xuất hiện trong bước reference_safety.
Mô-đun reference_safety định nghĩa hàm chuyển giao được sử dụng để xác minh tính an toàn của các tham chiếu trong quá trình thực hiện. Nó chủ yếu kiểm tra xem có tồn tại tham chiếu treo, việc truy cập vào tham chiếu có thể thay đổi có an toàn hay không, và việc truy cập vào tham chiếu lưu trữ toàn cục có an toàn hay không.
Quá trình xác thực bắt đầu từ hàm nhập xác thực an toàn, hàm này sẽ gọi analyze_function. Trong analyze_function, mỗi khối cơ bản sẽ được xác thực. Khối cơ bản là một chuỗi mã, không có lệnh nhánh ngoại trừ điểm vào và điểm ra.
Ngôn ngữ Move xác định các khối cơ bản bằng cách duyệt mã byte, tìm tất cả các chỉ thị nhánh và chuỗi chỉ thị vòng lặp. Một ví dụ điển hình về khối mã IR Move có thể chứa 3 khối cơ bản, được xác định bởi các chỉ thị BrTrue, Branch và Ret.
Ngôn ngữ Move hỗ trợ hai loại tham chiếu: tham chiếu không thay đổi (&) và tham chiếu thay đổi (&mut). Tham chiếu không thay đổi được sử dụng để đọc dữ liệu, tham chiếu thay đổi được sử dụng để sửa đổi dữ liệu. Thiết kế này giúp duy trì an toàn mã và xác định các mô-đun đọc.
Quy trình chính của xác thực an toàn bao gồm: quét các chỉ thị bytecode của các khối cơ bản trong hàm, xác định tất cả các thao tác tham chiếu có hợp pháp hay không. Quá trình này sử dụng cấu trúc AbstractState, nó chứa đồ thị vay và các biến cục bộ, được sử dụng để đảm bảo tính an toàn của các tham chiếu trong hàm.
Trong quá trình xác minh, mã khối cơ bản sẽ được thực thi, tạo ra trạng thái sau (post state), sau đó trạng thái trước (pre state) và trạng thái sau sẽ được kết hợp để cập nhật trạng thái của khối, và điều kiện hậu khối sẽ được truyền đến các khối tiếp theo. Quá trình này tương tự như ý tưởng Sea of Nodes trong V8 turbofan.
Lỗi xuất hiện trong hàm join_. Khi tổng độ dài của các tham số và độ dài của biến cục bộ lớn hơn 256, do local là kiểu u8, sẽ xảy ra tràn số nguyên. Mặc dù Move có quá trình kiểm tra số lượng locals, nhưng trong mô-đun kiểm tra giới hạn chỉ kiểm tra locals, không bao gồm độ dài của tham số.
Lỗ hổng tràn số nguyên này có thể dẫn đến cuộc tấn công DoS. Bằng cách tạo ra một khối mã lặp và lợi dụng sự tràn để thay đổi trạng thái của khối, có thể khiến bản đồ locals mới khác với bản đồ trước đó. Khi thực hiện lại hàm execute_block, nếu chỉ thị cần truy cập chỉ mục không tồn tại trong bản đồ locals của AbstractState mới, sẽ dẫn đến DoS.
Chúng tôi phát hiện ra rằng trong mô-đun reference safety, các opcode MoveLoc/CopyLoc/FreeRef có thể đạt được mục tiêu này. Lấy ví dụ về hàm copy_loc, nếu LocalIndex không tồn tại sẽ dẫn đến panic, từ đó làm cho toàn bộ nút bị sập.
Để xác minh lỗ hổng này, chúng tôi đã viết một PoC. Khối mã trong PoC này chứa một lệnh nhánh vô điều kiện, mỗi khi thực hiện lệnh cuối cùng sẽ nhảy trở lại lệnh đầu tiên, do đó khối mã này sẽ gọi nhiều lần các hàm execute_block và join.
Bằng cách thiết lập các tham số phù hợp, chúng ta có thể làm cho độ sâu của locals map mới trở thành 8. Trong lần thực thi thứ hai của hàm execute_block, do độ sâu của locals không đủ, sẽ dẫn đến panic.
Lỗ hổng này nhắc nhở chúng ta rằng ngay cả những ngôn ngữ như Move nhấn mạnh tính an toàn cũng có thể tồn tại lỗ hổng. Chúng tôi khuyên các nhà thiết kế ngôn ngữ Move nên thêm nhiều mã kiểm tra hơn trong thời gian chạy để ngăn chặn các tình huống bất ngờ xảy ra. Hiện tại, ngôn ngữ Move chủ yếu thực hiện kiểm tra an toàn ở giai đoạn xác minh, nhưng điều này có thể vẫn chưa đủ. Một khi việc xác minh bị vượt qua, nếu giai đoạn chạy không có đủ biện pháp an toàn, có thể dẫn đến những vấn đề nghiêm trọng hơn.
Với tư cách là người dẫn đầu trong nghiên cứu an ninh ngôn ngữ Move, chúng tôi sẽ tiếp tục nghiên cứu sâu về các vấn đề an ninh của Move và sẽ chia sẻ nhiều phát hiện hơn trong tương lai.