Hotline : 1800 1093 - 07 088 44444
Thích
Chia sẻ

Buffer Overflow là gì? Tìm hiểu về lỗi tràn bộ đệm

01/07/2021

Buffer Overflow là gì?

Trước khi tìm hiểu Buffer Overflow là gì, ta cần biết được khái niệm về Buffer. Buffer (bộ đệm dữ liệu) là vùng lưu trữ dữ liệu tạm thời trong khi chờ để được chuyển đến vị trí khác. Buffer Overflow (hay Buffer Overrun) sẽ xảy ra khi khối lượng dữ liệu vượt quá khả năng lưu trữ của buffer. Do đó, khi chương trình cố gắng ghi dữ liệu vào trong buffer, nó sẽ ghi đè lên các bộ nhớ liền kề khác.

Lấy ví dụ, một buffer lưu trữ thông tin đăng nhập có thể được thiết kế sao cho input username và password là 8 byte. Do đó, với các transaction có input đến 10 byte, chương trình có thể ghi dữ liệu thừa (2 byte) vượt quá giới hạn của buffer.

Vậy ảnh hưởng của Buffer Overflow là gì? Hiện tượng Buffer Overflow có thể gây ra ảnh hưởng xấu đến tất cả các loại phần mềm. Nguyên nhân thường là do input không đúng định dạng, hoặc không gian lưu trữ không được phân bổ đủ cho buffer. Nếu transaction ghi đè lên các executable code (mã thực thi), chương trình có thể hoạt động không chính xác, đưa ra kết quả sai, crash. Bên cạnh đó còn có thể dẫn đến nhiều lỗi truy cập bộ nhớ khác.

Buffer-Overflow-la-gi

Buffer Overflow attack là gì?

Các hacker khai thác Buffer Overflow attack bằng cách ghi đè bộ nhớ của các ứng dụng. Việc này sẽ làm thay đổi execution path của chương trình, trigger một response làm ảnh hưởng xấu đến các file trên hệ thống. Hoặc thậm chí là làm lộ thông tin cá nhân của người dùng.

Một ví dụ đơn giản về Buffer Overflow attack là hacker gửi các code exploit, lệnh mới đến ứng dụng để có thể truy cập và chiếm quyền các hệ thống.

Làm thế nào những kẻ tấn công khai thác lỗi Buffer Overflow?

Vậy cách những kẻ tấn công khai thác lỗi Buffer Overflow là gì? Các hacker có thể cố tình đưa một input vào chương trình, làm cho chương trình lưu trữ input đó vào một buffer không đủ bộ nhớ. Từ đó ghi đè lên các phần bộ nhớ được kết nối với buffer.

Nếu hacker biết cách bố trí bộ nhớ của chương trình, chúng có thể cố tình gửi các input mà buffer không thể lưu trữ. Từ đó ghi đè lên các executable code bằng code của chúng. Chẳng hạn, hacker có thể ghi đè lên một con trỏ (một đối tượng chỉ vào các vùng khác trong bộ nhớ), và trỏ đến một payload khác để giành quyền kiểm soát chương trình.

Những ai có thể bị tấn công Buffer Overflow?

buffer overflow attack

Vậy đối tượng phổ biến của Buffer Overflow là gì? Các lỗ hổng bảo mật của buffer thường có nhiều hơn ở những ngôn ngữ lập trình như C hay C++. Vì những ngôn ngữ này bỏ qua tính bảo mật để có thể đổi lấy được sự hiệu quả, đồng thời cũng không kiểm soát truy cập bộ nhớ.

Đối với các ngôn ngữ lập trình bậc cao như Python, PHP, Perl, Java hay JavaScript, việc phòng chống Buffer Overflow attack cũng là vô cùng cần thiết. Vì các hệ điều hành vẫn thường được viết bằng C, hoặc sử dụng môi trường runtime viết bởi C. Và những code của ngôn ngữ C thường sẽ dễ bị Buffer Overflow hơn.

