Tràn bộ đệm là một lớn. Không có gì trong C được kiểm tra phạm vi theo mặc định, vì vậy rất dễ ghi đè lên bộ đệm. Có một chức năng thư viện tiêu chuẩn, gets()
không thể dừng lại khi tràn bộ đệm và hầu như không bao giờ được sử dụng.
Có một số kỹ thuật ở mức triển khai để cản trở việc khai thác, chẳng hạn như xáo trộn các khối heap, nhưng điều đó sẽ không ngăn chặn tràn bộ đệm trong bộ đệm cục bộ, thường có thể thực hiện những điều thú vị như thay đổi địa chỉ mà hàm sẽ quay trở lại.
Không có giải pháp chung tốt nào trong C. Nhiều hàm thư viện có các phiên bản sẽ giới hạn số lượng chúng sẽ viết. mặc dù tính toán có thể vụng về Có phần mềm có thể phát hiện lỗi tràn bộ đệm trong thử nghiệm, miễn là thử nghiệm thích hợp được chạy và tràn ngăn xếp thường sẽ hiển thị như một sự cố trong thử nghiệm. Ngoài ra, đó là vấn đề mã hóa và xem xét mã cẩn thận.
Một vấn đề liên quan là vấn đề ghi vào bộ đệm quá nhỏ bởi một ký tự, quên rằng một chuỗi C dài n ký tự yêu cầu n + 1 ký tự trong bộ nhớ, vì bộ '\0'
kết thúc. Nếu kẻ tấn công có thể quản lý để lưu trữ một chuỗi mà không có bộ kết thúc, bất kỳ hàm C nào mong đợi một chuỗi sẽ tiếp tục xử lý cho đến khi nó đạt đến một byte bằng 0, điều này có thể dẫn đến sao chép hoặc xuất ra nhiều thông tin hơn mong muốn (hoặc nhấn bộ nhớ được bảo vệ cho một cuộc tấn công DOS ). Giải pháp, một lần nữa, là nhận thức, chăm sóc và đánh giá mã.
Có một rủi ro khác với printf()
gia đình. Nếu bạn từng viết char * str; ... printf(str);
, bạn đang tự đặt ra vấn đề nếu str
chứa '%' khi được in. Các %n
chỉ thị định dạng cho phép printf()
để viết vào bộ nhớ. Giải pháp là printf("%s", str);
hay puts(str);
. (Ngoài ra, sử dụng C99 snprintf()
thay vì sprintf()
.)
Sử dụng các số nguyên không dấu, đặc biệt là các chỉ mục vòng lặp, có thể gây ra vấn đề. Nếu bạn chỉ định một giá trị âm nhỏ cho một dấu không dấu, bạn sẽ nhận được một giá trị dương lớn. Điều đó có thể làm suy yếu những thứ như chỉ xử lý N trường hợp của một cái gì đó, hoặc trong các chức năng hạn chế như strncpy()
. Kiểm tra tất cả các số nguyên không dấu. Bạn có thể muốn tránh unsigned short
, vì một giá trị lớn ở một trong số đó sẽ chuyển thành giá trị dương lớn trong một int
.
Đừng quên rằng một hằng ký tự, trong C, thực sự là một int
. Viết một cái gì đó như char c; while((c = getchar()) != EOF) ...
có thể dễ dàng thất bại, vì EOF
sẽ không thể được đại diện trong một char
.
Tôi có thể nghĩ ra nhiều lỗi C đặc trưng hơn, nhưng những lỗi này có thể gây ra vấn đề bảo mật.