Rủi ro / lỗ hổng bảo mật mà mỗi lập trình viên C phải nhận thức được là gì? [đóng cửa]


13

Có nhiều rủi ro bảo mật đến từ việc tiếp xúc gần với phần cứng trái ngược với việc sử dụng các API đã được kiểm chứng và chứng minh từ các ngôn ngữ lập trình cấp cao. Việc tạo ra lỗi tràn bộ đệm trong C sẽ dễ dàng hơn nhiều so với ngôn ngữ như Java.

Rủi ro hoặc lỗ hổng bảo mật (ví dụ như lỗi tràn bộ đệm) mà mọi lập trình viên C nên biết (lỗ hổng IE có liên quan đến lập trình viên C) là gì? Những vấn đề này có thể dẫn đến? Làm thế nào để tránh chúng, và những lỗi phổ biến gây ra những điều này xảy ra trong các chương trình là gì?


Điều gì về danh sách này: owasp.org/index.php/Carget:OWASP_Top_Ten_Project Còn gì cần thiết hơn thế này?
S.Lott

2
@ S.Lott: Có vẻ như rất nhiều về các vấn đề bảo mật trong phát triển web. Dường như có nhiều tài nguyên về điều đó nói chung hơn những gì tôi thực sự yêu cầu, dường như.
Anto

@Anto: Vui lòng cập nhật câu hỏi để phân biệt giữa tất cả các tài nguyên về bảo mật và bảo mật bạn đang hỏi về.
S.Lott

@ S.Lott: Tôi không chắc ý của bạn là gì. Tôi yêu cầu bảo mật có tầm quan trọng đối với hầu hết các lập trình viên C, nghĩa là, những thứ như tràn bộ đệm và những thứ khác có thể có trong C.
Anto

@Anto: "Dường như có nhiều tài nguyên hơn về [bảo mật web?] Nói chung so với những gì tôi thực sự yêu cầu" Có vẻ như bạn đang hỏi về một số bảo mật không phải là bảo mật web. Thật? Nếu vậy, xin vui lòng cập nhật câu hỏi để giải thích những gì bạn đang tìm kiếm. Sai? Sau đó, bạn đang hỏi về bảo mật web, trong trường hợp nào, tại sao danh sách OWASP không được đề cập trong câu hỏi của bạn?
S.Lott

Câu trả lời:


13

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 strchứa '%' khi được in. Các %nchỉ 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ì EOFsẽ 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.


Không cần sử dụng printf("%s", str)chuỗi trần khi puts(str)sẽ thực hiện cùng một công việc.
Blrfl

@Blrfl nhưng putsthêm một ký tự dòng mới trong khi printfkhông.
đúng

Cũng có thể làm fputs(str, stdout), mà không.
Blrfl

Đối với tràn số nguyên: Sử dụng ints đã ký là không có giải pháp, vì tràn chúng sẽ gây ra UB. Giải pháp duy nhất (đau đớn) là chính thức chứng minh rằng bạn sẽ không bao giờ tràn, hoặc kiểm tra khi chạy (nhưng kiểm tra chính xác, điều này cũng khó khăn mà không tràn vào kiểm tra).
sleske

@DavidThornley: C11 & C ++ 14 đã loại bỏ hàm get () khỏi thư viện chuẩn do tính nguy hiểm của nó.
Kẻ hủy diệt

5

Một số rủi ro cụ thể của C bao gồm: tràn bộ đệm , tấn công định dạng chuỗitràn số nguyên .


1
Không có gì cụ thể về C tràn bộ đệm - bất kỳ ngôn ngữ nào có con trỏ đều có thể có điều này. Tràn số nguyên áp dụng cho bất kỳ ngôn ngữ nào và cũng có thể dễ dàng xảy ra trong mã được quản lý.
Steve

1
@Steve, nó không thực sự là con trỏ gây ra vấn đề đó nhưng làm thế nào ngôn ngữ không thực thi giới hạn mảng.
Doug T.

2
@Steve câu hỏi không phải là hỏi về những thứ chỉ liên quan đến C, mà là điều mà các lập trình viên C nên biết.
Tấn

