Rủi ro bảo mật của NuGet Packages và cách giải quyết

6 min read

nuget

NuGet Packages mang lại cách tiện lợi để chia sẻ mã nguồn, nhưng nhiều lúc chúng ta tải chúng về mà không xem xét nội dung hoặc xác minh các bản cập nhật khi có phiên bản mới được phát hành. Khi bạn cài đặt một gói NuGet, bạn đang:

  • Tải về mã nguồn từ các tác giả không rõ danh tính mà có thể chưa được nhiều người khác kiểm tra kỹ lưỡng.
  • Chạy mã với toàn quyền trên máy tính cục bộ của bạn, có nguy cơ làm lộ dữ liệu cá nhân.
  • Thực thi mã với quyền truy cập đầy đủ trên các máy tích hợp liên tục (CI), gây rủi ro cho các thông tin bảo mật và môi trường của bạn.

Thật bất ngờ khi không có nhiều sự cố xảy ra hơn! Hãy cùng xem xét kỹ hơn những gì có thể xảy ra sai sót.

Những gì NuGet package có thể làm được

MSBuild props và targets

Một gói NuGet có thể chứa các tệp MSBuild được tự động nhập khi xây dựng dự án. Những tệp này có thể thay đổi quy trình xây dựng ứng dụng của bạn. Nó có thể chạy một target thực thi các lệnh hoặc chạy mã C# một cách động. Ngoài ra, nó cũng có thể thay đổi mã nguồn của ứng dụng trước khi tiến hành xây dựng.

Bạn có thể kiểm tra nội dung của các tệp nằm trong các thư mục build, buildMultitargeting, và buildTransitive của gói NuGet.

Roslyn Analyzers và Source Generators

Các gói NuGet có thể chứa Roslyn analyzers. Roslyn analyzers được thực thi trong lúc thiết kế (IDE) và lúc xây dựng (build) và có thể thực hiện bất kỳ hành động nào trên máy của bạn.

Mặc dù analyzers được thiết kế để phân tích mã nguồn, chúng thực tế đang chạy bên trong quá trình biên dịch (compiler process) và có thể làm bất kỳ điều gì chúng muốn (không có sandbox). Chúng có thể ghi tệp, cập nhật tệp nhị phân sau khi biên dịch, v.v.

Roslyn source generators rất giống với analyzers, nên các mối lo ngại về bảo mật tương tự cũng được áp dụng. Chúng cũng có thể thêm hoặc cập nhật mã nguồn của ứng dụng trong quá trình xây dựng.

Lưu ý rằng bạn có thể ngăn việc tải analyzers từ một gói bằng cách sử dụng thuộc tính IncludedAssets hoặc ExcludedAssets trong tệp .csproj. Ví dụ, bạn có thể sử dụng đoạn mã sau để chỉ tải các thư viện từ một gói:

<PackageReference Include="Meziantou.Framework.InlineSnapshotTesting" Version="3.2.1">
    <IncludeAssets>compile</IncludeAssets>
</PackageReference>

Libraries

Bạn có chắc các tệp DLL trong gói NuGet là những tệp mà bạn nghĩ không? Ngay cả khi mã nguồn có trên GitHub, bạn có chắc các tệp DLL được xây dựng từ mã nguồn đó không?

Bạn có thể kiểm tra nội dung của tệp DLL bằng cách decompile nó. Nếu các tệp biểu tượng (PDB) được cung cấp và chứa thông tin chính xác, bạn có thể tự động xác thực rằng mã nguồn đã được xây dựng từ mã nguồn được cung cấp.

Code execution khi cài đặt hoặc gỡ cài đặt 1 package

Các gói NuGet có thể chứa các script PowerShell được thực thi khi gói được cài đặt hoặc gỡ cài đặt. Lưu ý rằng các script này chỉ được thực thi đối với các dự án không sử dụng . Vì vậy, đây không phải là mối lo ngại đối với hầu hết các dự án hiện đại.