Mặc dù các hệ điều hành mới đều có khả năng bảo vệ Buffer Overflow attack, nhưng hầu hết các web server, server ứng dụng và môi trường ứng dụng hiện nay đều có khả năng bị tấn công. Ngoại trừ một số môi trường được thiết kế để phiên dịch những ngôn ngữ như Java hay Python – miễn nhiễm với tấn công Buffer Overflow.

Có một số ngôn ngữ lập trình “nhạy cảm” với Buffer Overflow attack hơn hẳn. Chẳng hạn như C và C++, vì chúng không được tích hợp khả năng bảo vệ, chống lại việc truy cập hay ghi đè dữ liệu bộ nhớ. Hiện nay có nhiều hệ điều hành được viết bằng C và C++ như: Windows, Mac OS và Linux.

Những ngôn ngữ hiện đại khác như Java, PERL, C# dù có tích hợp sẵn những tính năng giúp giảm thiểu Buffer Overflow, nhưng cũng khó có thể loại bỏ hoàn toàn được.

Các loại Buffer Overflow Attack

Vậy cách phân loại Buffer Overflow là gì? Có những loại Buffer Overflow attack nào? Hiện nay có nhiều loại hình tấn công cũng như chiến lược Buffer Overflow khác nhau, nhắm vào những mục tiêu và code cụ thể. Sau đây là một số loại Buffer Overflow attack phổ biến nhất:

  • Stack Overflow attack – Đây chính là loại hình tấn công phổ biến nhất, liên quan đến Buffer Overflow ở trong call stack.
  • Heap Overflow attack – Kiểu tấn công này nhắm vào dữ liệu ở trong một vùng bộ nhớ mở, được gọi là heap.
  • Interger Overflow attack – Hiện tượng này xảy ra khi thực hiện một phép toán đưa ra kết quả là một số nguyên quá lớn, do đó kiểu dữ liệu số nguyên (interger) không thể lưu trữ được. Từ đó dẫn đến Buffer Overflow.
  • Unicode Overflow – Unicode overflow tạo một Buffer Overflow bằng cách chèn các kí tự Unicode vào input dự kiến của các ký tự ASCII. (ASCII và Unicode đều là các tiêu chuẩn mã hóa để máy tính có thể hiển thị văn bản. ASCII chỉ có kí tự của các nước phương Tây, nhưng Unicode hỗ trợ hầu hết mọi ký tự ở trên thế giới. Do đó, ký tự Unicode thường lớn hơn ASCII nhiều).

Stack Overflow Attack

Stack có dạng cấu trúc dữ liệu và LIFO (Last In First Out), hỗ trợ hai toán tử là PUSH và POP. Toán tử PUSH được dùng dể chỉ định giá trị của steel, còn POP có nhiệm vụ trích xuất giá trị của steel. Nếu dữ liệu ở trên stack gặp sự cố, chúng sẽ ghi đè lên các bộ nhớ lièn kê. Từ đó làm ảnh hưởng đến dữ liệu hoặc con trỏ được lưu trữ bởi chương trình khác.

Stack Overflow là một lỗ hổng bảo mật cũ, sử dụng các bộ nhớ được stack chỉ tồn tại trong runtime. Lỗ hổng này thường xuất hiện ở trong C hoặc C++, vì người dùng có thể tự do sử dụng con trỏ ở trong các ứng dụng này. Các hacker có thể lợi dụng lỗ hổng này để khai thác hệ thống bằng cách thao túng dữ liệu hoặc tạo một con trỏ để chạy mã độc.

Heap Overflow Attack

Hiện tượng Heap Overflow xảy ra khi một phần bộ nhớ được gán cho heap, và dữ liệu được ghi vào bộ nhớ đó mà không cần kiểm tra. Việc này sẽ tạo ra một số cấu trúc dữ liệu quan trọng ở trong heap, chẳng hạn như heap header. Hay là bất kỳ dữ liệu heap-based nào khác, như con trỏ đối tượng động – có khả năng khi đè lên table function ảo.

heap overflow attack

Interger Overflow Attack

Interger Overflow (tràn số nguyên) là một lỗi tràn số học, xảy ra khi kết quả của một phép toán số nguyên không nằm trong giới hạn bộ nhớ. Việc này không dẫn đến lỗi chương trình mà thường đưa ra những kết quả không mong muốn. Với hầu hết các ngôn ngữ lập trình, các giá trị số nguyên đều được gán một giới hạn bit nhất định ở trong bộ nhớ.

Lấy ví dụ, kiểu số nguyên 4 byte (32 bit) trong ngôn ngữ C có giá trị từ (-231) đến (231 – 1). Giả sử bây giờ bạn muốn lưu trữ giá trị 231 vào kiểu số nguyên thì điều gì sẽ xảy ra? Hầu hết các ngôn ngữ hay trình biên dịch đều không gặp lỗi chương trình, mà chỉ đơn thuần thực hiện phép tính mô-đun. Cùng lắm chỉ khiến chương trình bị crash, và không để lại lỗ hổng bảo mật nào. Nhưng đây lại là cơ hội tốn để hacker thực hiện Buffer Overflow attack.

Thậm chí, việc tràn số nguyên còn có thể dẫn đến một số hậu quả nghiêm trọng hơn nữa, chẳng hạn như thao túng tính toán tài chính, ảnh hưởng đến những khách hàng.

Unicode Overflow

Các chuỗi Unicode được tạo ra để đảm bảo mọi ngôn ngữ trên thế giới đều có thể sử dụng. Ví dụ, các kí tự Ả Rập không thể được chuyển đổi bằng bảng mã ASCII, nhưng với Unicode thì hoàn toàn có thể. Khi đó, việc cung cấp các ký tự Unicode vào input của ASCII sẽ vượt qua giới hạn tối đa của ASCII, từ đó làm tràn buffer.

Những ví dụ về Buffer Overflow

Tiếp theo, hãy cũng tìm hiểu một số ví dụ về Buffer Overflow để có thể hiểu rõ hơn Buffer Overflow là gì, cũng như các loại hình và cách thức hoạt động của Buffer Overflow là gì.

Lỗi buffer overflow khi dùng hàm gets()

Dưới đây là một đoạn code minh họa cho lỗi Buffer Overflow đơn giản, thường xảy ra do code dựa vào dữ liệu bên ngoài để kiểm soát hành vi của nó. Code sử dụng hàm gets() để đọc một lượng dữ liệu ngẫu nhiên đi vào trong stack buffer. Vì không có cách nào có thể giới hạn số lượng dữ liệu được đọc bởi hàm này, nên code chỉ có thể yêu cầu người dùng chỉ nhập những kí tự nhỏ hơn BUFSIZE

...
char buf[BUFSIZE];
gets(buf);
...

Lỗi buffer overflow khi dùng toán tử >>

Dưới đây là một ví dụ cho thấy cách lợi dụng hành vi không an toàn của hàm gets() trong C++ bằng toán tử >> để đọc input thành một chuỗi char[].

...
char buf[BUFSIZE];
cin >> (buf);
...

Lỗi buffer overflow khi dùng hàm memcpy()

Trong ví dụ này, code cũng phụ thuộc vào input của người dùng để kiểm soát hành vi của nó. Tuy nhiên, nó thêm một hàm memory copy memcpy(). Hàm này nhận một buffer đích, một buffer nguồn và số lượng byte cần copy. Buffer input được điền bằng một call để read(), nhưng người dùng chỉ định số lượng byte mà hàm memcpy() sẽ copy.

...
char buf[64], in[MAX_SIZE];
printf("Enter buffer contents:\n");
read(0, in, MAX_SIZE-1);
printf("Bytes to copy:\n");
scanf("%d", &bytes);
memcpy(buf, in, bytes);
...

