Tìm lỗi bảo mật thông qua rà soát an toàn mã nguồn

16:20 | 02/04/2018

Hiện nay, phương pháp phổ biến để xác định các lỗ hổng bảo mật cho ứng dụng web là thực hiện kiểm thử xâm nhập. Tuy nhiên, người kiểm thử xâm nhập chỉ có thông tin về đường dẫn truy cập đến website và một số thông tin sơ bộ về chức năng. Rà soát an toàn mã nguồn là một quá trình để tìm ra các đoạn mã không an toàn nếu chúng tồn tại trong phần mềm thì có thể gây ra một lỗ hổng tiềm ẩn trong quá trình phát triển phần mềm.

Giới thiệu chung

Hiện nay, phương pháp phổ biến để xác định các lỗ hổng bảo mật cho ứng dụng web là thực hiện kiểm thử xâm nhập. Tuy nhiên, người kiểm thử xâm nhập chỉ có thông tin về đường dẫn truy cập đến website và một số thông tin sơ bộ về chức năng. Điều này khiến người thực hiện kiểm thử không có cái nhìn chi tiết về ứng dụng, dẫn đến kết quả kiểm thử có thể không được đầy đủ.

Trong khi đó, các tính năng của phần mềm ngày càng phức tạp, kiểm thử xâm nhập với hạn chế về phương tiện và công nghệ sẽ không thể đáp ứng được yêu cầu đảm bảo về mặt an toàn thông tin. Trong trường hợp này có thể sử dụng một phương pháp khác hiệu quả hơn, đó là rà soát an toàn mã nguồn (secure code review).

Rà soát an toàn mã nguồn là một quá trình để tìm ra các đoạn mã không an toàn nếu chúng tồn tại trong phần mềm thì có thể gây ra một lỗ hổng tiềm ẩn trong quá trình phát triển phần mềm.

Rà soát an toàn mã nguồn tập trung vào việc tìm kiếm các lỗ hổng về: xác thực (Authentication), Phân quyền (Authrization), cấu hình (Configuration), Quản lý phiên (Session Management), ghi nhật ký (Logging), Kiểm tra dữ liệu (Data validation), Xử lý lỗi và ngoài lệ (Error/Excaption handling), Mã hóa (Encryption), Business logic.

Người thực hiện rà soát an toàn mã nguồn phải là người có trình độ chuyên môn cao, có nhiều kinh nghiệm trong việc lập trình an toàn như: am hiểu nhiều ngôn ngữ lập trình, các nền tảng lập trình, am hiểu về các tiêu chuẩn và phương pháp lập trình an toàn.

Ngoài mã nguồn của ứng dụng, người thực hiện rà soát cũng cần có thêm các tài liệu liên quan đến thiết kế phần mềm, tài liệu về đặc tả chức năng. Các tài liệu này cho phép người thực hiện rà soát có cái nhìn toàn cảnh về ứng dụng.

Hiểu biết sâu sắc về ứng dụng giúp cho thực hiện rà soát sâu vào từng chức năng, từng luồng xử lý dữ liệu để xác định các lỗ hổng tiềm ẩn.

Rà soát an toàn mã nguồn và lợi ích

Khi nào nên rà soát an toàn mã nguồn

Vòng đời phát triển phần mềm (Software Development Life Cycle - SDLC) bao gồm 5 giai đoạn cơ bản: Phân tích yêu cầu (Requirement), Thiết kế (Design), Phát triển (Development), Thử nghiệm (Testing), Phát hành (Release).


Rà soát an toàn mã nguồn trên SDLC

Đa số các lỗ hổng có thể được phát hiện trong giai đoạn phát triển của SDLC. Ở giai đoạn này, các hàm, biến, lớp đang được hình thành. Sự liên kết và kế thừa giữa các đối tượng chưa phức tạp dẫn đến việc xử lý lỗi diễn ra nhanh chóng.

Việc thực hiện rà soát an toàn mã nguồn song song cùng với việc phát triển ứng dụng sẽ làm kéo dài giai đoạn phát triển. Tuy nhiên, điều này cũng mang lại nhiều lợi ích như các lập trình viên sẽ tuân thủ các tiêu chuẩn lập trình an toàn, mã nguồn đầu ra được đảm bảo về mặt chất lượng.

Các lỗ hổng được phát hiện ở giai đoạn cuối của SDLC thường mất nhiều thời gian để sửa lỗi. Ở giai đoạn này, các hàm, các lớp, các biến được kế thừa, sử dụng ở khắp nơi bên trong ứng dụng. Việc thay đổi có thể gây đổ vỡ cho một tính năng hoặc thậm chí cho cả ứng dụng đó. Lập trình viên cần thời gian để xử lý lỗi và xử lý các ảnh hưởng khác đi kèm. Tuy nhiên, một số những lỗ hổng đặc biệt như các lỗ hổng về logic xử lý chỉ có thể được phát hiện khi giai đoạn phát triển hoàn thành.

Vì vậy, rà soát an toàn mã nguồn nên được thực hiện bắt đầu từ giai đoạn phát triển và kết thúc sau khi giai đoạn phát triển kết thúc.

Lợi ích của rà soát an toàn mã nguồn

Chi phí: Chi phí cho việc khắc phục một lỗ hổng được phát hiện sau khi ứng dụng đã được phát hành là rất lớn. Nó bao gồm chi phí cho việc lập trình viên sửa lỗi, xử lý các ảnh hưởng của sự thay đổi, chi phí cho việc dừng dịch vụ để cập nhật, chi phí cho việc khắc phục các thiệt hại nếu lỗ hổng đã bị khai thác. Thậm chí, trong quá trình sửa lỗi, các lỗ hổng mới có thể được hình thành. Rõ ràng, khi các lỗ hổng được phát hiện sớm thì sẽ tiết kiệm được rất nhiều chi phí.

Sự tuân thủ: Một số các ứng dụng đặc biệt cần phải tuân thủ các tiêu chuẩn trước khi phát hành, ví dụ như các ứng dụng liên quan đến tài chính, ngân hàng thì cần phải tuân thủ tiêu chuẩn PCI (Payment Card Industry). Trong tiêu chuẩn có yêu cầu về mã nguồn, các ứng dụng cần phải được rà soát an toàn mã nguồn trước khi được phát hành. Việc thực hiện rà soát an toàn mã nguồn có thể giúp cho tổ chức có cơ hội tốt hơn để có được chứng nhận.

Việc thực hiện rà soát an toàn mã nguồn cũng làm cho các lập trình viên sẽ chú ý hơn đến các lỗi cơ bản trong khi lập trình. Việc này sẽ hình thành các thói quen lập trình và dần dần sẽ nâng cao được chất lượng đầu ra của các đoạn mã nguồn.

Uy tín: Rà soát an toàn mã nguồn sẽ loại bỏ được hầu hết các lỗ hổng bảo mật trước khi ứng dụng được phát hành. Điều này làm cho ứng dụng an toàn hơn khi thực hiện kiểm thử xâm nhập (Penetration Testing). Vì vậy, sẽ giảm khả năng ứng dụng bị tấn công và thỏa hiệp, ít có cơ hội gây thiệt hại về danh tiếng cho tổ chức.

Các phương pháp thực hiện rà soát an toàn mã nguồn

Về cơ bản, có hai phương pháp rà soát an toàn mã nguồn là sử dụng các công cụ rà soát an toàn mã nguồn tự động (Automation tools) hoặc là thực hiện công việc thủ công (Manual).

Thực hiện rà soát an toàn mã nguồn sử dụng các công cụ tự động

Đối với các lập trình viên

Đa số các lập trình viên thường chỉ quan tâm đến việc làm thế nào để ứng dụng có thể hoạt động và thực hiện đúng yêu cầu về mặt chức năng. Vấn đề an toàn thường được xem xét sau khi ứng dụng đã cơ bản hoạt động.

Lợi ích của việc phát hiện sớm các lỗ hổng là rất rõ ràng. Tuy nhiên, người thực hiện rà soát an toàn mã nguồn không thể liên tục làm việc với lập trình viên để chỉ ra các lỗi sai trong từng dòng mã. Việc rà soát an toàn mã nguồn được thực hiện song song với việc phát triển phần mềm khi có sự hỗ trợ của các công cụ tự động.

Các công cụ rà soát an toàn mã nguồn tự động có các thành phần cho phép tích hợp lên công cụ phát triển phần mềm của các lập trình viên. Nó cho phép nhắc nhở lập trình viên các về các lỗ hổng bảo mật ngay trong giai đoạn đang lập trình. Các công cụ này có thể gợi ý cách sửa lỗi một cách chi tiết đến từng dòng mã lệnh.

Đối với người thực hiện rà soát

Khi ứng dụng đã được lập trình xong chuyển sang bước thử nghiệm (Testing). Các công cụ tự động có thể hỗ trợ cho người thực hiện rà soát dò quét các lỗ hổng trong ứng dụng theo một bộ mẫu nhận dạng (signature).

Sử dụng các công cụ tự động mang lại những lợi ích sau:

  • Hỗ trợ nhiều ngôn ngữ và nền tảng lập trình: Hầu hết công cụ rà soát an toàn mã nguồn đều hỗ trợ đa ngôn ngữ và đa nền tảng. Điều này mang loại lợi ích cho các tổ chức/doanh nghiệp sử dụng nhiều ngôn ngữ và nền tảng lập trình khác nhau. Việc vận hành các công cụ này không tốn nhiều nguồn nhân lực.
  • Phát hiện nhiều lỗ hổng: Hầu hết các lỗ hổng đều có thể được phát hiện bằng các công cụ tự động. Các công cụ có chứa một bộ phân tích mã nguồn và bộ các mã nhận dạng các lỗ hổng. Nó cho phép phát hiện nhiều loại lỗ hổng khác nhau. Hơn nữa, nó còn liên tục được cập nhật để phát hiện được nhiều loại lỗ hổng mới hơn.
  • Tốc độ nhanh trên một khối lượng công việc lớn: Các công cụ tự động cho phép thực hiện rà soát an toàn mã nguồn cho nhiều ứng dụng cùng một lúc và gần như không giới hạn độ lớn của ứng dụng đó. Tốc độ xử lý rất nhanh nên có thể rút ngắn được thời gian thực hiện giúp đảm bảo được tiến độ của dự án.
  • Có khả năng lập lịch rà soát định kỳ theo yêu cầu: Các ứng dụng luôn được cập nhật, bổ sung và sửa đổi. Các công cụ có thể được thiết lập để tự động thực hiện quá trình rà soát an toàn mã nguồn và tự động xuất báo cáo.
  • Tích hợp với các công cụ lập trình: Công cụ rà soát an toàn mã nguồn tự động có các thành phần có thể tích hợp với các công cụ lập trình. Nó cho phép chỉ ra các lỗi và gợi ý cho các lập trình viên cách xử lý. Điều này có thể nâng cao nhận thức của các lập trình viên từ đó nâng cao chất lượng cả các đoạn mã nguồn.

Một số công cụ trả phí \ như:

  • Fortify của HP
  • IBM Security AppScan Source của IBM
  • Checkmark của Checkmark

Một số công cụ miễn phí như:

  • RIPS-Scanner (Hỗ trợ ngôn ngữ PHP)
  • FindBugs (Hỗ trợ ngôn ngữ Java)
  • OWASP ORIZON (Hỗ trợ ngôn ngữ Java, .NET, C)
  • OWASP Code Crawler (Hỗ trợ ngôn ngữ Java)

Thực hiện rà soát an toàn mã nguồn thủ công 

Với phương pháp này, người thực hiện rà soát sẽ xem xét toàn bộ mã nguồn của ứng dụng. Ngoài ra, cũng cần phải được nắm rõ các thông tin về thiết kế phần mềm, đặc tả chức năng, hướng xử lý.

Để thực hiện rà soát an toàn mã nguồn thủ công, người thực hiện cần phải trải qua các bước sau:

  • Xác định phạm vi:

Việc đầu tiên, người thực hiện rà soát phải xác định được phạm vi công việc của mình. Bằng cách tiếp cận với mã nguồn, các tài liệu thiết kế và đặc tả chức năng, người thực hiện rà soát phải trả lời được các câu hỏi:

  • Ứng dụng sử dụng ngôn ngữ lập trình gì?
  • Sử dụng nền tảng lập trình gì?
  • Ứng dụng có các chức năng gì?
  • Các luồng dữ liệu xử lý như thế nào?
  • Các lỗ hổng cần tìm kiếm là gì?

Ngoài đọc các tài liệu, người thực hiện nên trao đổi thông tin với các nhà phát triển. Qua đó sẽ giúp người thực hiện rà soát hiểu rõ cách tiếp cận của các nhà phát triển với một số vấn đề như xác thực, kiểm tra dữ liểu, luồng xử lý… Từ đó xác định được các điểm quan trọng trong vấn đề an toàn của ứng dụng.

Thực hiện rà soát an toàn mã nguồn

Trước tiên, người thực hiện cần xác định được mức độ ưu tiên của từng loại lỗ hổng. Tùy thuộc vào chức năng đặc thù của từng ứng dụng mà mức độ ưu tiên của từng loại lỗ hổng là khác nhau. Ví dụ, đối với các ứng dụng doanh nghiệp, quy trình và phân quyền là rất quan trọng. Người thực hiện rà soát an toàn mã nguồn cần ưu tiên tìm các lỗi liên quan đến Business logic và phân quyền.

