Các công cụ Trí tuệ nhân tạo như Bard, ChatGPT và Bing Chat là những tên tuổi lớn hiện nay trong danh mục Mô hình ngôn ngữ lớn (LLM) đang trên đà phát triển.
LLM được đào tạo trên các tập dữ liệu khổng lồ để có thể giao tiếp bằng cách sử dụng ngôn ngữ hàng ngày của con người làm lời nhắc trò chuyện. Với tính linh hoạt và tiềm năng của LLM, các công ty đang tích hợp chúng vào nhiều quy trình công việc trong ngành công nghệ để giúp cuộc sống của chúng ta tốt hơn và dễ dàng hơn. Một trong những tích hợp quy trình làm việc AI chính là plugin mã tự động hoàn thành, cung cấp khả năng thấy trước và tạo các mẫu mã phù hợp để mã hóa nhanh hơn và hiệu quả hơn.
Trong thị trường công cụ tạo mã AI hiện nay, có rất nhiều người chơi, bao gồm GitHub Copilot , Amazon CodeWhisperer , Google Cloud Code (Duet AI) , Blackbox AI Code Generation , v.v. Bài đăng trên blog này nêu ra các ví dụ về những cạm bẫy bảo mật phổ biến mà các nhà phát triển gặp phải khi sử dụng những công cụ như vậy.
Mục tiêu của bài viết này là nâng cao nhận thức và nhấn mạnh rằng mã được tạo tự động không thể được tin cậy một cách mù quáng và vẫn yêu cầu xem xét bảo mật để tránh gây ra các lỗ hổng phần mềm.
Lưu ý: một số nhà cung cấp gợi ý rằng công cụ tự động hoàn thành của họ có thể chứa các đoạn mã không an toàn.
Nhiều bài viết đã nhấn mạnh rằng các công cụ tự động hoàn thành tạo ra các lỗ hổng đã biết như IDOR , SQL SQL và XSS. Bài đăng này sẽ nêu bật các loại lỗ hổng khác phụ thuộc nhiều hơn vào ngữ cảnh của mã, nơi có khả năng cao AI sẽ tự động hoàn thành để đưa lỗi vào mã của bạn.
Công cụ tạo mã bảo mật và AI Các mô hình AI được đào tạo về mã thường được đào tạo trên các cơ sở mã lớn với nhiệm vụ chính là tạo ra mã chức năng.
Nhiều vấn đề bảo mật có cách giảm thiểu đã biết và xác định mà không ảnh hưởng đến mặt hiệu suất (ví dụ: có thể tránh việc tiêm SQL bằng cách không nối trực tiếp thông số/đầu vào của người dùng vào truy vấn) - và do đó, có thể bị xóa vì không có lý do gì để viết mã một cách không an toàn.
Tuy nhiên, nhiều vấn đề bảo mật phụ thuộc vào ngữ cảnh có thể an toàn tuyệt đối khi được triển khai dưới dạng chức năng nội bộ, trong khi khi tiếp xúc với đầu vào bên ngoài từ máy khách, chúng sẽ trở thành lỗ hổng và do đó khó có thể phân biệt được thông qua tập dữ liệu học tập của AI.
Trong những lỗ hổng như vậy, cách sử dụng mã cụ thể thường phụ thuộc vào các phần khác của mã và mục đích chung của ứng dụng.
Dưới đây là một số trường hợp và ví dụ sử dụng phổ biến mà chúng tôi đã thử nghiệm, cho thấy một số loại lỗ hổng sau:
Sau khi xem cách các công cụ tạo mã AI xử lý các trường hợp trên, chúng tôi đã thử kiểm tra khả năng của chúng trong việc tạo các bộ lọc bảo mật phù hợp và các cơ chế giảm thiểu khác.
Dưới đây là một số trường hợp và ví dụ sử dụng phổ biến mà chúng tôi đã thử nghiệm bằng cách cố tình yêu cầu mã bảo mật:
Nhiều ứng dụng bao gồm mã tìm nạp tệp trở lại người dùng dựa trên tên tệp. Sử dụng truyền tải thư mục để đọc các tệp tùy ý trên máy chủ là một phương pháp phổ biến mà kẻ xấu sử dụng để lấy thông tin trái phép.
Có vẻ hiển nhiên là phải vệ sinh tên tệp/đường dẫn tệp do người dùng nhập trước khi tìm nạp lại tệp, nhưng chúng tôi cho rằng đây là một nhiệm vụ khó khăn đối với mô hình AI được đào tạo trên các cơ sở mã chung - điều này là do một số bộ dữ liệu không cần phải làm như vậy. sử dụng các đường dẫn đã được dọn dẹp như một phần chức năng của chúng (thậm chí nó có thể làm giảm hiệu suất hoặc gây hại cho chức năng) hoặc không bị tổn hại bởi các đường dẫn chưa được dọn dẹp vì chúng chỉ dành cho mục đích sử dụng nội bộ.
Đề xuất công cụ AI (Google Cloud Code - Duet AI): Hãy thử tạo chức năng tìm nạp tệp cơ bản từ đầu vào của người dùng, sử dụng Google Cloud Code - Duet AI tự động hoàn thành. Chúng tôi sẽ để Duet AI tự động hoàn thành mã của chúng tôi, dựa trên tên chức năng và tuyến đường của chúng tôi -
Như chúng ta có thể thấy bằng màu xám, đề xuất tự động hoàn thành là sử dụng chức năng “ send_file ” của Flask, đây là chức năng xử lý tệp cơ bản của Flask.
Nhưng ngay cả tài liệu của Flask cũng nêu rõ “ Không bao giờ chuyển đường dẫn tệp do người dùng cung cấp ”, nghĩa là khi chèn trực tiếp thông tin đầu vào của người dùng vào chức năng “send_file”, người dùng sẽ có khả năng đọc bất kỳ tệp nào trên hệ thống tệp, chẳng hạn như bằng cách sử dụng các ký tự truyền tải thư mục chẳng hạn như “../” trong tên tệp.
Thực hiện đúng:
Việc thay thế chức năng “send_file” bằng chức năng “send_from_directory” an toàn của Flask sẽ giảm thiểu rủi ro truyền tải thư mục. Nó sẽ chỉ cho phép tìm nạp các tệp từ một thư mục được mã hóa cứng cụ thể (“xuất” trong trường hợp này).
Trong một số ngôn ngữ lập trình, chẳng hạn như PHP và NodeJS, có thể so sánh giữa hai loại biến khác nhau và chương trình sẽ thực hiện chuyển đổi loại ở hậu trường để hoàn thành hành động.
Các so sánh lỏng lẻo không kiểm tra hậu trường kiểu của biến và do đó dễ bị tấn công tung hứng kiểu kiểu hơn. Tuy nhiên, việc sử dụng các so sánh lỏng lẻo bản thân nó không được coi là một cách viết mã không an toàn - nó phụ thuộc vào ngữ cảnh của mã. Và một lần nữa, các mô hình AI rất khó có thể phân biệt được các trường hợp.
Đề xuất công cụ AI (Amazon CodeWhisperer): Ví dụ phổ biến nhất về việc tung hứng kiểu PHP là so sánh lỏng lẻo các mã thông báo/băm bí mật trong đó dữ liệu nhập của người dùng được đọc qua yêu cầu JSON (cho phép kiểm soát loại dữ liệu đầu vào) đạt đến mức so sánh lỏng lẻo (“ ” ) thay vì nghiêm ngặt (“ =”).
Khi xuất hiện, CodeWhisperer tạo ra các điều kiện so sánh lỏng lẻo trong các đề xuất tự động hoàn thành:
Việc so sánh lỏng lẻo của secret_token cho phép kẻ thù bỏ qua việc so sánh $data[“secret_token”] == “secret_token”. Trong khi gửi một đối tượng JSON có giá trị “secret_token” là True (boolean), kết quả so sánh lỏng lẻo cũng là True (ngay cả trên các phiên bản PHP mới hơn).
Ngay cả khi “gợi ý” công cụ (sử dụng nhận xét) để viết séc “một cách an toàn”, nó cũng không tạo ra đoạn mã chứa sự so sánh nghiêm ngặt -
Thực hiện đúng:
Chỉ khi chỉ định một so sánh nghiêm ngặt (“===”), chúng tôi mới được bảo vệ khỏi các cuộc tấn công tung hứng kiểu.
Các lỗ hổng trong cơ chế “Quên mật khẩu” rất phổ biến trong các ứng dụng SaaS và là nguyên nhân sâu xa đằng sau các CVE như
Cụ thể, lỗ hổng Va chạm ánh xạ trường hợp Unicode xảy ra khi đầu vào của người dùng được viết hoa hoặc viết thường trong biểu thức so sánh trong khi giá trị ban đầu của nó cũng được sử dụng trong mã. Một số ký tự khác nhau sẽ dẫn đến cùng một mã char khi được chuyển đổi. Ví dụ: “ß” và “SS” đều sẽ chuyển thành “0x00DF” khi được viết hoa.
Những trường hợp như vậy thường được sử dụng để bỏ qua/đánh lừa một số kiểm tra bảo mật bằng cách đánh lừa kiểm tra so sánh và sau đó sử dụng giá trị ban đầu khác với dự kiến. Những trường hợp này khá khó nắm bắt, đặc biệt khi có thể thực hiện được nhiều triển khai.
Đề xuất công cụ AI (GitHub Copilot): Một cơ chế đặc biệt dễ bị loại lỗ hổng này là cơ chế quên mật khẩu . Thông thường, việc chuẩn hóa thông tin nhập của người dùng thành chữ hoa hoặc chữ thường (trong địa chỉ email hoặc tên miền) khi thực hiện kiểm tra để tránh những sai lệch không mong muốn.
Ví dụ: xem mã do Copilot tạo cho chức năng quên mật khẩu (bên dưới) cho thấy rằng nó dễ gặp phải vấn đề này.
Mã của Copilot trước tiên tra cứu địa chỉ email viết thường:
Sau đó, khi thực hiện phần còn lại của quy trình, nó gợi ý như sau:
Như chúng ta có thể thấy, đề xuất tự động hoàn thành sẽ tạo một mật khẩu ngẫu nhiên và gửi nó đến địa chỉ email của người dùng. Tuy nhiên, ban đầu nó sử dụng phiên bản chữ thường của email người dùng để tìm nạp tài khoản người dùng, sau đó tiếp tục sử dụng email 'nguyên trạng' của người dùng ban đầu (không chuyển đổi chữ thường) làm mục tiêu của email khôi phục.
Ví dụ: giả sử kẻ tấn công sở hữu hộp thư đến cho “[email protected]” (“K” là ký tự unicode Kelvin Sign ) và sử dụng email này cho cơ chế “Quên mật khẩu”. Các email “[email protected]” và “[email protected]”, không tương đương 'nguyên trạng', nhưng sau khi chuyển đổi chữ thường, chúng sẽ -
Sử dụng địa chỉ email “[email protected]” sẽ lấy thông tin tài khoản cho “[email protected]” nhưng mật khẩu đặt lại sẽ được gửi đến hộp thư đến của kẻ tấn công (“[email protected]”), cho phép chiếm đoạt “ tài khoản [email protected]”.
Triển khai đúng cách: Địa chỉ email được sử dụng để tìm nạp tài khoản người dùng phải chính xác bằng địa chỉ email khôi phục (tức là tham số send_email cũng sẽ sử dụng email.low()).
Ngoài ra, để phòng ngừa, nên sử dụng giá trị đã được lưu trữ trong máy chủ thay vì giá trị do người dùng cung cấp.
Một chủ đề khác có thể gây nhầm lẫn cho các công cụ tự động hoàn thành là việc ghi tệp cấu hình, đặc biệt đối với cơ sở hạ tầng đám mây phức tạp.
Lý do chính là thực sự có những hướng dẫn thực hành tốt nhất về bảo mật, nhưng không phải ai cũng tuân theo chúng và trong một số trường hợp, cần phải đi ngược lại chúng. Các mẫu mã như vậy có thể được đưa vào tập dữ liệu đào tạo AI. Do đó, một số kết quả đầu ra tự động hoàn thành sẽ vi phạm các nguyên tắc bảo mật được đề xuất.
Trong ví dụ sau, chúng ta sẽ tạo tệp cấu hình cho Kubernetes Pod , đơn vị thực thi nhỏ nhất trong Kubernetes.
Đề xuất công cụ AI (Tạo mã Blackbox AI): Trong ví dụ này, chúng tôi bắt đầu tạo tệp cấu hình Pod.
Đề xuất tạo phần khả năng và thêm khả năng nhân Linux (SYS_ADMIN) vào vùng chứa về cơ bản tương đương với việc chạy nhóm với tư cách là người dùng root.
Triển khai đúng cách: Có tốt hơn nếu bỏ qua securityContext? Không - vì sau đó nhiều khả năng khác sẽ được thêm vào theo mặc định, vi phạm nguyên tắc đặc quyền tối thiểu .
Theo các phương pháp hay nhất về bảo mật của Docker , cách thiết lập an toàn nhất trước tiên là loại bỏ tất cả các khả năng của nhân Linux và chỉ sau đó thêm những khả năng cần thiết cho vùng chứa của bạn.
Để khắc phục các sự cố được đề cập ở trên, phần khả năng bắt đầu bằng cách loại bỏ tất cả các khả năng và sau đó sẽ dần dần thêm những khả năng cần thiết cho vùng chứa của chúng tôi.
Ca sử dụng: Đối tượng cấu hình - Sự không nhất quán dẫn đến quá trình khử tuần tự hóa không an toàn
Nhiều lỗ hổng yêu cầu xác định đối tượng cấu hình, đối tượng này quyết định cách ứng dụng xử lý thành phần được yêu cầu.
Ví dụ chúng tôi chọn là thư viện giải tuần tự hóa JSON của Newtonsoft trong C#, thư viện này có thể được sử dụng an toàn hoặc không an toàn tùy thuộc vào cấu hình của đối tượng JsonSerializerSettings và cụ thể là TypeNameHandling .
Trong khi kiểm tra mã khử lưu huỳnh, chúng tôi nhận thấy rằng định nghĩa của đối tượng cấu hình khá ngẫu nhiên và những thay đổi nhỏ có thể dẫn đến việc tạo ra một bộ cấu hình khác.
Đề xuất công cụ AI (Amazon CodeWhisperer): Các ví dụ sau hiển thị hành vi không nhất quán chỉ dựa trên tên phương thức được nhà phát triển sử dụng:
Chúng ta có thể thấy hai cấu hình khác nhau đều dẫn đến quá trình giải tuần tự hóa JSON không an toàn do thuộc tính TypeNameHandling là “Tự động” và “TẤT CẢ”. Các thuộc tính này cho phép tài liệu JSON xác định lớp được giải tuần tự hóa - cho phép kẻ tấn công giải tuần tự hóa các lớp tùy ý. Điều này có thể dễ dàng được tận dụng để thực thi mã từ xa, chẳng hạn như bằng cách giải tuần tự hóa lớp “System.Diagnostics.Process”. Sự khác biệt duy nhất trong mã gốc của nhà phát triển là tên phương thức.
Thực hiện đúng:
Theo mặc định, một đối tượng JsonSerializerSettings được khởi tạo bằng “TypeNameHandling = TypeNameHandling.None”, được coi là an toàn. Do đó, chúng tôi sử dụng hàm tạo mặc định của JsonSerializerSettings, điều này sẽ mang lại giá trị TypeNameHandling an toàn.
Đề xuất công cụ AI (GitHub Copilot):
Chúng ta có thể thấy rằng việc kiểm tra bảo mật thực sự rất đơn giản, chỉ tránh các chuỗi dấu chấm-dấu gạch chéo cần thiết để thực hiện các nỗ lực truyền tải thư mục. Tham số đường dẫn có thể là đường dẫn tuyệt đối - trỏ đến bất kỳ đường dẫn mong muốn nào trên hệ thống (ví dụ: /etc/passwd), điều này làm mất đi mục đích của việc kiểm tra bảo mật.
Thực hiện đúng:
Ở đây, hàm safe_file_read nhận tham số tên tệp (tương đối) cùng với một thư mục (safe_dir) nơi tên tệp sẽ nằm (và không được thoát). Nó tạo ra một đường dẫn tuyệt đối bằng cách nối safe_dir và tên tệp và tiến hành lấy dạng chuẩn hóa của nó bằng cách gọi realpath. Sau đó nó sẽ có dạng chuẩn hóa của thư mục safe_dir. Sau đó, nội dung tệp chỉ được trả về nếu đường dẫn được chuẩn hóa bắt đầu bằng safe_dir được chuẩn hóa.
Đề xuất công cụ AI (Tạo mã Blackbox AI): Trong ví dụ sau, chúng tôi đã yêu cầu trình tự động hoàn thành AI tạo một chức năng có nhiệm vụ lọc các phần mở rộng tệp nguy hiểm.
Mã Python được đề xuất lấy tên tệp, tách phần mở rộng và so sánh nó với danh sách các phần mở rộng nguy hiểm.
Thoạt nhìn, đoạn mã này có vẻ an toàn. Tuy nhiên, quy ước về tên tệp của Windows cấm tên tệp kết thúc bằng dấu chấm và khi cung cấp tên tệp kết thúc bằng dấu chấm (“.”) trong quá trình tạo tệp, dấu chấm sẽ bị loại bỏ. Có nghĩa là bộ lọc được tạo có thể bị bỏ qua trên Windows khi gửi tệp có phần mở rộng độc hại theo sau là dấu chấm (ví dụ: “example.exe.”).
Triển khai đúng cách: Thông thường, cách tiếp cận tốt hơn là sử dụng danh sách trắng , danh sách này chỉ kiểm tra phần mở rộng tệp đối với các phần mở rộng được phép. Tuy nhiên, vì các công cụ sử dụng cách tiếp cận danh sách đen (cần thiết trong một số trường hợp), chúng tôi sẽ phác thảo cách triển khai danh sách đen an toàn hơn:
Trong đoạn mã sau, chúng tôi loại bỏ nhiều quyền kiểm soát mà người dùng có đối với đầu vào bằng cách loại bỏ phần mở rộng khỏi tất cả các ký tự không phải chữ và số và nối nó với tên tệp mới được tạo.
Điểm mấu chốt - hãy thận trọng khi sử dụng Những người đồng lập trình tự động rất phù hợp để đề xuất ý tưởng, tự động hoàn thành mã và tăng tốc quá trình phát triển phần mềm. Chúng tôi hy vọng những công cụ này sẽ tiếp tục phát triển theo thời gian, nhưng hiện tại, như đã được minh họa qua các trường hợp sử dụng trong bài đăng này, các giải pháp AI tự động hoàn thành có nhiều thách thức cần vượt qua cho đến khi chúng tôi có thể thư giãn đầu óc và tin tưởng vào kết quả đầu ra của chúng mà không cần kiểm tra kỹ lỗi.
Một cách khả thi để giảm khả năng phát sinh lỗ hổng là cố tình yêu cầu công cụ tạo mã AI tạo mã bảo mật. Mặc dù điều này có thể hữu ích trong một số trường hợp sử dụng nhưng nó không phải là điều dễ hiểu - kết quả đầu ra "có vẻ an toàn" vẫn phải được xem xét thủ công bởi người thành thạo về bảo mật phần mềm.
Đề xuất của Nhóm nghiên cứu bảo mật JFrog Để giúp bảo mật phần mềm của bạn, chúng tôi khuyên bạn nên xem xét thủ công mã do các công cụ tạo AI tạo ra, cũng như kết hợp các giải pháp bảo mật như Kiểm tra bảo mật ứng dụng tĩnh (SAST) có thể phát hiện các lỗ hổng một cách đáng tin cậy khi bạn thực hiện. Như đã thấy trong ví dụ trên, các công cụ SAST có thể cảnh báo và nắm bắt xung đột ánh xạ trường hợp unicode được mô tả trong trường hợp sử dụng số 3. Cách tiếp cận chủ động này là cần thiết để đảm bảo tính bảo mật cho phần mềm của bạn.
Luôn cập nhật với Nghiên cứu bảo mật của JFrog Các phát hiện và nghiên cứu của nhóm nghiên cứu bảo mật đóng một vai trò quan trọng trong việc cải thiện khả năng bảo mật phần mềm ứng dụng của Nền tảng JFrog.
Theo dõi những khám phá và cập nhật kỹ thuật mới nhất từ nhóm Nghiên cứu bảo mật JFrog trên trang web nghiên cứu của chúng tôi và trên X @JFrogSecurity .