7 Tổng kết
3.1 Các bước của quá trình phân tích tĩnh1
3.1.2 Công cụ áp dụng kỹ thuật mới
Phân tích tĩnh và phân tích động được đề cập trong tiểu mục 3.1.1 là những kỹ thuật nền tảng và được sử dụng nhiều trong việc xây dựng các công cụ kiểm tra, tìm kiếm lỗ hổng bảo mật. Tuy nhiên, chúng vẫn đòi hỏi có sự điều khiển sử dụng của những người có chuyên môn và tốn nhiều thời gian để cập nhật khi có thông tin về loại lỗ hổng bảo mật mới. Chính vì vậy, các kỹ thuật mới như AI, ML, DL ngày càng được nhiều nghiên cứu hướng tới để tăng khả năng tự động hóa và giảm thời gian xem xét mã nguồn.
WIRECAML. Trong bài nghiên cứu [15], tác giả Jorrit Kronjee phân tích khả năng áp dụng kĩ thuật học máy và phân tích tĩnh để nhận diện lỗ hổng trong mã nguồn của ngôn ngữ kiểu động PHP. Trọng tâm của nghiên cứu là về các lỗ hổng trong ứng dụng web, cụ thể là SQL injection (SQLi) và Cross-Site Scripting (XSS). Đóng góp chính của
Chương 3
nghiên cứu này chính là công cụ WIRECAML có thể phát hiện mã PHP dễ bị tấn công bằng cách sử dụng bộ phân loại xác suất và các đặc trưng được trích xuất bằng phân tích luồng dữ liệu. Kết quả của nghiên cứu cho thấy, so với các công cụ RIPS, PIXY thì WIRECAML cho kết quả chính xác hơn và đáng tin cậy hơn, dựa theo các chỉ số Precision, Recall và F1 được kiểm tra trên cùng bộ dữ liệu.
TAP. TAP là một mô hình phân tích và phát hiện lỗ hổng bảo mật PHP được dựa trên cơ chế phân tích token và kỹ thuật học sâu, được nghiên cứu bởi nhóm tác giả Fang Y của trường đại học Tứ Xuyên, Trung Quốc [10]. Ý tưởng chính của mô hình này là việc xem mã nguồn như một loại ngôn ngữ với mỗi “từ” có ý nghĩa phụ thuộc vào “ngữ cảnh” và ý nghĩa của các “từ” xung quanh. Mã nguồn sẽ được chuyển đổi thành các token, sau đó thông qua sự kết hợp của mô hình work2vec và LSTM để học các phát hiện các lỗ hổng bảo mật. Theo như trong bài báo nghiên cứu, kết quả thử nghiệm của TAP trên tập dữ liệu kiểm tra đều đạt giá trị cao hơn so với công cụ RIPS ở tất cả các chỉ số đánh gía (Precision, Recall, F1, accuracy, AUC).
Từ hai nghiên cứu trên, có thể thấy việc sử dụng những kĩ thuật giúp tận dụng được thông tin của lượng lớn dữ liệu mã nguồn có tiềm năng lớn trong việc giúp việc rà soát lỗ hổng bảo mật được chính xác và nhanh chóng hơn. Ở các mục tiếp theo, chúng tôi sẽ phân tích chi tiết hơn về các nghiên cứu cùng loại theo hai bước: biểu diễn mã nguồn và lựa chọn mô hình học máy.
3.2 Biểu diễn mã nguồn
Lựa chọn các kỹ thuật định hướng dữ liệu (data-driven technique) như học máy cho quá trình phân tích tự động trên mã nguồn đòi hỏi mã nguồn phải được biểu diễn ở dạng thích hợp, nhằm giúp các thuật toán này hoạt động hiệu quả và xác định được vị trí các lỗ hổng phát hiện trên mã nguồn. Có hai hình thức biểu diễn chính: tuần tự (sequence) và cấu trúc (structure).
Đối với biểu diễn dạng tuần tự, phần lớn các nghiên cứu [10, 16, 18] tiếp cận theo hướng chuyển đổi mã nguồn về dạng tương tự như ngôn ngữ tự nhiên để xử lí. Một trong số đó là phương pháp để học các mẫu đặc trưng của lỗ hổng một cách tự động được Xin Li trình bày trong bài báo [16]. Các chức năng và câu lệnh quan trọng có liên quan với nhau trong chương trình được xâu chuỗi theo thứ tự thực thi. Sau đó, bằng một bộ phân tích từ vựng (lexical analysis), họ đưa mã nguồn về một dạng biểu diễn trung gian tối thiểu (Minimum Intermediate Representation - MIR) tương tự như ngôn ngữ tự nhiên (Hình 3.2). Tiếp đến là bước ánh xạ dạng biểu diễn trung gian thành các vector giá trị. Giả thuyết được đặt ra là ngữ cảnh của một token chính là các token xuất hiện trước và sau nó, và các token xuất hiện trong cùng ngữ cảnh thường có chung ngữ nghĩa. Dựa trên giả thuyết này, các token được biểu diễn dưới dạng một phân bố quan hệ với các token còn lại. Các token tương tự về mặt ngữ nghĩa sẽ được ánh xạ tới các biểu diễn vector tương tự do có ngữ cảnh tương tự. Mô hình Continuous Bag-of-word (CBOW) được sử dụng để thu được biểu diễn vector phân tán (distributed vector representations).
Hình 3.2: Các bước chuyển đổi mã nguồn thành MIR
số hạn chế trong việc nắm bắt toàn diện ngữ nghĩa của chương trình để mô tả các lỗ hổng bảo mật đa dạng và phức tạp, bởi vì cấu trúc của mã nguồn mang tính logic của các thuật toán nhiều hơn là tính tự nhiên của ngôn ngữ. Về phương diện này thì những biểu diễn dạng cấu trúc như cây AST, đồ thị luồng dữ liệu và đồ thị luồng điều khiển thể hiện tốt hơn so với biểu diễn tuần tự.
Trong nghiên cứu [5], nhóm tác giả đề xuất biểu diễn thông tin mã nguồn bằng cây AST, đồng thời đưa ra phương pháp chuyển đổi thông tin được biểu diễn dưới dạng cấu trúc cây về dạng mảng một chiều (Hình 3.3, 3.4, 3.5). Nhờ đó, từng phần tử cụ thể trong mảng được xem như một đặc trưng (feature) và có thể được đưa trực tiếp vào thuật toán học máy, cho phép tận dụng mọi thông tin có được từ việc phân tích cây AST. Tuy vậy, lượng thông tin mà cây AST cung cấp là chưa đủ để nhận diện một số lỗ hổng có luồng thực thi phức tạp và tương tác với nhiều dữ liệu.
Nhằm mục đích giảm sự mất mát thông tin, Fabian Yamaguchi cùng những cộng sự của
Hình 3.3: Các bước của phương pháp biểu diễn mã nguồn bằng AST và lưu trong cấu trúc mảng.
mình đã nghiên cứu và đề xuất đồ thị CPG. Như đã trình bày chi tiết trong Mục 2.1, là sự tổng hợp từ các đồ thị AST, CFG, CDG, đồ thị CPG được đề xuất trong nghiên cứu cung cấp được thông tin từ nhiều góc độ về mã nguồn, bao gồm các luồng dữ liệu, luồng thực thi và cú pháp câu lệnh. Đồng thời, trong nghiên cứu còn nhấn mạnh lợi thế của việc lưu trữ đồ thị bằng các cơ sở dữ liệu đồ thị như Neo4j cho phép tác giả sử dụng ngôn ngữ truy vấn đồ thị Cypher giúp dễ dàng tìm kiếm các dấu hiệu của lỗ hổng bảo mật theo một mẫu bất kì. Chính vì những ưu điểm này mà đồ thị CPG được sử dụng bởi rất nhiều công trình về phân tích mã nguồn sau này [1, 3, 21, 22, 34].
Chương 3
Hình 3.4: Biểu diễn dữ liệu bằng cây AST
Hình 3.5: Lưu dữ liệu cây AST vào mảng
Ngoài việc tìm cách biểu diễn lại mã nguồn và tự động trích xuất đặc trưng từ đó cho các mô hình học máy, học sâu, một số nghiên cứu thực hiện đề xuất trực tiếp các đặc trưng để nhận diện lỗ hổng bảo mật. Ví dụ, nghiên cứu [24] đề xuất sẵn một bộ các thuộc tính đặc trưng nhận diện lỗ hổng. Sau đó, mã nguồn được phân tích theo phương pháp của Balzarotti [4] để xác định có hay không có sự tồn tại của từng đặc trưng: các thuộc tính thuộc về phân tích tĩnh được xem xét trước, nếu bị nghi ngờ không chính
xác, thực hiện phân tích động bằng cách mô phỏng lại hiệu ứng của các hàm có chức năng lọc dữ liệu nhận vào bằng cách thực thi đoạn mã với nhiều bộ dữ liệu kiểm tra khác nhau. Vector chứa các giá trị thể hiện thuộc tính đặt ra có hay không có trong mã nguồn đang xem xét chính là vector đặc trưng để đưa vào mô hình học máy phân loại.Tương tự, trong nghiên cứu [25], hai tác giả L. K. Shar và H. B. K. Tan cũng đề xuất một bộ các thuộc tính (Bảng 3.1) liên quan đến việc kiểm tra và sàng lọc giá trị đầu vào nhạy cảm, được lấy từ quá trình phân tích tĩnh mã nguồn của chương trình. Sau đó, thông tin về các thuộc tính này được sử dụng để huấn luyện mô hình dự đoán hai lỗ hổng bảo mật là SQL injection (SQLi) và cross site scripting (XSS). Điểm chung giữa hai nghiên cứu này là các đặc trưng dùng cho mô hình học nhận diện các lỗ hổng đều được định sẵn, dựa theo nghiên cứu hoặc kinh nghiệm về đặc điểm của một số lỗ hổng xác định. Việc tự định nghĩa một bộ các thuộc tính khiến cho độ chính xác của mô hình phụ thuộc nhiều vào việc các đặc trưng được đề ra có thể hiện được đặc điểm nhận diện của một lỗ hổng bảo mật hay không. Một nhược điểm nữa của việc sử dụng các đặc trưng được định sẵn là sự thiếu linh hoạt trong việc cập nhập lỗ hổng mới. Nếu muốn mô hình có thể nhận diện được một lỗ hổng chưa được phân tích, các bước như thu thập dữ liệu về lỗ hổng, phân tích đặc điểm, tổng quát hóa đặc điểm của lỗ hổng thành đặp trưng cụ thể đều phải làm thủ công và đưa liệu vào huấn luyện mô hình lại.
Chương 3
Bảng 3.1: Bộ thuộc tính mã nguồn được đề xuất.
Attribute Description
Client The number of nodes which access data from external users File The number of nodes which access data from files
Database The number of nodes which access data from database
Textdatabase Boolean value ‘TRUE’ if there is any textbased data accessed from database; ‘FALSE’ otherwise
Otherdatabase Boolean value ‘TRUE’ if there is any data except text-based data accessed from database; ‘FALSE’ otherwise
Session The number of nodes which access data from persistent data objects
Uninit The number of nodes which reference uninitialized program variable
SQL The number of SQL sink nodes HTML The number of HTML sink nodes
SQLIsanitization The number of nodes that apply language provided SQLI pre- vention functions
XSSsanitization The number of nodes that apply language provided XSS pre- vention functions
... ...
Vulnerable? Target attribute which indicates a class label—Vulnerable or Not-Vulnerable
3.3 Ứng dụng các kĩ thuật hướng dữ liệu3.3.1 Phương pháp học sâu 3.3.1 Phương pháp học sâu
Trong xây dựng công cụ nhận diện lỗ hổng bảo mật, một số nghiên cứu lựa chọn áp dụng kĩ thuật học sâu để tự động tạo ra các đặc trưng để phân loại mã nguồn. Ví dụ, nghiên cứu [16] được đề cập trước đó, coi mã nguồn như ngôn ngữ tự nhiên, sau đó sử dụng kết hợp các mô hình CNN để học các đặc trưng cần thiết. Cũng với phương pháp xử lí mã nguồn bằng học sâu, các nhà nghiên cứu của công cụ VulDeePecker [18] sử dụng ý tưởng từ LSTM để xây dựng nên mô hình mạng neuron phân loại mã nguồn.
3.3.2 Phương pháp học máy
Hầu hết các nghiên cứu khác [13, 25], không lựa chọn biểu diễn mã nguồn ở dạng cấu trúc tuần tự như ngôn ngữ tự nhiên, sẽ hướng đến cách vector hóa các thông tin có trong mã nguồn và thực hiện huấn luyện các mô hình học máy cơ bản để phân loại. Cách tiếp cận này đòi hỏi dữ liệu được vector hóa trong bước biểu diễn mã nguồn phải có giá trị thông tin cao do chất lượng phân loại của các mô hình học máy cơ bản phụ thuộc rất lớn vào điều này.
4
Phương pháp đề xuất
4.1 Phát biểu bài toán
Trong luận văn này, một công cụ thực hiện phân tích và dự đoán dự tồn tại của lỗ hổng trong mã nguồn được đề xuất và hiện thực. Dữ liệu được sử dụng làm đầu vào cho công cụ là các file mã nguồn có chứa hoặc không chứa lỗ hổng bảo mật. Kết quả mong đợi sau khi công cụ thực hiện phân tích xử lí trên mã nguồn đưa vào là dự đoán về sự tồn tại của lỗ hổng trong đó. Công cụ dự đoán lỗ hổng trên mã nguồn với sự hỗ trợ của học máy sẽ gồm ba bài toán chính cần giải quyết.
• Biểu diễn mã nguồn.
• Trích xuất đặc trưng từ biểu diễn của mã nguồn.
• Huấn luyện mô hình học máy để dự đoán lỗ hổng trong mã nguồn.
4.2 Mô tả Tập dữ liệu4.2.1 SARD 4.2.1 SARD
SARD (Software Assurance Reference Dataset) là một bộ dữ liệu liên tục được cập nhật và bổ sung từ gần hai trăm nghìn chương trình thử nghiệm với những lỗ hổng đã được ghi nhận với các trường hợp kiểm thử khác nhau, từ các chương trình tổng hợp nhỏ đến lớn. Tập dữ liệu SARD cho phép người dùng, các nhà nghiên cứu và các nhà phát triển đánh giá các công cụ và kiểm tra các phương pháp rà soát lỗ hổng được đề xuất.
Tập dữ liệu sử dụng trong luận văn này được lấy từ SARD, bao gồm các đoạn mã tổng hợp cho các lỗ hổng bảo mật SQLi và XSS của ngôn ngữ PHP, được tạo ra bởi một công cụ do Bertrand Stivalet xây dựng [27]. Các mẫu kiểm thử được chia thành hai loại: an toàn và không an toàn. Toàn bộ mã nguồn được chứa trong một file duy nhất, với thông tin về loại lỗ hổng và vị trí dòng chứa đoạn mã bị lỗi. Số lượng các file và phân bố của mỗi loại được thể hiện như trong Bảng 4.1.
Bảng 4.1: Phân bố các file theo loại lỗ hổng trong bộ dữ liệu
Phân loại SQLi (CWE-89) XSS (CWE-79)
An toàn 8640 6176
Không an toàn 912 3904
4.2.2 Xử lí Tập dữ liệu
Từ bảng thống kê 4.1, số lượng file an toàn và không an toàn của cả hai loại lỗi chênh lệnh tương đối lớn, nghĩa là đây là bộ dữ liệu không cân bằng (imbalance dataset). Điều này cho thấy mô hình học máy phân loại dựa trên tập dữ liệu này có khả năng không hiệu quả và chỉ số đo lường về độ chính xác sẽ không phản ánh đúng khả năng của mô hình. Để giải quyết vấn đề này, chúng tôi sử dụng phương pháp undersampling: đối với tập các file an toàn, chúng tôi sẽ lấy mẫu ngẫu nhiên để làm cho số lượng file của lớp an toàn ngang bằng với lớp không an toàn (lớp thiểu số). Điều này có nghĩa là chúng tôi chỉ sử dụng một tập hợp con ngẫu nhiên của các file an toàn này để tạo nên tập dữ liệu chính thức. Bên cạnh đó, vì số lượng tệp là rất lớn, việc lấy mẫu ngẫu nhiên này là cần thiết để tránh gặp phải vấn đề về bộ nhớ ở các bước sau. Bên cạnh đó, để đánh giá độ hiệu quả của mô hình, nhiều chỉ số liên quan khác ngoài độ chính xác đều sẽ được xem xét. Các chỉ số này sẽ được trình bày trong Chương??.
Sau đó, chúng tôi thực hiện chia tập dữ liệu đã qua xử lí thành các tập huấn luyện (training) / điều chỉnh (validating) / kiểm tra (testing) theo tỷ lệ tương ứng là 70%, 10% và 20%. Danh sách các file thuộc các tập dữ liệu với thông tin về dòng chứa lỗi và loại lỗi sau đó được “pickle” 1 và lưu trữ trong một file hệ thống. Điều này giúp tiết kiệm thời gian quét lại các thư mục lưu trữ file và các file được chia vào các tập vẫn được giữ cố định.
4.3 Biểu diễn thông tin mã nguồn
4.3.1 Mức độ chi tiết trong phân tích mã nguồn
Như đã đề cập ở Mục 3.2, khi sử dụng học máy để phát hiện lỗ hổng bảo mật, chúng ta cần biểu diễn mã nguồn theo cách có thể bảo toàn được đầy đủ nhất thông tin cú pháp và ngữ nghĩa liên quan đến lỗ hổng. Việc xác định mức độ chi tiết (granularity) để xem xét mã nguồn là bước đầu trong quá trình này.
Với tiêu chí đảm bảo thông tin về cấu trúc và mối liên hệ giữa các thành phần được toàn vẹn, lựa chọn đơn giản nhất chính là coi toàn bộ mã nguồn là một đơn vị để xem xét. Tuy nhiên, đối với một ứng dụng trong thực tế, số lượng mã nguồn là tương đối lớn. Điều này khiến việc phân tích không hiệu quả do chứa quá nhiều đoạn mã dư thừa và không cung cấp thông tin về lỗ hổng.
1Pickle là một phần quan trong trong thư viện của Python. Pickling là quá trình chuyển đổi một đối tượng phân cấp trong Python thành dạng binary. Pickle sử dụng cách thức chuyển đổi riêng (chỉ dành riêng cho Python), không gắn với bất cứ một chuẩn chuyển đổi nào.
Chương 4
Một lựa chọn khác là xem xét mã nguồn ở mức độ hàm, nghĩa là coi mỗi chức năng trong chương trình là một vùng riêng lẻ để phân tích. Ưu điểm của nó nằm ở việc các câu