Lưu ý: Loại lỗ hổng Buffer Overflow này phổ biến trong các thư viện xử lý file, hình ảnh, âm thanh.

Cách ngăn chặn Lỗi tràn bộ nhớ đệm

cách ngăn chặn buffer overflow

Vậy cách chống Buffer Overflow là gì? Các developer có thể ngăn chặn lỗ hổng Buffer Overflow thông qua các biện pháp bảo mật với code. Hoặc đơn giản là sử dụng những ngôn ngữ có tích hợp khả năng bảo vệ.

Bên cạnh đó, các hệ điều hành hiện đại đều có thêm khả năng bảo vệ runtime. Trong đó, ba biện pháp bảo vệ phổ biến nhất là:

  • Address Space Layout Randomization (ASLR) – di chuyển ngẫu nhiên xung quanh các không gian địa chỉ của vùng dữ liệu. Thông thường, các cuộc tấn công Buffer Overflow cần biét được vị trí của executable code, và việc ngẫu nhiên các không gian địa chỉ sẽ hoàn toàn vô hiệu hóa cách thức tấn công này.
  • Bảo vệ việc thực thi dữ liệu Falg một số vùng bộ nhớ là non-executable (không thể thực thi) hoặc executable (có thể thực thi) để ngăn chặn các cuộc tấn công chạy mã ở trong vùng non-executable.
  • Structured exception handler overwrite protection (SEHOP) – giúp ngăn chặn các code độc hại tấn công SEH (Ngoại lệ có cấu trúc) – một hệ thống được tích hợp sẵn để quản lý các ngoại lệ (exception) của phần cứng và phần mềm. Từ đó, ngăn chặn các hacker lợi dụng kỹ thuật khai thác ghi đè SEH. Ở cấp độ chức năng, việc ghi đè SEH có thể đạt được bằng cách sử dụng một stack-based Buffer Overflow dể ghi đè một bản ghi đăng ký ngoại lệ, được lưu trữ trong stack của thread.

Dĩ nhiên, các biện pháp bảo mật về code hay hệ thống vẫn chưa hoàn toàn là đủ để ngăn chặn Buffer Overflow attack. Khi tổ chức phát hiện bất kỳ lỗ hổng Buffer Overflow nào, cần phải nhanh chóng vá các phần mềm bị ảnh hưởng. Đồng thời đảm bảo người dùng của phần mềm có thể truy cập được các bản vá đó.

Hy vọng sau bài viết này, các bạn có thể hiểu được Buffer Overflow là gì, ảnh hưởng của nó cũng như các cách có thể ngăn chặn được Buffer Overflow attack. Chúc các bạn thành công!

Nếu bạn có thắc mắc hay có vấn đề cần hỗ trợ, bạn có thể liên hệ trực tiếp với Vietnix thông qua các kênh sau:
  • Hotline: 1800 1093 - 07 088 44444
  • Email: support@vietnix.vn
  • Hoặc chat trực tiếp với Vietnix thông qua biểu tượng Livechat ở góc phải màn hình. Đội ngũ chuyên viên của chúng tôi luôn sẵn sàng tư vấn và hỗ trợ bạn 24/7.
Vietnix hiện đang có chương trình khuyến mãi lớn nhất trong năm, giảm giá 50%  dịch vụ Hosting. Đăng ký dùng thử ngay và Vietnix sẽ hoàn tiền 100% nếu quý khách không hài lòng với chất lượng sản phẩm, dịch vụ!
Mình là Bo - admin của Quản Trị Linux. Mình đã có 10 năm làm việc trong mảng System, Network, Security và đã trải nghiệm qua các chứng chỉ như CCNP, CISSP, CISA, đặc biệt là chống tấn công DDoS. Gần đây mình trải nghiệm thêm Digital Marketing và đã hòan thành chứng chỉ CDMP của PersonVUE. Mình rất thích được chia sẻ và hỗ trợ cho mọi người, nhất là các bạn sinh viên. Hãy kết nối với mình nhé!
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments