Lỗi do tràn bộ nhớ đệm và cách khắc phục

Quản trị mạng - Về cơ bản, tràn bộ nhớ đệm thường xuất phát từ một nguyên nhân duy nhất. Đó là do người dùng gửi quá nhiều dữ liệu tới một chương trình và một phần của dữ liệu này buộc phải lưu trữ ra ngoài bộ nhớ mà lập trình viên đã cấp cho chương trình đó. Quá trình tràn bộ nhớ đệm có thể gây ra nhiều vấn đề, trong đó có một vấn đề mà chúng ta cần quan tâm đó là khi bộ nhớ đệm lưu trữ dữ liệu tới một mức độ nhất định nào đó thì tin tặc có thể chạy các đoạn mã chương trình trên hệ thống.

Trong bài viết này chúng ta sẽ tìm hiểu một tình huống tràn bộ nhớ đệm mà tin tặc có thể khai thác để chạy mã trên hệ thống. Sau đó chúng ta sẽ tìm hiểu Data Execution Preventions (DEP), một tính năng được tích hợp trong hệ điều hành Windows có chức năng ngăn tràn bộ nhớ đệm.

Nhận biết hiện tượng tràn bộ nhớ đệm

Để có thể hiểu rõ về hiện tượng tràn bộ nhớ đệm chúng ta phải nắm vững ngôn ngữ lập trình cao cấp như C hay C++, cũng như có một vốn kiến thức sâu về quá trình vận hành của các ngăn xếp bộ nhớ.

Khi viết một chương trình, một trong những điều mà lập trình viên cần phải tính toán cẩn trọng đó là kích thước vùng trống của bộ đệm được phân bổ cho những hàm cụ thể. Bộ nhớ đệm là một vùng trống liền kề của bộ nhớ mà một chương trình có thể sử dụng để lưu trữ dữ liệu mà các chức năng khác có thể sử dụng. Chúng ta hãy xem xét đoan mã ví dụ sau:


Hình 1: Hàm A C rất dễ bị tấn công khi tràn bộ nhớ đệm.

Hàm này rất rõ ràng, bắt đầu bằng việc khai bào hai biến bufferAbufferB có kích thước lần lượt là 5016. Chương trình này hiển thị một câu hỏi tới người dùng yêu cầu nhập tên và sử dụng hàm gets đễn nhận thông tin nhập vào. Sau đó dữ liệu mà người dùng cung cấp được copy từ bufferA sang tham số bộ nhớ đệm và hàm này được hoàn thành.

Với một chương trình đơn giản như vậy có thể hơi quá khi cho rằng nó có thể bị tác động bởi mọi cuộc tấn công. Tuy nhiên vấn đề ở đây nằm trong hàm gets. Vì hàm gets không tự kiểm tra giới hạn do đó khó có thể khẳng định rằng thông tin nhập vào bufferA không vượt quá 50 kí tự. Nếu người dùng nhập hơn 50 kí tự thì chương trình sẽ bị sập.

Hàm strcopy sẽ copy dữ liệu trong bufferA sang bufferB. Tuy nhiên bufferB có kích thước nhỏ hơn bufferA, điều này có nghĩa là dù người dùng nhập vào ít hơn 50 kí tự nhưng vẫn có thể nhiều hơn 16 kí tự vào bufferA, và khi copy sang bufferB sẽ gây ra hiện tượng tràn bộ nhớ đệm và chương trình cũng sẽ bị sập. Chương trình nhỏ này không chỉ có một mà là hai lỗ hổng tràn bộ nhớ đệm.

Khai thác tràn bộ nhớ

Tiếp theo chúng ta sẽ tìm hiểu những điều kiện gây ra tràn bộ nhớ và vấn đề phát sinh từ tràn bộ nhớ? Trong những trường hợp bộ nhớ đệm bị tràn thì dữ liệu tràn ra ngoài bộ nhớ đệm được chỉ định sẽ phải lưu trữ vào một nơi khác. Dữ liệu này sẽ chảy vào các vùng nhớ lân cận, và thông thường khi đó chương trình sẽ bị lỗi vì nó không thể xử lý các dữ liệu bổ sung. Mặt khác, khi lỗi này bị một ai đó hiểu biết về ngôn ngữ Assembly (một bộ ngôn ngữ lập trình cấp thấp được sử dụng trong lập trình máy tính, vi xử lý, vi điều khiển và mạch tích hợp) và ngăn xếp bộ nhớ khai thác thì mọi chuyện còn tồi tệ hơn. Trong tình huống này, tin tặc có thể gây tràn bộ nhớ đệm theo phương pháp mà chúng có thể tạo những lệnh hệ thống riêng, rồi chuyển đổi những lệnh này thành mã byte cấp thấp sau đó gửi chúng tới chương trình này theo định dạng phù hợp thì những lệnh này sẽ được chạy.


Hình 2: Một mẫu Shellcode của Assembly và C được viết để trả về
một dấu nhắc C:\ của Windows.

Lúc này đoạn mã được chạy trong ngữ cảnh ứng dụng dễ bị tấn công ban đầu của người dùng. Điều đó có nghĩa là nếu chương trình này được quản trị hệ thống chạy thì mã kết hợp cũng chạy trong ngữ cảnh của một quản trị viên hệ thống. Tùy thuộc vào kích thước của bộ nhớ đệm mà tin tặc có thể kết hợp nhiều loại mã khác nhau. Những loại mã thường được sử dụng là những loại được gọi là Shellcode. Mã này sẽ trả về một Shell (ví dụ một dấu nhắc C:\ của Windows) tới người đã chạy đoạn mã đó. Trong một ngữ cảnh phù hợp thì người chạy mã đó sẽ có toàn quyền kiểm soát với máy trạm này. Tràn bộ nhớ đệm có thể xảy ra dưới nhiều hình thức và quy mô, một người thành thạo trong việc điều khiển ngăn xếp sẽ chiếm được toàn quyền kiểm soát mọi hệ thống dễ bị tấn công.

Data Execution Prevention

Phương pháp đơn giản nhất để chặn khả năng khai thác lỗ hổng phát sinh do tràn bộ nhớ đệm mà các lập trình viên thường sử dụng là luôn đảm bảo mã lập trình được bảo mật. Thực ra đây không phải là một tiến trình được tự động hóa vì nó yêu cầu tiêu tốn nhiều thời gian và công sức cho việc kiểm tra lại mã để đảm bảo rằng tính toàn vẹn của mã chương trình được duy trì, do đó số lượng dòng lệnh tỉ lệ thuận với thời gian và công sức cần phải bỏ ra. Xuất phát từ yêu cầu đó Microsoft đã phát triển một tính năng có tên Data Execution Prevention (DEP).

DEP, một tính năng bảo mật được giới thiệu trong Windows XP SP2, được thiết kế để chặn ứng dụng chạy mã trong vùng không thể chạy của bộ nhớ. DEP xuất hiện trong cả cấu hình Hardware-based DEP (nền tảng phần cứng) và Software-based DEP (nền tảng phần mềm).

Hardware-based DEP

DEP được cho là bảo mật nhất khi sử dụng Hardware-based DEP. Trong trường hợp này vi xử lý sẽ đánh dấu mọi vị trí nhớ là “không thể thực thi” nếu vị trí này không chứa mã thực thi. Mục đích của việc này là DEP sẽ chặn mọi mã chạy trong những vùng không thể thực thi.

Vấn đề chính của việc sử dụng Hardware-based DEP là nó chỉ được hỗ trợ bởi một số ít tiến trình. Vi xử lý có thể thực hiện được điều này là nhờ có tính năng NX của bộ vi xử lý AMD và XD của Intel.

Software-based DEP

Khi Hardware-based DEP không tồn tại thì Software-based DEP phải được sử dụng. Loại DEP này được tích hợp trong hệ điều hành Windows. Software-based DEP vận hành bằng cách dò tìm thời điểm mà những ngoại lệ được các chương trình đưa vào và đảm bảo rằng những ngoại lệ này là một phần hợp lệ của chương trình này trước khi cho phép chúng xử lý.







Cấu hình Data Execution Prevention

Trong Windows 7, DEP có thể được cấu hình trong Control Panel của hệ thống. Vào Control Panel | Advanced System Settings. Chọn tab Data Execution Prevention.


Hình 3: Cấu hình mặc định của DEP trong Windows 7.

DEP có hai tùy chọn cấu hình. Tùy chọn mặc định trong hình 3 được gọi là cấu hình OptIn. Tùy chọn này chỉ áp dụng DEP cho những chương trình và dịch vụ hệ thống quan trọng. Đây là một cấp độ bảo mật thấp (được gọi là cấu hình OptOut), nhưng nếu muốn sử dụng một cấp độ bảo mật cao hơn bạn nên lựa chọn tùy chọn thứ hai, tùy chọn này áp dụng DEP cho mọi chương trình và dịch vụ trên hệ thống. Lưu ý rằng, phía dưới của hộp thoại này cho biết CPU đang sử dụng có hỗ trợ Hardware-based DEP hay không.

Mặc dù việc cấu hình DEP áp dụng cho mọi chương trình và dịch vụ có cấp độ bảo mật cao nhất, nhưng cần nhớ rằng nó lại ẩn chứa những vấn đề về tương thích. Thứ nhất, một số chương trình sẽ thực hiện những chức năng chính thống mà có thể bị DEP chặn do phương pháp chúng vận hành. Trong những trường hợp này chúng ta phải tạo một ngoại lệ cho chương trình đó. Trên hộp thoại cấu hình DEP, nhấn nút Add rồi lựa chọn những file thực thi phù hợp. Microsoft đề xuất rằng chỉ nên sử dụng những driver được đăng ký để ngăn chặn những vấn đề tương thích có thể xảy ra khi lựa chọn tùy chọn thứ hai này.


Hình 4: Cấu hình DEP cho mọi dịch vụ và tạo chương trình ngoại lệ.

Sau khi thực hiện và lưu cấu hình, khi xuất hiện mã thực thi trong vùng không thể thực thi DEP sẽ hiển thị thông báo như trong hình 5.


Hình 5: DEP chặn thực thi trong Windows Explorer.

Kết luận

Tràn bộ nhớ đệm tưởng như không có gì nguy hại nhưng lại là một trong những mối đe dọa tới khả năng bảo mật hệ thống đáng chú ý nhất. Cơ bản, tin tặc thường nhằm vào lỗi này để khai thác hệ thống. Nếu là một lập trình viên bạn nên hạn chế lỗi này bằng cách đảm bảo quá trình kiểm tra mã và áp dụng các biện pháp bảo mật mã. Nếu là một quản trị viên hệ thống bạn có thể sử dụng DEP để ngăn chặn những nguy cơ bảo mật có thể phát sinh.
Thứ Năm, 29/10/2009 14:15
4,38 👨 28.096
0 Bình luận
Sắp xếp theo
    ❖ Kiến thức cơ bản