Trước khi cài đặt một gói, hãy chắc chắn kiểm tra nội dung của gói. Bạn có thể thực hiện điều này bằng cách tải gói về và giải nén nó. Hãy kiểm tra kỹ các tệp sau:

  • tools/init.ps1
  • tools/install.ps1
  • tools/uninstall.ps1

Other vector attacks

Typo squatting

Một người có ý đồ xấu có thể tạo ra một gói có tên tương tự như một gói phổ biến. Ví dụ, Newtonsoft.Json có thể bị thay thế bằng Newtomsoft.Json hoặc Newtomsoft-Json. Đây được gọi là typo squatting. Hãy chắc chắn kiểm tra tên gói trước khi cài đặt.

Lưu ý rằng nuget.org cho phép đặt trước một tiền tố để ngăn chặn loại tấn công này. Ví dụ, chỉ có tôi mới có thể tạo gói với tiền tố meziantou. Ngoài ra, tất cả các gói của tôi đều có dấu kiểm để chỉ ra rằng chúng thuộc tiền tố đã được đặt trước.

Gói cùng tên với gói riêng tư

Nếu bạn có một gói được xuất bản trên một nguồn cấp dữ liệu nội bộ như Azure Packages, với cùng tên như một gói công khai, gói công khai có thể được sử dụng thay vì gói riêng tư. Đây là một vấn đề bảo mật vì bạn không biết nội dung của gói công khai. Bạn có thể sử dụng package source mapping để ngăn chặn vấn đề này.

Gói bị gỡ bỏ

Ngay cả khi bạn đã xác thực một gói và cài đặt nó, bạn vẫn có thể không an toàn. Trên nuget.org, bạn không thể gỡ bỏ một gói. Bạn chỉ có thể đánh dấu nó là unlisted (không được liệt kê).

Khi một gói bị đánh dấu là unlisted, nó sẽ không hiển thị trên trang web hoặc khi giải quyết đồ thị gói. Nếu gói này được cập nhật, bạn sẽ nhận được phiên bản mới tự động. Điều này có nghĩa là ứng dụng của bạn có thể sử dụng phiên bản mới của gói mà bạn chưa xác thực.

Để ngăn chặn vấn đề này, bạn có thể sử dụng lock file. Lock file là một tệp chứa phiên bản chính xác của các gói bạn sử dụng. Khi bạn khôi phục các gói, bạn sẽ nhận được phiên bản chính xác mà bạn đã sử dụng trước đó.

Best practices

  • Kiểm tra nội dung của gói NuGet trước khi cài đặt nó bằng công cụ như NuGet Package Explorer.
  • Sử dụng lock file để ngăn việc sử dụng một phiên bản gói khác với phiên bản bạn đã xác thực.
  • Dùng package source mapping nếu bạn sử dụng một nguồn khác ngoài nuget.org.
  • Sử dụng IncludedAssets hoặc ExcludedAssets để kiểm soát các tài sản được tải từ một gói.
  • Kiểm tra xem gói NuGet có tuân thủ các thực tiễn tốt nhất hay không.
  • Sử dụng tiền tố đã đặt trước để ngăn ngừa typo squatting.

Kết Luận

Nếu bạn đọc kỹ các điểm trước, bạn sẽ hiểu rằng một gói NuGet có thể:

  • Thực thi mã trên máy của bạn, với quyền của người dùng hiện tại.
  • Thực thi mã trên các máy CI của bạn, với quyền của người dùng CI.
  • Thay đổi mã của ứng dụng của bạn, và có thể thêm mã độc. Do đó, nó có thể thực thi mã trên các máy sản xuất của bạn.

Hầu hết các gói là an toàn, nhưng bạn không thể biết được điều gì có thể xảy ra trong tương lai. Một tài khoản NuGet hoặc GitHub bị xâm phạm không phải là điều hiếm gặp. Vì vậy, hãy chắc chắn kiểm tra nội dung của các gói mà bạn cài đặt hoặc cập nhật.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *