Tuần trước, một nhóm hacker không rõ tên tuổi đã thực hiện thành công vụ trộm lớn thứ hai trong lịch sử của tiền điện tử. VnReview xin giới thiệu bài viết của kỹ sư phần mềm Haseeb Qureshi xung quanh vụ việc này.
Các hacker đã khai thác một lỗ hổng nghiêm trọng trên Parity, một loại ví điện tử đa chữ ký trên Ethereum, lấy đi ba tài khoản tiền Ether có giá trị lên đến 31.000.000 USD chỉ trong vài phút. Nếu có thêm vài giờ nữa, hacker đã có thể cuỗm sạch hơn 150.000.000 USD trong những ví có lỗ hổng khác.
Nhưng ai đó đã chặn chúng lại.
Vừa nhận được cảnh báo, một nhóm hacker mũ trắng từ cộng đồng Ethereum nhanh chóng được tập hợp. Cả nhóm phân tích cuộc tấn công và nhận thấy không có cách nào để hoàn lại tiền trong các tài khoản đã bị trộm, trong khi có rất nhiều những ví khác cũng tồn tại lỗ hổng. Thời gian rất gấp rút và các hacker mũ trắng kết luận họ chỉ có một lựa chọn duy nhất: tấn công những ví tiền điện tử còn lại trước khi kẻ tấn công làm điều đó.
Bằng cách khai thác cùng một lỗ hổng, nhóm hacker mũ trắng tấn công các tài khoản ví còn lại và rút sạch tiền trong đó, khiến kẻ tấn công không thể tiếp cận khoản tiền lên đến 77.000.000 USD.
Chính xác là như vậy. Để ngăn cản kẻ tấn công trộm thêm tiền, các hacker mũ trắng đã viết một phần mềm để trộm tất cả số tiền còn lại. Sau khi số tiền được ‘trộm an toàn’, họ bắt đầu trả lại cho các chủ tài khoản.
Đây quả là một câu truyện kỳ thú và có ý nghĩa to lớn với thế giới tiền ảo.
Có một chi tiết quan trọng cần phải nhớ, đó là cuộc tấn công này không khai thác lỗ hổng trên bản thân Ethereum hay trên ví Parity. Thật ra, đó là một lỗ hổng trên mã hợp đồng thông minh (smart contract code).
1. Thực sự điều gì đã xảy ra?
Có ba đối tượng liên quan đến câu chuyện này: Ethereum, hợp đồng thông minh và ví điện tử.
Ethereum là một loại tiền kỹ thuật số được giới thiệu lần đầu tiên năm 2013, bốn năm sau khi có Bitcoin. Kể từ đó, Ethereum đã trở thành đồng tiền kỹ thuật số có giá trị vốn hoá thị trường lớn thứ hai trên thế giới – 20 tỉ USD so với 40 tỉ USD của Bitcoin.
Giống như tất cả các loại tiền ảo khác, Ethereum là ‘hậu duệ’ của giao thức Bitcoin, đồng thời được phát triển dựa trên thiết kế của Bitcoin.
Trong khi Bitcoin sử dụng blockchain để ghi chép các giao dịch tiền mặt, Ethereum sử dụng blockchain để ghi lại các biến đổi trạng thái trên một máy tính phân tán khổng lồ.
Nói cách khác, Ethereum là một chiếc máy tính có quy mô trải rộng trên toàn thế giới. Bất kỳ ai sử dụng phần mềm Ethereum trên máy tính đều là tham gia vận hành chiếc máy ảo Ethereum (EVM) khổng lồ này. Bởi vì EVM được thiết kế theo ngôn ngữ Turing Complete, nó có thể làm hầu như tất cả mọi việc, miễn là việc đó có thể được diễn tả dưới dạng một chương trình máy tính.
Cần nhấn mạnh một chút: Đây là một thứ điên rồ. Thế giới ngầm đang sôi sục về tiềm năng của Ethereum, giá trị của nó tăng chóng mặt trong vòng 6 tháng qua.
Cộng đồng các nhà phát triển nhanh chóng bị thu hút, người ta hào hứng về những thứ có thể xây dựng trên EVM.
Hợp đồng thông minh, hiểu một cách đơn giản, chính là những chương trình máy tính chạy trên EVM. Ở rất nhiều điểm, chúng cũng giống các hợp đồng thông thường, ngoại trừ việc không cần đến luật sư hay quan toà để diễn giải. Thay vào đó, các hợp đồng thông minh được biên dịch theo bytecode và được giải thích rõ ràng bằng EVM. Với những chương trình này, bạn có thể tự động chuyển tiền ảo dựa trên các quy định của mã hợp đồng.
Ví tiền ảo. Trong thế giới tiền ảo, ví tiền ảo là phương tiện giúp các bạn cất giữ của cải của mình. Bạn truy cập các ví tiền này bằng khóa bí mật.
Có nhiều loại ví tiền ảo khác nhau với những tính năng bảo mật khác nhau. Một trong những ví tiền ảo phổ biến nhất là ví đa chữ ký.
Trong một ví đa chữ ký, có nhiều khóa bí mật để mở ví, nhưng nếu chỉ dùng một khóa thì chưa đủ. Ví dụ, nếu ví của bạn có 3 khóa, khi đó bạn phải xác thực ít nhất 2 trong 3 khóa mới có thể mở ví.
Điều này có nghĩa là nếu bố bạn, mẹ bạn và bạn là ba bên đồng sở hữu ví tiền ảo, khi đó nếu mẹ bạn bị hack và lấy mất khoá bí mật, hacker vẫn không thể truy cập tài khoản ví của bạn. Điều này đảm bảo mức độ bảo mật cao hơn, có nghĩa là yếu tố đa chữ ký chính là một tiêu chuẩn của tính bảo mật cho ví điện tử.
Đây cũng chính là loại ví điện tử bị tấn công trong vụ của Ethereum.
Vậy điều gì đã xảy ra? Có phải hacker đã phá khoá bí mật hay không? Hay chúng đã sử dụng máy tính lượng tử, hay một loại thuật toán tối tân nào đó?
Không phải. Cách tấn công đơn giản đến mức khó tin: hacker tìm thấy một lỗ hổng trong code do lỗi của lập trình viên. Lỗ hổng cho phép hacker khởi tạo lại ví, gần giống với việc khôi phục lại cài đặt gốc. Một khi đã thành công, hacker hoàn toàn có thể thiết lập để mình là chủ sở hữu mới, rồi lấy đi mọi thứ mà không gặp bất kỳ trở ngại nào.
2. Việc đó xảy ra thế nào?
Ethereum có một mô hình lập trình gần như ‘độc quyền’. Trên Ethereum, bạn viết code bằng cách xuất bản hợp đồng (có thể coi là đối tượng), các giao dịch được thực hiện bằng cách gọi các phương thức trên các đối tượng này để thay đổi trạng thái.
Để chạy code trên Ethereum, trước hết bạn cần triển khai hợp đồng (bản thân việc triển khai này chính là một giao dịch), điều này sẽ tiêu tốn của bạn một số lượng nhỏ Ether. Sau đó, bạn sẽ cần gọi các phương thức trên hợp đồng để tương tác, và bạn lại mất thêm một số Ether nhỏ nữa. Như bạn có thể hình dung, đây là động lực để các lập trình viên tối ưu code của mình, nhằm giảm bớt các chi phí giao dịch và tính toán. Có một cách để giảm chi phí là sử dụng các thư viện.
Ví tiền ảo đa chữ ký mặc định trên Parity đã áp dụng đúng cách này: Liên kết với một thư viện được chia sẻ bên ngoài có logic khởi tạo ví.
Vậy lỗ hổng nằm ở đâu? Thực tế có 2 lỗ hổng. Thứ nhất, hai phương thức initWallet và initMultiowned trên thư viện chia sẻ đã không được đánh dấu ‘nội bộ’, và cũng không kiểm tra việc tài khoản ví thực ra vẫn chưa được khởi tạo. Chỉ cần một trong hai việc này được thực hiện thì cuộc tấn công đã không xảy ra. Lỗ hổng thứ hai nằm ở hướng dẫn delegateCall.
Hacker đã tận dụng các lỗ hổng để cuỗm sạch số tiền trong ba tài khoản ví điện tử ‘dầy’ nhất chúng tìm thấy. Dựa vào thời gian giao dịch, có thể thấy chúng đã làm việc này một cách thủ công.
Các hacker mũ trắng cũng làm việc đó, nhưng bằng script, nhờ vậy đã kịp ngăn kẻ tấn công lấy tiền trong các ví điện tử còn lại.
3. Cuộc tấn công có ý nghĩa gì với Ethereum?
Đầu tiên, cần nhớ rằng đó không phải là lỗ hổng trên Ethereum hay trên các hợp đồng thông minh nói chung, mà là lỗi của lập trình viên trong một hợp đồng thông minh cụ thể.
Vậy ai đã phát triển hợp đồng này?
Hợp đồng là một sản phẩm hợp tác giữa những người sáng lập Ethereum, đội ngũ nòng cốt của Parity và những thành viên của cộng đồng mã nguồn mở, đồng thời được đánh giá vô cùng kỹ lưỡng.
Những lập trình viên này cũng chỉ là con người. Con người thì có thể mắc lỗi. Những người đã rà soát code cũng vậy.
Các lập trình viên vẫn thường mắc phải những lỗi dạng này. Tất cả các chương trình đều có nguy cơ có lỗi do lập trình viên. Chúng ta phải ‘quẳng’ đi suy nghĩ rằng “nếu họ cẩn thận hơn, điều này đã không xảy ra”. Ở một mức độ nhất định, sự cẩn trọng là không đủ.
Tương tự như vậy, bao nhiêu lần rà soát bằng con người cũng là không đủ để ngăn chặn tất cả những lỗ hổng. Ngay cả Google hay NASA cũng mắc phải những lỗi lập trình, dù họ yêu cầu rất khắt khe với những code quan trọng.
Ở Google và Airbnb, mỗi khi có lỗi hay sự cố sản xuất, họ sẽ mổ xẻ, phân tích sự việc và đưa thông tin rộng rãi trong nội bộ công ty. Khi đó, sẽ luôn luôn có một nguyên tắc được áp dụng là không bao giờ đổ lỗi cho các cá nhân.
Việc đổ lỗi cho cá nhân là vô nghĩa, bởi vì tất cả các lập trình viên, dù là người có kinh nghiệm đến mức nào, cũng đều có khả năng mắc lỗi lớn hơn 0. Thay vào đó, mục đích của việc phân tích, mổ xẻ là để xác định lỗi xảy ra ở giai đoạn nào.
Vấn đề không nằm ở chỗ các lập trình viên quên đánh dấu ‘nội bộ’ trên thư viện ví điện tử, cũng không phải ở việc họ thực hiện lệnh gọi delegateCall mà không kiểm tra phương thức được gọi.
Vấn đề nằm ở chỗ các công cụ lập trình họ sử dụng đã để họ mắc lỗi.
Khi hệ sinh thái hợp đồng thông minh phát triển, sự phát triển đó cần có đảm bảo rằng việc mắc những lỗi này sẽ ít xảy ra hơn.
Đến đây, tác giả nghĩ đến một vấn đề khác.
Điểm mạnh chính là điểm yếu khi nói đến các ngôn ngữ lập trình. Một ngôn ngữ lập trình càng mạnh, code của ngôn ngữ đó sẽ càng phức tạp. Solidity là một ngôn ngữ cực kỳ phức tạp, được phát triển dựa trên mô hình tương tự Java.
Sự phức tạp là kẻ thù của bảo mật. Tôi nghĩ những ngôn ngữ như Viper là một hướng đi hứa hẹn. Viper có những cơ chế bảo mật cơ bản mặc định giúp ngăn ngừa những lỗ hổng cơ bản.
Càng ít việc bạn phải làm với ngôn ngữ lập trình, việc phân tích và chứng minh những đặc tính của một hợp đồng sẽ càng trở nên dễ dàng hơn. Bảo mật là một việc khó khăn, bởi cách duy nhất để chứng minh một nhận định ‘sáng sủa’ như “hợp đồng này an toàn” là phủ nhận tất cả các phương thức tấn công có thể xảy ra.
Đến đây, lại có một bài học lớn hơn được rút ra.
Hầu hết những lập trình viên tham gia vào mảng blockchain này đều có nền tảng là các lập trình viên web, các công cụ blockchain được thiết kế để có thể trông quen thuộc với những người phát triển web. Solidity được sử dụng rộng rãi trong cộng đồng các nhà phát triển bởi nó khá giống với những phương thức lập trình khác.
Vấn đề là, lập trình blockchain với lập trình web về cơ bản là khác nhau.
Trước thời đại của mô hình web client-server, hầu hết việc lập trình chỉ quanh quẩn ở các phần mềm đóng gói và những hệ thống nhúng. Đây là trước khi các gói update phần mềm tự động xuất hiện. Trong các chương trình này, một sản phẩm tới tay người dùng được coi là đã hoàn thành – cứ mỗi 6 tháng bạn lại phát hành một phiên bản của phần mềm, và nếu có lỗ hổng trên đó, lỗ hổng đó sẽ cứ ở đó cho đến lần phát hành tiếp theo. Chính vì vòng phát triển dài này, tất cả các phiên bản phần mềm trước khi phát hành sẽ được kiểm tra kỹ càng hơn, dưới tất cả các tình huống có thể nghĩ ra.
Phát triển web không khắt khe như vậy. Khi bạn đẩy code không tốt lên máy chủ web, sẽ chẳng phải là vấn đề lắm nếu code đó có chứa một lỗ hổng nghiêm trọng – bạn chỉ cần kéo code về, hay là đẩy code mới đã bao gồm bản vá, hay làm bất kỳ việc gì bạn muốn bởi vì bạn có quyền quản lý server. Ngay cả khi có chuyện tồi tệ xảy ra, như có người khai thác lỗ hổng hoặc có rò rỉ dữ liệu, bạn vẫn luôn có thể ngăn chặn bằng cách đóng server hoặc ngắt kết nối.
Hầu hết các lập trình viên ngày nay được đào tạo dựa trên mô hình phát triển web. Thật không may, mô hình bảo mật blockchain lại giống với cách thức cũ hơn.
Với blockchain, một khi bạn đã triển khai một hợp đồng thông minh có lỗi, ai cũng có thể thực hiện tấn công và không có cách nào để bạn có thể lấy nó về nếu hacker đã có code trong tay. Trừ khi bạn áp dụng các cơ chế bảo mật thông minh cho hợp đồng của mình, nếu chẳng may có một cuộc tấn công thành công hay tồn tại một lỗ hổng, bạn không thể đóng server để sửa lỗi. Sử dụng Ethereum cũng đồng nghĩa với việc mọi người đều sở hữu server của bạn.
Có một câu cửa miệng trong giới an ninh mạng là “tấn công bao giờ cũng dễ hơn phòng thủ”. Blockchain phân chia sâu sắc sự chênh lệch này. Việc tấn công dễ dàng hơn rất nhiều bởi bạn có thể truy cập code của mọi hợp đồng, biết có bao nhiêu tiền trong đó, và có thể có bao nhiêu thời gian tuỳ ý để thực hiện tấn công. Một khi cuộc tấn công của bạn thành công, về cơ bản bạn có thể lấy đi tất cả số tiền có trong hợp đồng.
Khi đó, việc phòng thủ trở nên cực kỳ khó khăn. Các hacker mũ trắng trong vụ tấn công Parity đã chứng minh cho chúng ta thấy có rất ít lựa chọn phòng thủ. Không có cách nào để bảo mật các hợp đồng, hay thậm chí là ‘hack’ lại số tiền đã bị mất; tất cả những gì họ có thể làm là hack toàn bộ số tiền còn lại trước khi kẻ tấn công kịp sờ đến.
Nhưng tôi không nghĩ đây là hồi chuông báo tử cho lập trình blockchain. Thay vào đó, vụ việc này xác nhận lại một việc ai cũng biết: hệ sinh thái này còn non trẻ và chưa trưởng thành. Sẽ cần nhiều thời gian và công sức, nhưng về lâu dài blockchain sẽ thành công.
Khi đó, không chỉ các lập trình viên trưởng thành hơn và được đào tạo bài bản hơn, mà những công cụ và ngôn ngữ lập trình cũng sẽ dễ dùng hơn, giúp chúng ta đảm bảo hơn về code được viết ra.
Vẫn còn khá sớm. Ethereum vẫn đang trong quá trình phát triển và thay đổi nhanh chóng. Bạn không nên coi Ethereum như một ngân hàng hay thay thế cho một cơ sở hạ tầng tài chính. Có một điều chắc chắn là bạn không nên giữ tiền trong các ‘ví nóng’ (ví tiền ảo Bitcoin được kết nối Internet gần như mọi lúc, người dùng có thể sử dụng tiền trong đó khi nào họ muốn).
Dù vậy, tôi vẫn nghĩ về lâu dài Ethereum sẽ thắng. Đây là lí do: Cộng đồng các nhà phát triển Ethereum chính là những người tạo nên sức mạnh cho nền tảng này.
Ethereum không ‘sống’ hay ‘chết’ phụ thuộc vào số tiền mình có, mà phụ thuộc vào đội ngũ các nhà phát triển, những người đang chiến đấu vì Ethereum.
Những ‘anh hùng’ mũ trắng không bảo vệ các ví điện tử có lỗ hổng vì tiền. Họ làm thế vì tin tưởng vào hệ sinh thái này. Họ muốn Ethereum phát triển. Họ mong mỏi niềm tin vào tương lai của mình sẽ thành sự thật. Trên hết, đây chính là những người góp phần đưa cộng đồng phát triển. Họ là lí do để Ethereum chiến thắng – và nếu họ từ bỏ Ethereum, sự từ bỏ đó là lí do khiến nền tảng này thua cuộc.
Cuộc tấn công lần này có ý nghĩa quan trọng: ‘thức tỉnh’ mọi người, khiến mọi người quan tâm hơn đến an ninh, buộc các lập trình viên nghiêm túc hơn với các hợp đồng thông minh.
Cuối cùng, các cuộc tấn công như thế này là cơ hội để cộng đồng phát triển. Bị tấn công là ‘đau khổ’, rồi báo chí sẽ làm rùm beng lên. Nhưng mỗi vết thương đều khiến cộng đồng lớn mạnh hơn, giúp chúng ta hiểu hơn về công nghệ của blockchain – cả nguy cơ lẫn tiềm năng.
Theo freeCodeCamp