Rate this post

Khai thác Format string xảy ra khi dữ liệu đã gửi của một chuỗi đầu vào được ứng dụng đánh giá như một lệnh. Bằng cách này, kẻ tấn công có thể thực thi mã, đọc ngăn xếp hoặc gây ra lỗi phân đoạn trong ứng dụng đang chạy, gây ra các hành vi mới có thể ảnh hưởng đến bảo mật hoặc sự ổn định của hệ thống.

Để hiểu cuộc tấn công, cần phải hiểu các thành phần cấu thành nó.

  • Hàm Định dạng là một hàm chuyển đổi ANSI C, như printf, fprintf, chuyển đổi một biến nguyên thủy của ngôn ngữ lập trình thành một biểu diễn chuỗi mà con người có thể đọc được.
  • Format string là đối số của Hàm định dạng và là một chuỗi ASCII Z chứa các tham số định dạng và văn bản, như: printf (“Con số kỳ diệu là:% d \ n”, 1911);
  • Tham số Format string, như% x% s xác định kiểu chuyển đổi của hàm định dạng.

Cuộc tấn công có thể được thực hiện khi ứng dụng không xác thực đúng đầu vào đã gửi. Trong trường hợp này, nếu tham số Format string, như% x, được chèn vào dữ liệu đã đăng, thì chuỗi đó sẽ được phân tích cú pháp bởi Hàm định dạng và chuyển đổi được chỉ định trong các tham số được thực thi. Tuy nhiên, Hàm định dạng đang mong đợi nhiều đối số hơn làm đầu vào và nếu các đối số này không được cung cấp, hàm có thể đọc hoặc ghi ngăn xếp.

Bằng cách này, có thể xác định một đầu vào được chế tạo tốt có thể thay đổi hành vi của chức năng định dạng, cho phép kẻ tấn công gây ra từ chối dịch vụ hoặc thực hiện các lệnh tùy ý.

Nếu ứng dụng sử dụng các Hàm định dạng trong mã nguồn, có thể diễn giải các ký tự định dạng, kẻ tấn công có thể khám phá lỗ hổng bằng cách chèn các ký tự định dạng vào một biểu mẫu của trang web. Ví dụ: nếu hàm printf được sử dụng để in tên người dùng được chèn vào một số trường của trang, trang web có thể dễ bị tấn công kiểu này, như được hiển thị bên dưới:

printf (userName);

Sau đây là một số ví dụ về Hàm định dạng, nếu không được xử lý, có thể khiến ứng dụng bị Tấn công Format string.

Định dạng chức năng Mô tả

  • fprint:Ghi printf vào một tệp
  • printf: Xuất ra một chuỗi được định dạng
  • sprintf: In thành một chuỗi
  • snprintf: In thành một chuỗi kiểm tra độ dài
  • vfprintf: In cấu trúc va_arg vào một tệp
  • vprintf: In cấu trúc va_arg sang stdout
  • vsprintf: In va_arg thành một chuỗi
  • vsnprintf: In va_arg vào một chuỗi kiểm tra độ dài

Dưới đây là một số tham số định dạng có thể được sử dụng và kết quả của chúng:

  • ”% x” Đọc dữ liệu từ ngăn xếp
  • ”% s” Đọc các chuỗi ký tự từ bộ nhớ của tiến trình
  • ”% n” Ghi một số nguyên vào các vị trí trong bộ nhớ của tiến trình

Để khám phá xem ứng dụng có dễ bị tấn công kiểu này hay không, cần phải xác minh xem hàm định dạng có chấp nhận và phân tích cú pháp các tham số Format string được hiển thị trong bảng 2 hay không.

Bảng 2. Các tham số phổ biến được sử dụng trong một cuộc tấn công Format string.

  • %%% ký tự (nghĩa đen) tham chiếu
  • % p Biểu diễn bên ngoài của một con trỏ đến vô hiệu Tham chiếu
  • % d thập phân
  • % c Ký tự
  • % u thập phân không dấu
  • % x thập lục phân
  • % s Tham chiếu chuỗi
  • % n Ghi số vào một tham chiếu con trỏ

Ví dụ về Format string attack

#include  <stdio.h> 
void main(int argc, char **argv)
{
	// This line is safe
	printf("%s\n", argv[1]);

	// This line is vulnerable
	printf(argv[1]);
}

Mã an toàn

Dòng printf (“% s”, argv [1]); trong ví dụ là an toàn, nếu bạn biên dịch chương trình và chạy nó:

/example "Hello World %s%s%s%s%s%s"

Printf ở dòng đầu tiên sẽ không diễn giải “% s% s% s% s% s% s” trong chuỗi đầu vào và kết quả đầu ra sẽ là: “Hello World% s% s% s% s% s% s ”

Mã dễ bị tổn thương

Dòng printf (argv [1]); trong ví dụ này là dễ bị tấn công, nếu bạn biên dịch chương trình và chạy nó:

./example "Hello World %s%s%s%s%s%s"

Printf trong dòng thứ hai sẽ diễn giải% s% s% s% s% s% s trong chuỗi đầu vào dưới dạng tham chiếu đến con trỏ chuỗi, vì vậy nó sẽ cố gắng diễn giải mọi% s dưới dạng một con trỏ đến một chuỗi, bắt đầu từ vị trí của bộ đệm (có thể là trên Ngăn xếp). Tại một thời điểm nào đó, nó sẽ đến một địa chỉ không hợp lệ và việc cố gắng truy cập nó sẽ khiến chương trình gặp sự cố.

Payload khác nhau

Kẻ tấn công cũng có thể sử dụng điều này để lấy thông tin chứ không chỉ làm hỏng phần mềm. Ví dụ, đang chạy:

./example "Hello World %p %p %p %p %p %p"

Sẽ in các dòng:

Hello World %p %p %p %p %p %p
Hello World 000E133E 000E133E 0057F000 CCCCCCCC CCCCCCCC CCCCCCCC

Dòng đầu tiên được in từ phiên bản printf không dễ bị tấn công và dòng thứ hai từ dòng dễ bị tấn công. Các giá trị được in sau văn bản “Hello World”, là các giá trị trên ngăn xếp của máy tính của tôi tại thời điểm chạy ví dụ này.

Cũng có thể đọc và ghi vào bất kỳ vị trí bộ nhớ nào trong một số điều kiện và thậm chí cả thực thi mã.

Để biết thêm thông tin, vui lòng xem bài viết Khai thác lỗ hổng định dạng chuỗi từ năm 2001.

Các chức năng tương tự với printf

Toàn bộ họ hàm printf đều dễ bị tấn công. Đây là một ví dụ về

snprintf:

#include  <stdio.h>
void main(int argc, char **argv)
{
	char buf[100];
	snprintf(buf, sizeof buf, argv[1]);
}

Chạy chương trình này như sau sẽ gây ra sự cố.

./example "Hello World %s%s%s%s%s%s"

Cách sử dụng snprintf an toàn sẽ là:

snprintf(buf, sizeof buf, "%s", argv[1]);

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Contact Me on Zalo
Call now