1
@Steve: C rất dễ bị tràn bộ đệm, một phần do thiếu hỗ trợ kiểm tra phạm vi và số lượng chức năng thư viện sẽ vui vẻ tràn bộ đệm cho bạn.
David Thornley

Tôi hiểu câu hỏi đang hỏi về C nói riêng, nhưng tôi nghĩ rằng nó đáng để làm rõ trong trường hợp câu trả lời được đọc ra khỏi bối cảnh rằng những rủi ro này là tổng quát hơn. Cụ thể, các nhà phát triển mã được quản lý (IMHO) quá tự mãn về bảo mật và đặc biệt là tràn số nguyên ảnh hưởng đến hầu hết các ngôn ngữ.
Steve

4

Đây là một rủi ro dễ bỏ lỡ có thể gây ra vấn đề sẽ mất hàng giờ để khắc phục.

Xem xét các mã sau đây, sẽ biên dịch không có vấn đề.

if(lpstr_current_state = CONST_EMERGENCY_STATE_HOLY_CRAP)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Khi bạn kiểm tra để xem nếu lpstr_current_statelà ở CONST_EMERGENCY_STATE_HOLY_CRAPbạn đang thực sự phân công. Tốt hơn là luôn luôn đặt biến không đổi ở bên trái. Khi bạn đặt hằng số ở bên trái, thì trình biên dịch sẽ thất bại vì bạn không thể gán giá trị cho một biến.

if(CONST_EMERGENCY_STATE_HOLY_CRAP = lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Sau đó, bạn có thể dễ dàng nói với chính mình, "Holy crap, điều đó có thể là xấu", trong khi sửa mã để đọc ...

if(CONST_EMERGENCY_STATE_HOLY_CRAP == lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

7
Điều đó dễ dàng cho trình biên dịch bắt và gắn cờ như một cảnh báo, không giống như một số vấn đề khác. Thật không may, không phải tất cả các trình biên dịch làm cho nó dễ dàng để làm.
David Thornley

2
Điều đó có thể xảy ra trong các ngôn ngữ khác ngoài C, bất kỳ ngôn ngữ nào sử dụng ===.
Thất vọngWithFormsDesigner

3
Đây cũng không thực sự là một lỗ hổng bảo mật, đây là một lỗi.
Chris Pitman

1
Chúng được gọi là điều kiện Yoda.

2
@Kristofer Hoch: Nếu chúng ta sẽ gọi bất kỳ lỗi C có khả năng nào là rủi ro và xem xét nó ở đây, chúng ta sẽ cần một diễn đàn lớn hơn nhiều.
David Thornley

0

Chỉ có một rủi ro bảo mật: Thực tế là có những người bên ngoài sẽ cố gắng hết sức để nắm bắt bất kỳ lỗ hổng nào trong phần mềm của bạn và khai thác nó để thu lợi riêng. Mọi thứ khác theo sau từ đó.

Vì vậy, khi bạn nghĩ rằng "không ai trong tâm trí của họ sẽ ...", thì bạn cần phải nghĩ ngay lập tức "ngoại trừ ai đó muốn hack vào máy tính của người khác sẽ làm chính xác điều đó".

Hậu quả lớn nhất là bất cứ khi nào bạn phản ứng với các sự kiện bên ngoài (ví dụ: bằng cách xử lý dữ liệu được gửi từ bên ngoài), bạn phải cho rằng dữ liệu này nằm dưới sự kiểm soát của kẻ thù tồi tệ nhất của bạn.


Mặc dù tôi sẽ đồng ý với đoạn hai và ba, nhưng việc đổ lỗi cho kẻ tấn công là một chút dày đặc trong mắt tôi. Nó luôn mất hai lần để tấn công thành công: Một lập trình viên bắt vít và một kẻ tấn công bắt được lập trình viên trong hành động. Tuy nhiên, lỗ hổng bảo mật là có trước khi kẻ tấn công có thể khai thác nó. Và vì điều đó, lập trình viên sẽ bị đổ lỗi.
cmaster - phục hồi monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.