Quá trình thực hiện nên có nhiều người tham gia và thực hiện một cách độc lập. Cách tiếp cận của mỗi người là rất quan trọng. Mỗi người có một cách tiếp cận riêng đối với ứng dụng, điều này dẫn đến những kết quả khác nhau nhưng thường liên quan đến nhau và khi nhiều người cùng thực hiện thì sẽ nâng cao chất lượng của công việc

Báo cáo

Sau khi các thành viên thực hiện xong việc rà soát, nhóm thực hiện cần phải chia sẻ về kết quả mà mình phát hiện được. Mỗi người thực hiện có cơ hội để được xem lại những phát hiện của người khác và trao đổi với mọi người về các phát hiện của mình và các hướng xử lý. Giai đoạn này cũng đảm bảo rằng tất cả các phát hiện đều được báo cáo.

Danh sách kết quả cuối cùng cần có đủ các thông tin mô tả chi tiết về lỗ hổng và phương pháp xử lý.

Các lợi ích mà phương pháp này mang lại:

  • Xác định các lỗi xử lý logic và thiết kế: Người thực hiện rà soát có một cái nhìn tổng quan và chi tiết đối với ứng dụng do đã được tiếp cận với mã nguồn, tài liệu thiết kế, tài liệu đặc tả chức năng. Khi đó, họ có thể kiểm tra sâu bên trong các dòng code, các luồng xử lý và hiểu được cách thức, các bước ứng dụng xử lý dữ liệu. Từ đó xác định được mức độ an toàn về mặt logic. Ngoài ra, cũng sẽ phát hiện được các lỗi liên quan đến việc không tuân thủ tài liệu thiết kế.
  • Kết quả chinh xác và chi tiết: Các công cụ tự động có thể phát hiện được các lỗ hổng liên quan đến việc xác thực (Authentication), Phân quyền (Authorization) và kiểm tra dữ liệu (Data validation). Tuy nhiên, nó không thể biết được việc phân quyền, xác thực, kiểm tra đầu vào như vậy đã đầy đủ và chính xác hay chưa. Rà soát an toàn mã nguồn thủ công có thể cho ra kết quả một cách chi tiết và chính xác đối với các lỗ hổng loại này.
  • Nâng cao kỹ năng và kiến thức: Nhiều người thực hiện rà soát an toàn ứng dụng là một cách tốt nhất để cho thể chia sẻ kinh nghiệm và nâng cao kỹ năng của người thực hiện.

Tuy nhiên, phương pháp này tồn tại một số nhược điểm như sau:

  • Không nhất quán: Việc rà soát được thực hiện bởi con người và phụ thuộc rất nhiều vào kỹ năng và kiến thức. Vì vậy nhiều người thực hiện rà soát sẽ cho kết quả khác nhau. Nhiều lần thực hiện rà soát cũng sẽ cho ra các kết quả khác nhau.
  • Chất lượng phụ thuộc vào người thực hiện: Công việc rà soát an toàn mã nguồn phụ thuộc vào sự kiên trì, tỉ mỉ và kiến thức về ngôn ngữ và nền tảng lập trình của người thực hiện.
  • Thời gian hoàn thành: Việc thực hiện thường đòi hỏi các lập trình viên phải tham gia để cung cấp thông tin cho người thực hiện rà soát. Ngoài ra, việc hoàn thiện báo cáo với khối lượng lớn dữ kiện thu thập được sau quá trình rà soát an toàn mã nguồn cũng mất nhiều thời gian của nhóm thực hiện.
  • Khối lượng công việc: Các ứng dụng có số lượng dòng mã lớn hơn 10 nghìn là một thách thức đối với người thực hiện rà soát. Đối với các ứng dụng lớn, phạm vi công việc thường chỉ có thể tập trung vào các lỗ hổng mức cao hoặc các chức năng quan trọng của ứng dụng.

Kết luận

Các ứng dụng có hàng nghìn đến hàng trăm nghìn dòng mã và chu kỳ phát triển ngày càng được rút ngắn. Tuy nhiên, thời gian để thực hiện rà soát an toàn mã nguồn thì vẫn không thay đổi, thậm chí có thể tăng lên do sự phức tạp của tính năng, nhiều luồng xử lý dữ liệu, nhiều lỗ hổng mới được phát hiện.

Hai phương pháp sử dụng các công cụ tự động và thực hiện thủ công có thể bổ trợ cho nhau.

Các công cụ tự động có thể giúp con người rút gọn thời gian để phát hiện các lỗ hổng phổ biến. Con người có thể kiểm chứng lại kết quả đầu ra của các công cụ tự động và phát hiện các lỗ hổng phức tạp mà các công cụ tự động không thể thực hiện được.