Professional Documents
Culture Documents
LÊ THẾ HUY
NGHIÊN CỨU TỔNG HỢP CÁC CÔNG CỤ PHÁT HIỆN LỖI PHẦN
MỀM ĐỂ GIẢM CẢNH BÁO SAI
NGƯỜI HƯỚNG DẪN KHOA HỌC: PGS. TS. TRƯƠNG ANH HOÀNG
Hà Nội - 2020
1
MỤC LỤC
DANH MỤC HÌNH ẢNH .............................................................................................3
DANH MỤC BẢNG BIỂU ...........................................................................................4
DANH MỤC CÁC KÝ HIỆU VÀ CHỮ VIẾT TẮT ..................................................5
LỜI CẢM ƠN ................................................................................................................6
LỜI CAM ĐOAN ..........................................................................................................7
Chương 1. GIỚI THIỆU ĐỀ TÀI VÀ CÁC CÔNG CỤ SỬ DỤNG PHÂN TÍCH
MÃ NGUỒN ...................................................................................................................8
3.1.2. Phân tích theo từng danh mục chuẩn CWE .......................................43
3.1.3. Phân tích tổ hợp công cụ không theo chuẩn CWE .............................45
Hình 1.9: Lỗi đặt vi pham quy tắc đặt tên biến .............................................................17
Hình 2.15: Tệp dữ liệu đầu vào của công cụ SonarQube ..............................................33
Hình 2.19: Ví dụ mã nguồn có lỗi không mã hóa thông tin mật khẩu ..........................36
Bảng 3.2: Bảng phân tích đơn công cụ theo chuẩn CWE .............................................43
Bảng 3.3: So sánh phân tích đơn công cụ và phân tích tổ hợp công cụ ........................49
5
Biểu đồ 3.1: Biểu đồ tính hiệu suất của từng công cụ ...................................................43
API Application Programming Interface Giao diện lập trình ứng dụng
LỜI CẢM ƠN
Trước tiên học viên xin dành lời cảm ơn chân thành và sâu sắc đến thầy giáo,
PGS. TS. Trương Anh Hoàng và PGS. TS. Nguyễn Đức Anh – Hai thầy đã hướng dẫn,
chỉ bảo nhiệt tình và tạo điều kiện tốt nhất từ khi bắt đầu thực hiện đến khi kết thúc
công việc của mình.
Học viên xin dành lời cảm ơn chân thành đến các thầy cô khoa công nghệ thông
tin, trường Đại học Công Nghệ, ĐHQGHN đã tận tình đào tạo, cung cấp cho các kiến
thức vô cùng quý và bổ ích trong suốt thời gian hai năm học tại trường. Các thầy cô
luôn đồng hành và tạo điều kiện cho tất cả học viên được nghiên cứu và học hỏi theo
nguyên vọng của bản thân.
Đồng thời học viên cũng dành lời cảm ơn chân thành đến gia đình, bạn bè, đồng
nghiệp luôn động viên và bên cạnh trong suốt thời gian qua.
7
Lê Thế Huy
8
trình. Là một nền tảng mã nguồn mở giúp nhà phát triển có thể kiểm tra chất lượng mã
nguồn của dự án.
SonarQube được viết bằng java nhưng hỗ trợ các ngôn ngữ khác nhau: PHP,
Ruby, Java (bao gồm cả Android), C#, JavaScript, TypeScript, C/C++, Kotlin, Go,
COBOL, PL/SQL, PL/I, ABAP, VB.NET, VB6, Python, RPG, Flex, Objective-C,
Swift, CSS, HTML, và XML và hỗ trợ các cơ sở dữ liệu để lưu trữ kết quả: MySql,
Postgresql.
SonarQube hỗ trợ trong dự án việc đánh giá mã nguồn theo các tiêu chuẩn của
từng ngôn ngữ có trong dự án. Bên cạnh đó có thể thực hiện những việc sau:
• Phát hiện lỗi: phát hiện mã nguồn không dùng đến, các mã nguồn bị trùng
lặp.
• Tính toán độ bao phủ của mã nguồn theo kiểm thử đơn vị (Unit test - Unit-
test coverage) – Đó là cách tính toán trong kiểm thử hộp trắng đảm bảo rằng
tất cả các trường hợp trong mã nguồn đều được đảm bảo chạy qua khi chạy
thực tế.
• Tính toán trong việc các mã nguồn được sử dụng mang tính tạm thời không
được tối ưu để sử dụng lại và dễ bảo trì mã nguồn của hệ thống (Technical
Debt) – Nghĩa là giải quyết vấn đề một cách nhanh chóng không theo quy
chuẩn chỉ quan tâm đến kết quả. Giả sử đúng ra một giá trị phải khai báo là
hằng số để sử dụng chung cho các trường hợp khác nhưng khi sử dụng lại
dùng luôn giá trị chứ không khai báo biến hằng số. Ví dụ đoạn mã nguồn như
sau: if (message == “Nhập thiếu thông tin”) {} thay vào đó có thể khai báo
một biến là hằng số trong một lớp java như là Constant.java: public static
final String MESSAGE = “Nhập thiếu thông tin”; Như vậy ở bất kỳ đâu cần
sử dụng biến MESSAGE đều có thể sử dụng và khi thay đổi giá trị chỉ cần
thay đổi ở một chỗ thay vì phải vào nhiều đoạn mã để thay đổi.
• So sánh chất lượng mã nguồn so với các lần kiểm tra trước.
• Phát hiện lỗ hổng bảo mật.
• Kiểm tra độ phức tạp của mã nguồn.
Sonar gồm 4 thành phần [1]:
• Máy chủ tìm kiếm dựa trên Elasticsearch để sao lưu các tìm kiếm từ giao
diện người dùng.
• Máy chủ phụ trách xử lý các báo cáo phân tích mã nguồn và lưu chúng
vào cơ sở dữ liệu của SonarQube.
➢ Một cơ sở dữ liệu để lưu trữ:
• Cấu hình của SonarQube (bảo mật, cài đặt plugin,...).
• Ảnh chụp nhanh chất lượng của dự án, chế độ xem,...
➢ Nhiều plugin SonarQube được cài đặt trên máy chủ, có thể bao gồm ngôn
ngữ, SCM, tích hợp xác thực và quản trị.
➢ Một hoặc nhiều SonarScanners chạy trên máy chủ tích hợp liên tục và xây
dựng để phân tích dự án.
SonarQube Scanners là các plugin sẽ được chạy ở phía người dùng. Giúp thu
thập thông tin từ dự án, sinh các “thuộc tính" cho việc phân tích. Sau đó nó sẽ chạy bộ
phân tích SonarQube dựa trên các “thuộc tính” này. Tương ứng với mỗi công cụ quản
lý dựng (build management), sẽ có một Scanner tương ứng.
SonarQube Plugins bao gồm các plugin về ngôn ngữ lập trình, quản lý phiên
bản mã nguồn hoặc thậm chí là các plugin cho các công cụ phân tích mã nguồn khác
như PMD, FindBugs, jDepend, Android Lint, CheckStyle, WebDriver, ... Xem thêm
tại đây: https://docs.sonarqube.org/display/PLUG/Plugin+Library.
SonarQube hiện tại hỗ trợ cho 26 ngôn ngữ lập trình, do vậy sẽ có 26 plugin
tương ứng để phân tích mã nguồn cho loại ngôn ngữ đấy. Sau đây là hình ảnh minh
họa – hình 1.2:
Java đã cho và tạo ra cấu trúc dữ liệu tương đương: cú pháp cây (Syntax
Tree). Mỗi cấu trúc của ngôn ngữ Java có thể được biểu diễn bằng một thành
phần cụ thể cú pháp cây (Syntax Tree), chi tiết từng đặc điểm của nó. Mỗi
cấu trúc này được liên kết với một giao diện riêng mô tả rõ ràng tất cả các
đặc tính của nó. Khi tạo ra một luật, lớp IssuableSubscriptionVisitor sẽ được
thực thi, nó cung cấp các phương thức hữu ích để làm rõ các vấn đề cũng như
xác định chiến lược sẽ sử dụng khi phân tích một tệp. Nó dựa trên cơ chế
đăng ký (subscription mechanism), cho phép chỉ định loại cây mà luật này sẽ
phản ứng với. Các nút mà cần đảm bảo sẽ được duyệt được chỉ định bởi một
phương thức là nodesToVisit(). Từ đó SonarQube sẽ có được các thông tin
để bắt đầu xác định các lỗi có trong mã nguồn hay thực thi các luật.
• Sử dụng API (Using semantic API): Ngoài việc thực thi các luật dựa vào dữ
liệu được cung cấp bởi cú pháp cây (syntax tree), thì SonarQube cung cấp
càng nhiều thông tin hơn liên quan đến mã nguồn thông qua một mô hình
ngữ nghĩa của mã. Tuy nhiên mô hình này hiện chỉ hoạt động với mã nguồn
Java. Mô hình ngữ nghĩa này cung cấp thông tin liên quan đến từng ký hiệu
được thao tác. Ví dụ, đối với một phương thức, API ngữ nghĩa sẽ cung cấp
dữ liệu hữu ích như chủ sở hữu của phương thức, công dụng của nó, các loại
tham số và loại trả về của nó, ngoại lệ mà nó có thể ném,...
1.2.2. Công cụ phân tích HuntBugs
Công cụ phân tích mã Java bytecode dựa trên công cụ Procyon Compiler với
mục đích để thay thế FindBugs. Công cụ có thể chạy với maven, ant, gradle hoặc là
một plugin của Eclipse. Phiên bản mới nhất hiện nay là 0.0.11. Hiện tại dự án đã bị
hủy và không được hỗ trợ trong tương lai.
HuntBugs có một điểm yếu lớn là nó không thể quét được các lỗi mã nguồn
trong khi phát triển, chúng ta phải dựng hoặc đóng gói thì mới có thể quét được.
Việc tích hợp HuntBugs rất nhanh và dễ hiểu, việc quét các tệp lỗi và xuất ra
tệp báo cáo cũng rất nhanh, có thể xem kết quả ngay trên IDE tích hợp HuntBugs.
HuntBugs không như các công cụ khác và có hạn chế khi chỉ hỗ trợ quét lỗi dự án thực
hiện bằng ngôn ngữ Java.
Việc chạy công cụ HuntBugs giúp phát hiện một vài lỗi trong hệ thống nhưng
vẫn còn rất nhiều lỗi không bị phát hiện. Ngoài ra do hiện nay công cụ HuntBugs đã
không được hỗ trợ trong tương lai nên rất khó phát triển thêm.
1.2.3. Công cụ phân tích PMD [6]
PMD (Programming Mistake Detector) là một công cụ mã nguồn mở phân tích
mã nguồn tĩnh để tìm ra các vấn đề trong mã nguồn giúp cải thiện chất lượng mã
nguồn. PMD hỗ trợ các ngôn ngữ sau JavaScript, PLSQL, Apex, Python, Java.
PMD có thể phát hiện một số lỗi sau trong mã nguồn:
• Thân rỗng trong các khối lệnh try/catch/finally/switch và if/while.
• Mã nguồn không được sử dụng với các biến toàn cục, tham số, các hàm
mang tính chất đóng gói (private methods).
13
• Các biểu thức quá phức tạp, không cần thiết cho các câu lệnh điều kiện (if),
vòng lặp for và while.
• Tối ưu việc sử dụng String/String Buffer.
• Trùng lặp mã nguồn.
PMD plugins cho một số IDE sau: eclipse, NetBeans, IntelliJ, Maven,
JDeveloper, JBuilder, SonarQube. PMD plugins mới nhất có version 6.17.0.
Cách thức hoạt động:
1. Khi bắt đầu thực hiện chạy phân tích mã nguồn của dự án sẽ chạy vào lớp
chính (class main): net.sourceforge.pmd.PMD.
2. Truyền tham số cho dòng lệnh net.sourceforge.pmd.cli.PMDParameters.
Đồng thời tải tập tin bộ nhớ đệm (cache) để tăng cường việc phân tích.
3. Tải các bộ luật đã được định nghĩa sẵn hoặc do mình định nghĩa lại.
4. Xác định ngôn ngữ mình thực hiện phân tích. (Mỗi ngôn ngữ được hỗ trợ
một số bộ luật riêng hoặc giữa các ngôn ngữ có nhưng bộ luật trùng nhau).
5. Xác định các tệp (sử dụng thư mục nguồn đã cho, lọc theo phần mở rộng tệp
ngôn ngữ).
6. Chuẩn bị cho quá trình kết xuất kết quả.
7. Sắp xếp các tệp tin (file) theo tên.
8. Kiểm tra xem có thể sử dụng bộ nhớ đệm (cache) để thực việc phân tích (nếu
các quy tắc thay đổi thì việc làm trên sẽ không hợp lệ).
9. Chuẩn bị SourceCodeProcessor dựa trên cấu hình.
10. Phân tích các tệp tin (đơn luồng hoặc đa luồng) thực hiện trong
net.sourceforge.pmd.Processor.PMDRunnable:
Tạo luồng đầu vào
Gọi bộ xử lý mã nguồn net.sourceforge.pmd.SourceCodeProcessor:
• Xác định ngôn ngữ.
• Kiểm tra bộ nhớ đệm (cache) tệp đã được phân tích hay có sẵn.
• Phân tích mã nguồn. Kết quả là nút AST gốc.
• Luôn luôn chạy khách truy cập SymbolFacade. Nó xây dựng phạm vi,
tìm khai báo và tập quán.
• Chạy DFA (phân tích luồng dữ liệu – nếu có ít nhất một quy tắc yêu cầu)
để xây dựng biểu đồ luồng điều khiển và các nút luồng dữ liệu.
• Chạy TypeResolution (nếu có ít nhất một quy tắc yêu cầu).
• Chạy phân tích đa biến (nếu ít nhất một quy tắc yêu cầu).
• Thực hiện quy tắc luật:
✓ Trước tiên hãy chạy các quy tắc đã chọn cho cơ chế chuỗi quy tắc.
✓ Chạy tất cả các quy tắc khác và để chúng đi qua AST. Các quy tắc có
thể sử dụng bảng ký hiệu, thông tin độ phân giải và các nút DFA.
✓ Các quy tắc sẽ báo cáo các vấn đề được tìm thấy như vi phạm quy tắc
(Rule Violations).
14
11. Kết xuất các vi phạm được tìm thấy thành định dạng mong muốn (XML,
văn bản, HTML).
12. Phân tích bộ nhớ đệm lưu trữ.
13. Tùy thuộc vào số lượng vi phạm được tìm thấy, thoát với mã 0 hoặc 4.
1.2.4. Công cụ phân tích IntelliJ IDE
IntelliJ IDEA là công cụ nhằm tạo ra những dự án lập trình cho điện thoại hoặc
cho với khả năng mã hóa sâu sắc và điều hướng nhanh phần mềm còn cung cấp cho
người dùng một danh sách các biểu tượng và ký hiệu phục vụ trong công việc lập trình
của người dùng.
IntelliJ IDEA thực hiện phân tích dòng dữ liệu đầu vào của người dùng, phần
mềm phân tích lưu lượng dữ liệu để đoán biểu tượng thể loại thời gian phần mềm thực
hiện phân tích kịch bản được đưa vào của người dùng với các để xuất khác nhau tự
động thêm các lớp phôi để phù hợp với chương trình mà bạn đang làm việc.
IntelliJ IDEA là một IDE Java để phát triển các phần mềm máy tính. Công cụ
được phát triển bởi JetBrains (trước đây gọi là IntelliJ), nó được cấp phép Apache 2
cho phiên bản cộng đồng, và một phiên bản thương mại độc quyền. Cả hai có thể được
sử dụng cho phát triển thương mại.
Những tính năng chính:
• Lập trình các dự án cho điện thoại, java,…
• So sánh tìm kiếm các đoạn mã trùng nhau.
• Phân tích dữ liệu.
• Tìm kiếm nhanh chóng.
• Ứng dụng rộng rãi.
Ở vai trò là một công cụ phân tích mã nguồn tĩnh thì IntelliJ IDE có rất nhiều
ưu điểm vượt trội đáng chú ý. IntelliJ IDE cung cấp cho người sử dụng bản sửa lỗi
nhanh và thông minh. Vì vậy chất lượng mã nguồn luôn được đảm bảo ngay từ đầu mà
không làm gián đoạn quá trình viết mã nguồn theo yêu cầu của hệ thống. Từ đó giúp
cho các lập trình viên làm việc hiệu quả và tiết kiệm thời gian. Với hơn 600 mã nguồn
kiểm tra tự động giúp người dùng dễ dàng phát hiện các điểm mâu thuẫn khác nhau.
IntelliJ IDE chia các lỗi mã nguồn thành các nhóm lỗi để có thể xử lý tùy theo mục
đích của các dự án khác nhau. Sau đây học viên sẽ giới thiệu các nhóm lỗi mà IntelliJ
IDE đang chia ra [9]:
• Tìm lỗi có thể xảy ra: IntelliJ IDE phân tích mã người dùng đang nhập và
có khả năng tìm và sửa các lỗi có thể xảy ra không phải là “lỗi biên dịch”
ngay tức thì. Đây là một ví dụ về tình huống như vậy:
15
ứng hoặc luôn luôn là “đúng”. Trong trường hợp này, mã chịu trách nhiệm
không thể truy cập được và thực sự là mã không được sử dụng (mã “chết”).
và giúp bạn kiểm soát các phụ thuộc thông qua việc chia nhỏ mã của bạn
thành các module, sử dụng các phụ thuộc theo chu kỳ tạm thời, đánh dấu lỗi.
IntelliJ IDE cũng tìm kiếm các bản sao cấu trúc, ngay cả các bản sao “mờ”.
• Tuân thủ các hướng dẫn và tiêu chuẩn mã hóa: IntelliJ IDE cho phép tìm
ra các điểm mâu thuẫn khác nhau liên quan đến nhiều hướng dẫn và tiêu
chuẩn mã hóa, từ các tiêu chuẩn Java phổ biến đến bất kỳ tiêu chuẩn cụ thể
nào của công ty. Tất cả những nơi, ví dụ, tìm thấy sự không nhất quán của
Javadoc, đều được đánh dấu trong trình chỉnh sửa khi đang di chuyển. Sau
đây là ví dụ:
Hình 1.9: Lỗi đặt vi pham quy tắc đặt tên biến
Trong trường hợp này, dự án đã xác định rằng tất cả các hằng số trong dự án
phải bắt đầu bằng ký hiệu “_”. Bóng đèn màu vàng báo động rằng hằng số
không phù hợp với tiêu chuẩn riêng mà dự án đặt cho các tên như vậy.
IntelliJ IDE có thể giúp giải quyết vấn đề. Chỉ cần nhấn Alt + Enter và chọn
để đổi tên biểu tượng. Tất cả các cách sử dụng của biểu tượng này trong mã
cũng sẽ được đổi tên.
• Tuân theo thông số kỹ thuật: IntelliJ IDE nêu bật tất cả các vi phạm đặc
điểm kỹ thuật, như EJB, JSP, JSF,…. Không giống như sự mâu thuẫn về
nguyên tắc, vi phạm thông số kỹ thuật dẫn đến việc không thể triển khai ứng
dụng trên máy chủ. Đó là lý do tại sao điều quan trọng là phải tìm những địa
điểm mã như vậy ngay lập tức. Đây là một ví dụ:
Infer là công cụ tập trung vào lỗi hệ thống về null và dữ liệu, do đó nó không có
thông báo một số lỗi thông dụng hơn như:
• Lỗi trỏ ra ngoài mảng (Array bounds errors).
• Chuyển đổi kiểu dữ liệu lỗi từ kiểu này sang kiểu khác (Cast exceptions).
• Dùng dữ liệu không ổn (Leaking of tainted data). Ví dụ int a=0, b=a+b.
• Nhiều luồng sửa vào cùng nguồn dữ liệu vào cùng lúc (Concurrency race
conditions).
Cách thức hoạt động [2, 7]:
• Phương pháp tìm lỗi của chương trình dựa trên hai lý thuyết về hệ thống
chương trình - Separation và Bi-abduction.
✓ Separation dựa vào việc phân tích chương trình thành các hoạt động con
xử lý trên dữ liệu và sau đó kết hợp lại tất cả các hoạt động con này thành
trạng thái để có thể xem xét cuối cùng.
✓ Bi-abduction là phương pháp tìm kiếm các phần cần thiết để thỏa mãn
các ước đoán mà chúng ta cần kiểm tra.
• Cấu trúc này cho phép chương trình phân tích các đoạn mã một cách độc lập
và ít tương tác với nhau, đồng nghĩa với việc khi một khu vực mã bị thay đổi,
chỉ có các ước đoán và trạng thái của khu vực đó trở đi bị ảnh hưởng, tăng
tốc độ kiểm tra mã. Điểm yếu của nó là ở chỗ phương pháp này chỉ có thể áp
dụng cho các loại lỗi thuộc về cấu trúc, chứ không thể sử dụng cho tất cả các
loại lỗi có thể được phát hiện (ví dụ truy cập ngoài kích cỡ của mảng, chuyển
đổi kiểu giá trị gây ngoại lệ).
• Trong hoạt động thực tế (khi sử dụng lên các mã C++/Java), hệ thống chạy
bằng câu lệnh tương ứng, lúc này các công cụ biên dịch của hệ thống (clang,
javac, ant, make,...) sẽ bị thay bằng biên dịch của Infer để chạy phân tích.
Infer có 2 giai đoạn thực hiện:
✓ Chiếm lấy (Capture): Ở bước này, mã của chương trình sẽ được tạo
thành các đồ thị và hoạt động như trên, sau đó dữ liệu đó được lưu lại
trên đĩa cứng. Thông thường dữ liệu này ở thư mục infer-out, nhưng có
thể chọn được một thư mục khác bằng lệnh option -o. Lý do để có bước
này là bởi vì Infer hỗ trợ việc chỉ kiểm tra khu vực bị thay đổi thay vì
toàn bộ chương trình, do đó, cần phải lưu trữ dữ liệu từ các bước trước.
✓ Phân tích (Analyze): Ở bước này, dữ liệu từ bước chiếm lấy (Capture) sẽ
được phân tích để tạo ra báo cáo cần thiết. Nếu chỉ chạy cho phần dữ liệu
bị thay đổi, Infer sẽ được chạy với option --reactive, đưa đến tốc độ
nhanh hơn. Dù là kiểm tra toàn bộ hay cục bộ, phân tích sẽ in ra thông tin
lỗi và cảnh báo ra bàn điều khiển (console - stdout) và tệp infer-
out/bugs.txt ngoài ra, infer cũng có report.csv mang thông tin trên dưới
dạng tệp excel, csv.
21
chính xác một lỗi có chủ đích và thường ít nhất một cấu trúc không sai sót tương tự
như lỗ hổng có chủ đích – Tức là mã nguồn không có một lỗi nào cả để đối lập và
phân biệt với mã nguồn có lỗi trong bộ dữ liệu kiểm thử. Các cấu trúc không sai sót
được sử dụng để xác định xem liệu các công cụ có thể phân biệt sai sót với không sai
sót hay không. Ví dụ: một trường hợp thử nghiệm minh họa một loại lỗ hổng tràn bộ
đệm. Mã lỗi trong trường hợp thử nghiệm chuyển cho hàm C strcpy một bộ đệm đích
nhỏ hơn chuỗi nguồn. Cấu trúc không sai sót chuyển một bộ đệm đích đủ lớn để
strcpy. Các trường hợp thử nghiệm do CAS tạo ra và được sử dụng để nghiên cứu các
công cụ phân tích tĩnh được gọi là bộ thử nghiệm Juliet. Chúng được công bố rộng rãi
thông qua Viện Tiêu chuẩn và Công nghệ Quốc gia (NIST) tại
http://samate.nist.gov/SRD/testsuite.php.
Bộ dữ liệu Juliet Testsuite phiên bản 1.3 được chọn để đưa vào thử nghiệm vì nó
không chỉ giới hạn ở 10 lỗ hổng hàng đầu không giống như tập dữ liệu kiểm tra mã
nguồn chuẩn OWASP (OWASP là viết tắt của Open Web Application Security Project
– là tổ chức phi lợi nhuận và đưa ra chuẩn OWASP phục vụ công việc pentest hiệu quả
và chi tiết). Ngoài ra, bộ thử nghiệm được thiết kế cho tất cả các điểm yếu và không
chỉ giới hạn ở các điểm yếu dựa trên web như OWASP. Một trong những mục tiêu để
phát triển bộ thử nghiệm Juliet là cho phép nghiên cứu thực nghiệm dựa trên các bộ
thử nghiệm lớn. Các nhà nghiên cứu đã bắt đầu sử dụng các phiên bản của bộ thử
nghiệm Juliet để đánh giá phân tích mã nguồn [4, 12]. Bộ thử nghiệm Juliet phiên bản
mới nhất (phiên bản 1.3) tổng hợp 64099 trường hợp thử nghiệm trong C/C++ và
28881 trường hợp thử nghiệm trong Java.
1.5. Các lớp yếu điểm(CWE)
CWE là viết tắt của Common Weakness Enumeration - bảng liệt kê yếu điểm
chung của phần mềm do cộng đồng phát triển. Mục đích là phục vụ như một tiêu
chuẩn chung cho những người làm việc với phần mềm. Sau đây sẽ là một vài ví dụ để
hiểu hơn về các lỗi được định nghĩa trong CWE:
Ví dụ 1: Tràn bộ đệm dựa trên ngăn xếp (CWE-121) và tràn bộ đệm dựa trên lớp
(CWE-122) đều được đặt trong lớp điểm yếu xử lý bộ đệm. Do đó, tất cả các trường
hợp thử nghiệm liên quan đến các mục 121 và 122 của CWE được ánh xạ tới lớp điểm
yếu xử lý bộ đệm.
Ví dụ 2: SQL Injection là một kỹ thuật chèn mã có thể phá hủy cơ sở dữ liệu. Có
câu lệnh sau để khi thực hiện yêu cầu đăng nhập từ một hệ thống website
SELECT * FROM Users WHERE UserId = 105; người tấn công có thể bổ sung câu
như sau để câu lệnh trên luôn luôn thực hiện Select * from users where userId = 105 or
1 = 1; kỹ thuật tấn công như trên được định nghĩa với mã là CWE-89 (SQL Injection).
23
Tất cả các tệp dữ liệu đều được chuẩn hóa để trở thành dữ liệu đầu vào cho các
bước phân tích tiếp theo.
2.1.3. Phân tích dữ liệu
Đưa các tệp dữ liệu chuẩn làm dữ liệu đầu vào phân tích theo các tiêu chí đã
được đề cập ở trên. Phân tích theo từng công cụ, phân tích bằng cách tổng hợp dữ liệu
từ các công cụ theo kiểu tổ hợp một công cụ kết hợp với các công cụ còn lại, kết hợp
hai công cụ, kết hợp ba công cụ,... từ đó đưa ra tổ hợp các công cụ nào sẽ cho kết quả
khả quan nhất. Tổng hợp so sánh các kết quả dưới dạng bảng.
Từ các kết quả phân tích để đưa ra đánh giá, gợi ý cho các nhà phát triển khi
thực hiện phân tích dự án cần sử dụng những công cụ nào sao cho phù hợp để đạt được
chất lượng và đảm bảo về mặt chi phí vận hành.
2.2. Tiến hành thử nghiệm
Là phần chính trong luận văn. Học viên sẽ tiến hành phân tích triển khai và
phân tích hạn chế đối với các công cụ phân tích tĩnh được tích hợp trong các IDE
nhằm tìm ra các lỗ hổng bảo mật cũng như những khuyết điểm trong mã nguồn theo
một số chuẩn chung.
Cấu trúc luận văn như sau. Phần 2.2 giải thích cách tiếp cận của học viên để
thực hiện nghiên cứu và cung cấp kết quả để từ đó đưa ra những kết luận đối với
những sự phát triển phần mềm sau này để đảm bảo được chất lượng sản phẩm, cũng
như mức độ an toàn và bảo mật của sản phẩm. Một phần luận văn thực hiện nghiên
cứu và chọn lọc các công cụ phân tích tĩnh như đã trình bày các kiến thức liên quan
của các công cụ trong chương 1. Trong phần 2.2.1, thực hiện nghiên cứu và chọn bộ
dữ liệu kiểm thử Juliet phiên bản 1.3 dành cho các ngôn ngữ java.
2.2.1. Bộ dữ liệu kiểm thử Juliet phiên bản 1.3
Cấu trúc của mã nguồn được chia thành các thư mục tên của mỗi thư mục là đại
diện cho các lớp điểm yếu (CWE). Dưới đây là hình ảnh đại diện một vài thư mục nằm
trong bộ mã nguồn.
25
➢ Trong cú pháp mã nguồn java khi dấu “{” được mở sẽ phải có dấu “}” đóng
tương ứng. Từ quy luật trên xác định được phạm vi của mã lỗi trong một
phương thức. Trong hình 2.13 có 7 lỗi được báo cáo trong tệp tin java
CWE113_HTTP_Response_Splitting__connect_tcp_addCookieServlet_01
tại lần lượt các dòng 49, 107, 128, 130, 153, 211, 223. Trong khi đó phương
thức bad() trong tệp tin trên bắt đầu từ dòng 35 đến dòng 112 như vậy chỉ có
2 lỗi được tìm đúng đó là lỗi ở dòng 49 và dòng 107. Từ đó chỉ số TP = 2 và
chỉ số FP = 5.
2.2.5. Thực hiện phân tích dữ liệu
Sử dụng công cụ đã tạo ra ở phần 2.2.4 để thực hiện phân tích và tính hiệu suất
phát hiện lỗi của các công cụ theo các chỉ số sau: TP, FP, Recall, Precision,
Discrimination, Discrimination Rate.
2.2.5.1. Phân tích đơn công cụ không theo chuẩn CWE
Input: tệp tin kết quả của các công cụ dạng csv đã được chuẩn hóa phần 2.2.3.
Output: là kết quả tính các chỉ số TP, FP, Recall, Precision, Discrimination,
Discrimination Rate.
Ví dụ: với tệp tin đầu vào của SonarQube
/ (TP + FP). Tính chỉ số Discrimination quét toàn bộ tệp tin trên nếu cả 11 lỗi tìm được
đều được tính là TP thì được giá trị Discrimination = 1, tương tự quét và phân tích các
tệp tin java khác được tìm ra là có lỗi và đưa ra kết quả cuối cùng của Discrimination.
Sau khi tính được Discrimination thì giá trị của Discrimination Rate = Discrimination /
(TP + FN). Trong nghiên cứu đo hiệu suất phát hiện lỗi của các công cụ tập trung và
hướng đến phân tích 2 chỉ số sau: Recall (Độ bao phủ mã nguồn), Precision (Hiệu suất
tìm lỗi chính xác).
2.2.5.2. Phân tích đơn công cụ theo chuẩn CWE
Trong nghiên cứu học viên sử dụng 12 chuẩn CWE để tính hiệu suất phát hiện
lỗi của các công cụ:
Xác thực và kiểm soát truy cập (Authentication and Access Control): người
tấn công có thể dành quyền truy cập vào hệ thống nếu không có cơ chế xác thực và
kiểm soát truy cập thích hợp. Kiểm tra lớp điểm yếu này để biết rằng mã nguồn có
đang ngăn chặn truy cập trái phép vào hệ thống không. Một số lớp CWE được sử dụng
trong nghiên cứu: CWE-15, CWE-222, CWE-223, CWE-247, CWE-256, CWE-259,
CWE-272, CWE-284, CWE-491, CWE-500, CWE-549, CWE-566, CWE-582, CWE-
605, CWE-607, CWE-643, CWE-620. Đặc điểm của bộ dữ liệu kiểm thử chứa các thư
mục và tệp tin mang nhưng lỗi và lớp điểm yếu đã được định nghĩa. Ví dụ: thư mục
sau CWE15_External_Control_of_System_or_Configuration_Setting tương ứng với
lớp CWE-15 thuộc lỗi xác thực và kiểm soát truy cập. Giả sử có tệp dữ liệu đầu vào là
kết quả chuẩn hóa của công cụ SonarQube phân thích như sau:
Hình 2.19: Ví dụ mã nguồn có lỗi không mã hóa thông tin mật khẩu
Một số lớp CWE được sử dụng trong nghiên cứu: CWE-315, CWE-366, CWE-
367, CWE-382, CWE-383, CWE-479, CWE-483, CWE-572, CWE-606, CWE-609,
CWE-666, CWE-667, CWE-674, CWE-698, CWE-764. Ví dụ:
một khối bộ nhớ trước khi sử dụng nó để xây dựng một thông báo được gửi đến một
bên không đáng tin cậy. Ví dụ, các nhà phát triển thường sử dụng thông báo lỗi để
thông báo cho người dùng rằng đã xảy ra lỗi. Thật không may, nếu thông tin nhạy cảm
được cung cấp trong thông báo lỗi, kẻ thù có thể sử dụng nó để khởi động các cuộc tấn
công trong tương lai vào hệ thống. Một số lớp CWE được sử dụng trong nghiên cứu:
CWE-209, CWE-226, CWE-244, CWE-499, CWE-526, CWE-533, CWE-534, CWE-
535, CWE-539, CWE-591, CWE-598, CWE-614, CWE-615. Ví dụ:
Quét trong tệp tin đầu vào hình 2.24 có các lớp tương ứng nằm trong dữ liệu
đường dẫn tệp java bị lỗi hay không. Ví dụ đường dẫn của tệp tin java chứa lỗi
CWE404_Improper_Resource_Shutdown/CWE404_Improper_Resource_Shutdown__
console_InputStreamReader_01.java có chứa thông tin lớp là CWE404. Như vậy sẽ
lấy tất cả các thư mục có chứa CWE404 và phân tích các tệp java để tính ra chỉ số TP,
FP, Recall, Precision, Discrimination, Discrimination Rate – Thực hiện như phần tích
đơn công cụ không theo chuẩn CWE 2.2.5.1.
Injection: Là một cách tấn công khai thác lỗ hổng từ chính mã nguồn của dựa
án. Việc chèn mã có thể xảy ra khi người dùng nhập không được xác thực đúng cách.
Một trong những loại lỗi tiêm phổ biến nhất là tập lệnh chéo trang (XSS). Kẻ tấn công
có thể đặt các chuỗi truy vấn vào trường đầu vào có thể khiến dữ liệu không mong
muốn được hiển thị. Điều này thường có thể được ngăn chặn bằng cách sử dụng xác
thực đầu vào thích hợp hoặc mã hóa dữ liệu. Hay một ví dụ khác là SQL Injection là
một lỗi câu lệnh truy vấn thao tác với cơ sở dữ liệu bị khai thác như ví dụ 2 trong phần
1.5. Một số lớp CWE được sử dụng trong nghiên cứu: CWE-78, CWE-80, CWE-81,
CWE-83, CWE-89, CWE-90, CWE-113, CWE-129, CWE-134, CWE-426, CWE-427,
CWE-470, CWE-601, CWE-643. Ví dụ:
• Rabbit/Bacterium: Là một kiểu tấn công tự tái tạo liên tục để làm cạn kiệt tài
nguyên hệ thống.
• Logic bomb: Là một kiểu tấn công có chủ đích, khi người tấn công sử dụng
một đoạn mã được cố ý chèn vào một hệ thống phần mềm sẽ thiết lập một
chức năng độc hại khi đáp ứng các điều kiện cụ thể. Ví dụ: một lập trình viên
có thể ẩn một đoạn mã bắt đầu xóa tệp (chẳng hạn như trình kích hoạt cơ sở
dữ liệu lương), nếu họ bị chấm dứt hợp đồng với công ty.
• Trapdoor/Backdoor: Là một kiểu tấn công cho phép truy cập hệ thống trái
phép thông qua một số phần mềm, phương tiện, chức năng không được cấp
phép.
Một số lớp CWE được sử dụng trong nghiên cứu: CWE-111, CWE-114, CWE-
321, CWE-325, CWE-506, CWE-510, CWE-511, CWE-546. Ví dụ:
Quét trong tệp tin đầu vào hình 2.27 có các lớp tương ứng nằm trong dữ liệu
đường dẫn tệp java bị lỗi hay không. Ví dụ đường dẫn của tệp tin java chứa lỗi
CWE190_Integer_Overflow/s01/CWE190_Integer_Overflow__byte_console_readLin
e_add_01.java có chứa thông tin lớp là CWE190. Như vậy sẽ lấy tất cả các thư mục có
chứa CWE190 và phân tích các tệp java để tính ra chỉ số TP, FP, Recall, Precision,
Discrimination, Discrimination Rate – Thực hiện như phần tích đơn công cụ không
theo chuẩn CWE 2.2.5.1.
Xử lý con trỏ và tham chiếu (Pointer and Reference Handling): Con trỏ
thường được sử dụng trong mã nguồn để tham chiếu đến một khối bộ nhớ mà không
cần phải tham chiếu trực tiếp đến khối bộ nhớ. Một trong những lỗi con trỏ phổ biến
nhất là tham chiếu đến con trỏ NULL. Điều này xảy ra khi con trỏ được mong đợi để
trỏ đến một khối bộ nhớ, nhưng thay vào đó nó trỏ đến giá trị NULL. Điều này có thể
gây ra một ngoại lệ và dẫn đến sự cố hệ thống. Ví dụ con trỏ NULL gây lỗi hệ thống:
2.2.5.3. Phân tích tổ hợp các công cụ không theo chuẩn CWE
Tính tổ hợp chập 2, chập 3, chập 4 tệp dữ liệu của các công cụ lại với nhau để
tính TP, FP, Recall, Precision, Discrimination, Discrimination Rate từ đó đưa ra kết
quả khi thực hiện phân tích lỗi từng công cụ so với kết hợp nhiều công cụ sẽ cải thiện
như nào. Giả sử tổ hợp chập 2 tệp dữ liệu của các công cụ: SonarQube và HuntBugs
thì hai tệp dữ liệu của hai công cụ này kết hợp lại với nhau thành một tệp dữ liệu mới
từ đó phân tích tệp dữ liệu tổng hợp để tính ra các chỉ số.
Khi tổng hợp nhiều tệp tin sẽ xảy ra trường hợp một bản ghi có cùng đường dẫn
đến tệp tin lỗi, cùng lỗi từ dòng, cùng lỗi đến dòng. Chuyển đổi các bản ghi vào thành
một đối tượng trong java có ba thuộc tính sau: path, fromLine, toLine sau đó đưa các
đối tượng vào một cấu trúc dữ liệu giải thuật đó là Set từ đó sẽ lọc được các bản ghi
trùng nhau theo cả ba tiêu chí chuẩn hóa. Sau đó đưa danh sách Set đi phân tích duyệt
từng phần tử rồi đi so sánh với bộ dữ liệu kiểm thử để tính ra các chỉ số TP, FP,
Recall, Precision, Discrimination, Discrimination Rate – Thực hiện như phần tích đơn
công cụ không theo chuẩn CWE 2.2.5.1.
Ví dụ tổ hợp 2 tệp tin kết quả từ công cụ SonarQube và HuntBugs:
Bảng 3.2: Bảng phân tích đơn công cụ theo chuẩn CWE
Từ bảng 3.2 kết quả đo hiệu suất của các công cụ phân theo lớp yếu điểm CWE
chi tiết như sau:
Xác thực và kiểm soát truy cập (Authentication and Access Control):
• Độ bao phủ: IntelliJ IDE cao nhất với 53% và thấp nhất là SpotBugs 0%.
• Độ chính xác: Infer cao nhất với 100% và thấp nhất là SpotBugs là 0%.
44
• Độ chính xác: HuntBugs cao nhất với 100% và thấp nhất là Infer, SpotBugs
là 0%.
Xử lý số (Number Handling):
• Độ bao phủ: IntelliJ IDE cao nhất với 60% và thấp nhất là SpotBugs,
HuntBugs là 0%.
• Độ chính xác: SonarQube cao nhất với 54% và thấp nhất là SpotBugs,
HuntBugs là 0%.
Xử lý con trỏ và tham chiếu (Pointer and Reference Handling):
• Độ bao phủ: IntelliJ IDE cao nhất với 100% và thấp nhất là Infer, SpotBugs,
HuntBugs là 0%.
• Độ chính xác: PMD cao nhất với 60% và thấp nhất là Infer, SpotBugs,
HuntBugs là 0%.
Kết luận 1: Độ bảo phủ mã nguồn tốt nhất qua phân tích theo các lớp yếu điểm
CWE là IntelliJ IDE, độ đo hiệu suất phát hiện lỗi chính xác nhất với tần số xuất hiện
nhiều ở các yếu điểm CWE là SonarQube.
3.1.3. Phân tích tổ hợp công cụ không theo chuẩn CWE
Độ bao phủ cao nhất là 97% với tổ hợp các công cụ sau: SonarQube, IntelliJ
IDE.
Độ bao phủ thấp nhất là 4% với tổ hợp công cụ SpotBugs + Infer.
Độ chính xác cao nhất là 60% với tổ hợp công cụ SonarQube + SpotBugs.
Độ chính xác thấp nhất là 34% với tổ hợp công cụ SpotBugs + Infer.
3.1.4. Phân tích tổ hợp theo chuẩn CWE
Xác thực và kiểm soát truy cập (Authentication and Access Control):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ có hiệu suất thấp nhất với 4% là HuntBugs + SpotBugs.
• Độ chính xác có hiệu suất cao nhất với 100% là SpotBugs + Infer.
• Độ chính xác có hiệu suất thấp nhất với 54% là HuntBugs + PMD.
Chất lượng mã nguồn (Code quality):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ có hiệu suất thấp nhất với 0% là tổ hợp của các công cụ sau:
VCG, SpotBugs, Infer.
• Độ chính xác có hiệu suất cao nhất đạt 84% là HuntBugs + PMD + SpotBugs
• Độ chính xác có hiệu suất thấp nhất đạt 0% là tổ hợp của các công cụ sau:
Huntbugs, VCG, SpotBug, Infer.
Quản lý luồng kiểm soát (Control Flow Management):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp các công cụ sau:
SonarQube, IntelliJ IDE.
46
• Độ bao phủ có hiệu suất thấp nhất với 0% là tổ hợp của các công cụ sau:
HunBugs, SpotBugs, Infer.
• Độ chính xác có hiệu suất cao nhất đạt 53% là tổ hơp của các công cụ sau:
SonarQube + IntelliJ IDE, PMD + IntelliJ IDE.
• Độ chính xác có hiệu suất thấp nhất đạt 0% là tổ hợp của các công cụ sau:
HunBugs, SpotBugs, Infer.
Mã hóa và tính ngẫu nhiên (Encryption and Randomness):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ có hiệu suất thấp nhất với 0% là tổ hợp của các công cụ sau:
HunBugs, SpotBugs, Infer.
• Độ chính xác có hiệu suất cao nhất đạt 53% là tổ hợp của các công cụ sau:
HuntBugs + PMD, HuntBugs + IntelliJ IDE, HuntBugs + VCG, PMD +
VCG, PMD + SpotBugs, PMD + Infer, IntelliJ IDE + VCG, IntelliJ IDE +
SpotBugs, IntelliJ IDE + Infer, VCG + SpotBugs, VCG + Infer.
• Độ chính xác có hiệu suất thấp nhất đạt 0% là tổ hợp của các công cụ sau:
HunBugs, SpotBugs, Infer.
Xử lý lỗi (Error Handling):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ có hiệu suất thấp nhất với 0% là tổ hợp các công cụ sau:
HuntBugs + VCG + Infer, HuntBugs + SpotBugs + Infer, HuntBugs + VCG
+ SpotBugs.
• Độ chính xác có hiệu suất cao nhất đạt 72% là các tôt hợp sau: HuntBugs +
PMD, PMD + VCG, PMD + SpotBugs, PMD + Infer, IntelliJ IDE + VCG,
IntelliJ IDE + SpotBugs, IntelliJ IDE + Infer.
• Độ chính xác có hiệu suất thấp nhất đạt 0% là các tổ hợp sau: HuntBugs +
VCG + SpotBugs, HuntBugs + VCG + Infer, HuntBugs + SpotBugs + Infer,
IntelliJ IDE + VCG +SpotBugs, VCG + SpotBugs + Infer.
Xử lý tệp tin (File Handling):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ thấp nhất là 0% với tổ hợp công cụ SpotBugs + Infer.
• Độ chính xác cao nhất là 61% với tổ hợp công cụ sau: IntelliJ IDE + VCG
+SpotBugs, VCG + SpotBugs + Infer.
• Độ chính xác thấp nhất là 0% với tổ hợp công cụ SpotBugs + Infer.
Lỗi rò rỉ thông tin (Information Leaks):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ thấp nhất là 0% với tổ hợp công cụ sau: HuntBugs + SpotBugs +
Infer.
47
• Độ chính xác cao nhất là 65% với tổ hợp công cụ HuntBugs + PMD +
IntelliJ IDE + Infer.
• Độ chính xác thấp nhất là 0% với tổ hợp công cụ sau: HuntBugs + SpotBugs
+ Infer
Khởi tạo và đóng tài nguyên (Initialization and Shutdown):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE , PMD.
• Độ bao phủ thấp nhất là 0% với tổ hợp công cụ sau: HuntBugs + SpotBugs +
Infer
• Độ chính xác cao nhất là 88% với tổ hợp công cụ sau: SonarQube +
HuntBugs, SonarQube + SpotBugs, SonarQube + Infer.
• Độ chính xác thấp nhất là 0% với tổ hợp công cụ sau: HuntBugs + SpotBugs,
HuntBugs + Infer, SpotBugs + Infer
Injection:
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
• Độ bao phủ thấp nhất là 2% với tổ hợp công cụ SpotBugs + Infer.
• Độ chính xác cao nhất là 66% với tổ hợp công cụ SonarQube + Infer.
• Độ chính xác thấp nhất là 1% với tổ hợp công cụ SonarQube +Huntbugs +
IntelliJ IDE + VCG.
Phần mềm độc hại (Malicious Logic):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là các tổ hợp sau: SonarQube +
IntelliJ IDE, HuntBugs + IntelliJ IDE, PMD + IntelliJ IDE, IntelliJ IDE +
VCG, IntelliJ IDE + Infer.
• Độ bao phủ thấp nhất là 0% với tổ hợp công cụ HuntBugs + SpotBugs.
• Độ chính xác cao nhất là 71% với tổ hợp công cụ SonarQube + HuntBugs.
• Độ chính xác thấp nhất là 1% với tổ hợp công cụ SonarQube +Huntbugs +
VCG + SpotBugs.
Xử lý số (Number Handling):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là các tổ hợp sau: SonarQube +
IntelliJ IDE, HuntBugs + IntelliJ IDE, PMD + IntelliJ IDE, IntelliJ IDE +
VCG, IntelliJ IDE + Infer.
• Độ bao phủ thấp nhất là 0% với tổ hợp công cụ HuntBugs + SpotBugs
• Độ chính xác cao nhất là 54% với tổ hợp công cụ sau: SonarQube +
HuntBugs, SonarQube + SpotBugs.
• Độ chính xác thấp nhất là 0% với tổ hợp công cụ HuntBugs + SpotBugs.
Xử lý con trỏ và tham chiếu (Pointer and Reference Handling):
• Độ bao phủ có hiệu suất cao nhất đạt 100% là tổ hợp của các công cụ sau:
SonarQube, IntelliJ IDE, PMD.
48
• Độ bao phủ thấp nhất là 0% với tổ hợp công cụ sau: HuntBugs + SpotBugs +
Infer
• Độ chính xác cao nhất là 63% với tổ hợp công cụ sau: HuntBugs + PMD,
PMD + SpotBugs, PMD + Infer.
• Độ chính xác thấp nhất là 0% với tổ hợp công cụ sau: HuntBugs + SpotBugs
+ Infer.
Kết luận 2: Từ kết quả thí nghiệm tổ hợp các công cụ để phân tích đã cho thấy
sự kết hợp của SonarQube + PMD, PMD + IntelliJ IDE, SonarQube + IntelliJ IDE
mang lại các kết quả phân tích hiệu suất khá cao. Trong đó rất nhiều sự kết hợp mang
lại hiệu quả nhưng lại là sự kết hợp của nhiều công cụ. Do đó học viên tìm kiếm sự kết
hợp ít công cụ và đạt hiệu quả trên như tổ hợp hai công cụ như đã đề cập ở trên.
3.2. Đánh giá
3.2.1. Phân tích không theo chuẩn CWE
Khi thực hiện phân tích đơn công cụ thì cho kết quả:
• Độ bao phủ cao nhất là 86% thuộc về IntelliJ IDE.
• Độ chính xác cao nhất là 60% thuộc về SonarQube.
Khi thực hiện phân tích tổ hợp từ các công cụ thì cho kết quả:
• Độ bao phủ cao nhất là 97% thuộc về IntelliJ IDE và SonarQube.
• Độ chính xác cao nhất là 60% thuộc về SonarQube và SpotBugs.
Kết luận: Sự kết hợp hai công cụ IntelliJ IDE và SonarQube đã cho kết quả khả
quan hơn rất nhiều về độ bao phủ của mã nguồn.
49