Chuỗi định dạng là một chuỗi ký tự được kết thúc bằng null cũng chứa các từ chỉ định chuyển đổi được thông dịch hoặc chuyển đổi trong thời gian chạy. Nếu mã phía máy chủ nối thông tin đầu vào của người dùng với một chuỗi định dạng, thì kẻ tấn công có thể thêm các chỉ định chuyển đổi bổ sung để gây ra lỗi thời gian chạy, tiết lộ thông tin hoặc tràn bộ đệm.
Trường hợp xấu nhất đối với lỗ hổng chuỗi định dạng xảy ra trong các ngôn ngữ không kiểm tra đối số và cũng bao gồm trình xác định% n ghi vào bộ nhớ. Những chức năng này, nếu bị kẻ tấn công khai thác khi sửa đổi chuỗi định dạng, có thể gây tiết lộ thông tin và thực thi mã:
- C và C ++ printf và các phương thức tương tự fprintf, sprintf, snprintf
- Perl printf và sprintf
Các hàm chuỗi định dạng này không thể ghi vào bộ nhớ, nhưng những kẻ tấn công vẫn có thể gây tiết lộ thông tin bằng cách thay đổi các chuỗi định dạng để xuất ra các giá trị mà nhà phát triển không có ý định gửi:
Python 2.6 và 2.7 str.format và Python 3 unicode str.format có thể được sửa đổi bằng cách chèn các chuỗi có thể trỏ đến các biến khác trong bộ nhớ
Các hàm chuỗi định dạng sau có thể gây ra lỗi thời gian chạy nếu kẻ tấn công thêm các từ chỉ định chuyển đổi:
- Java String.format và PrintStream.format
- PHP printf
Mẫu mã gây ra lỗ hổng chuỗi định dạng là lệnh gọi hàm định dạng chuỗi có chứa thông tin đầu vào của người dùng chưa được kiểm soát. Ví dụ sau cho thấy cách gỡ lỗi printf có thể làm cho một chương trình dễ bị tấn công:
Ví dụ trong C:
char *userName = /* input from user controlled field */; printf("DEBUG Current user: "); // Vulnerable debugging code printf(userName);
Ví dụ trong Java:
final String userName = /* input from user controlled field */; System.out.printf("DEBUG Current user: "); // Vulnerable code: System.out.printf(userName);
Trong ví dụ cụ thể này, nếu kẻ tấn công đặt userName của họ có một hoặc nhiều chỉ định chuyển đổi, thì sẽ có hành vi không mong muốn. Ví dụ C sẽ in ra nội dung bộ nhớ nếu userName chứa% p% p% p% p% p và nó có thể làm hỏng nội dung bộ nhớ nếu có% n trong chuỗi. Trong ví dụ Java, tên người dùng có chứa bất kỳ mã xác định nào cần đầu vào (bao gồm% x hoặc% s) sẽ khiến chương trình gặp sự cố với IllegalFormatException. Mặc dù các ví dụ vẫn còn phải đối mặt với các vấn đề khác, nhưng lỗ hổng bảo mật có thể được khắc phục bằng các đối số printf của printf(“DEBUG Current user: %s”, userName).
Mục tiêu kiểm tra Format String Injection
Đánh giá xem việc đưa các chỉ định chuyển đổi chuỗi định dạng vào các trường do người dùng kiểm soát có gây ra hành vi không mong muốn từ ứng dụng hay không.
Làm thế nào để kiểm tra Format String Injection
Các bài kiểm tra bao gồm phân tích mã và đưa các thông số chuyển đổi vào làm đầu vào của người dùng cho ứng dụng đang được kiểm tra.
Phân tích tĩnh
Các công cụ phân tích tĩnh có thể tìm lỗ hổng chuỗi định dạng trong mã hoặc trong tệp nhị phân. Ví dụ về các công cụ bao gồm:
- C và C ++: Flawfinder
- Java: Quy tắc FindSecurityBugs FORMAT_STRING_MANIPULATION
- PHP: Trình phân tích định dạng chuỗi trong phpsa
Kiểm tra mã thủ công
Phân tích tĩnh có thể bỏ sót các trường hợp phức tạp hơn bao gồm các chuỗi định dạng được tạo bởi mã phức tạp. Để tìm kiếm các lỗ hổng trong cơ sở mã theo cách thủ công, người kiểm tra có thể tìm kiếm tất cả các lệnh gọi trong cơ sở mã chấp nhận chuỗi định dạng và truy tìm lại để đảm bảo đầu vào không đáng tin cậy không thể thay đổi chuỗi định dạng.
Injection chỉ định chuyển đổi
Người kiểm tra có thể kiểm tra ở cấp độ unit test hoặc kiểm tra toàn bộ hệ thống bằng cách gửi thông số chuyển đổi trong bất kỳ đầu vào chuỗi nào. Đánh lừa chương trình bằng cách sử dụng tất cả các chỉ định chuyển đổi cho tất cả các ngôn ngữ mà hệ thống đang thử nghiệm sử dụng. Nếu thử nghiệm không thành công, chương trình sẽ bị lỗi hoặc hiển thị kết quả đầu ra không mong muốn. Nếu quá trình kiểm tra vượt qua, nỗ lực gửi thông số chuyển đổi sẽ bị chặn hoặc chuỗi sẽ đi qua hệ thống mà không gặp sự cố nào như với bất kỳ đầu vào hợp lệ nào khác.
Các ví dụ trong các phần phụ sau đây có URL của biểu mẫu này:
https://vulnerable_host/userinfo?username=x
Giá trị do người dùng kiểm soát là x (đối với tham số tên người dùng).
Manual Injection
Người kiểm tra có thể thực hiện kiểm tra thủ công bằng trình duyệt web hoặc các công cụ gỡ lỗi API web khác. Duyệt đến ứng dụng web hoặc trang web sao cho truy vấn có các chỉ định chuyển đổi. Lưu ý rằng hầu hết các chỉ định chuyển đổi cần mã hóa nếu được gửi bên trong URL vì chúng chứa các ký tự đặc biệt bao gồm% và {. Kiểm tra có thể giới thiệu một chuỗi các mã xác định% s% s% s% n bằng cách duyệt với URL sau:
https: //rability_host / userinfo? username =% 25s% 25s% 25s% 25n
Nếu trang web dễ bị tấn công, trình duyệt hoặc công cụ sẽ nhận được lỗi, lỗi này có thể bao gồm thời gian chờ hoặc mã trả lại HTTP 500.
Mã Java trả về lỗi
java.util.MissingFormatArgumentException: Format specifier '%s'
Tùy thuộc vào việc triển khai C, quy trình có thể bị lỗi hoàn toàn với Lỗi phân đoạn.
Công cụ hỗ trợ Fuzzing
Các công cụ Fuzzing bao gồm wfuzz có thể tự động hóa các thử nghiệm fuzzing. Đối với wfuzz, hãy bắt đầu với một tệp văn bản (trong ví dụ này là fuzz.txt) với một đầu vào trên mỗi dòng:
Tệp fuzz.txt chứa những thứ sau:
alice %s%s%s%n %p%p%p%p%p {event.__init__.__globals__[CONFIG][SECRET_KEY]}
Một thông báo đầu vào hợp lệ để xác minh ứng dụng có thể xử lý đầu vào bình thường
Hai chuỗi với mã định nghĩa chuyển đổi giống C
Một chỉ định chuyển đổi Python để cố gắng đọc các biến toàn cục
Để gửi tệp đầu vào fuzzing tới ứng dụng web đang được kiểm tra, hãy sử dụng lệnh sau:
wfuzz -c -z file,fuzz.txt,urlencode https://vulnerable_host/userinfo?username=FUZZ
Trong lệnh gọi trên, đối số urlencode cho phép thoát phê duyệt cho các chuỗi và FUZZ (với các chữ cái viết hoa) cho công cụ biết vị trí giới thiệu các đầu vào.
Một đầu ra ví dụ như sau
Kết quả ở trên xác nhận điểm yếu của ứng dụng đối với việc đưa vào các chỉ số chuyển đổi giống C% s và% p.