Một số vấn đề về bảo mật khi xây dựng phần mềm bằng ngôn ngữ C/C++

    Các lỗ hổng bảo mật như Heartbleed, Zero-Day hay lỗ hổng bị khai thác bởi Ransomware như WannaCry đều có chung nguyên nhân gốc và thường gặp trong 2 ngôn ngữ lập trình phổ biến là C và C++. Một báo cáo từ Motherboard chỉ ra rằng vấn đề này xuất phát từ cái gọi là “memory unsafety” (tạm dịch là “bộ nhớ không an toàn”) tồn tại trong trong C/C++.

Memory Unsafety là gì ?

Giả sử trong một chương trình có một danh sách 10 phần tử chứa các giá trị số (number). Về mặt lý thuyết, nếu trong chương trình mà truy cập vào phần tử thứ 11 thì chương trình phải hiển thị thông báo lỗi mới chuẩn. Tuy nhiên trong các ngôn ngữ memory-unsafe như C và C++ thì chương trình sẽ tìm kiếm phần tử thứ 11 ở chỗ mà nó cho rằng phần tử đó tồn tại ở đó (mặc dù trên thực tế nó không tồn tại) và truy cập vào memory ở vị trí đó. Vấn đề này được gọi là “buffer overflow” và bị khai thác trong các lỗ hổng như HeartBleed. Và đó chưa phải là lỗ hổng duy nhất trong C/C++. Còn một số loại lỗ hổng “memory unsafety” khác trong C/C++ như sau →

  • Type confusion: nhầm lẫn giữa giá trị tồn tại trong bộ nhớ và kiểu dữ liệu của nó
  • Use after free: truy cập bộ nhớ sau khi đã giải phóng nó
  • Use of uninitialized memory: truy cập và sử dụng bộ nhớ khi chưa khởi tạo giá trị cho nó
Các lỗ hổng này rất phổ biến trong các phần mềm được sử dụng rộng rãi như Firefox, Chrome, Windows, Android iOS.

Vậy tại sao C/C++ vẫn được sử dụng rất nhiều ?

Hiện nay chúng ta có một số ngôn ngữ lập trình bậc cao, có bộ nhớ an toàn (memory safe) ví dụ như Python, Java, Rust Swift. Nhưng chúng được sử dụng trong một số lượng dự án và phần mềm tương đối nhỏ hơn.

Các dự án phần mềm quan trọng và lâu đời như OpenSSL, Linux, các máy chủ web Apache và nhiều phần mềm nguồn mở khác được viết bằng ngôn ngữ C/C++, chúng đã có hàng chục năm tuổi, và chúng đã phát triển lớn dần theo thời gian. Vì vậy, viết lại chúng bằng một ngôn ngữ khác là một công việc cực kỳ khó khăn để làm. Các dự án lớn như vậy cần phải được migrated (chuyển đổi) từng bước, nó đòi hỏi rất nhiều thời gian, tiền bạc và công sức. Ngoài ra những thay đổi đồng bộ cũng cần phải được tiến hành trong các team phát triển phần mềm trên các công ty trên khắp thế giới – đó là một trở ngại cực kỳ lớn.

Ngôn ngữ C/C++ được biên dịch thẳng ra mã máy cộng với việc nó đẩy trách nhiệm quản lý memory cho developer (thằng nào khôn thì sống khỏe, thằng nào ngu thì chết) nên tốc độ thực thi của chương trình viết bằng C/C++ là rất nhanh.


Chém thì chém vậy thôi chứ nhiều người cũng không muốn quan tâm tới vấn đề security của C/C++, nhiều người trong số đó (trong đó có tôi) tin rằng các lỗ hổng không phải là lỗi của ngôn ngữ lập trình, mà đó là lỗi của các lập trình viên, tại chúng ta đang code QUÁ DỄ DÃI hoặc do dòng đời xô đẩy bắt buộc chúng ta phải dễ dãi mà thôi 🤪

— Phạm Minh Tuấn (Shun) —