Xây dựng docker image đảm bảo an toàn

Xuân Mạnh
Xuân Mạnh
date
Jul 14, 2024
slug
xay-dung-docker-image-dam-bao-an-toan
status
Published
tags
devops
security
devsecops
summary
Docker image có thể chứa các lỗ hổng bảo mật nếu không được xây dựng và duy trì đúng cách, dẫn đến nguy cơ bị tấn công. Để giảm thiểu các nguy cơ này, cần tuân thủ các thực hành tốt nhất về bảo mật khi xây dựng và duy trì Docker image.
type
Post
Docker image có thể chứa các lỗ hổng bảo mật nếu không được xây dựng và duy trì đúng cách, dẫn đến nguy cơ bị tấn công. Để giảm thiểu các nguy cơ này, cần tuân thủ các thực hành tốt nhất về bảo mật khi xây dựng và duy trì Docker image.

1. Tạo image

File Dockerfile cơ bản:
Ở trong file trên, ta đang sử dụng nginx làm base image bằng cách sử dụng lệnh FROM nginx, điều này có nghĩa là:
  • Ta đang ngầm sử dụng tag latest với nginx image, điều này có thể dẫn đến việc sử dụng phiên bản không ổn định hoặc chưa được kiểm định kỹ lưỡng, gây ra các lỗ hổng bảo mật không mong muốn.
  • Ta đang ngầm kéo nginx image từ Docker hub registry (registry mặc định của docker).
Đây là câu lệnh có chức năng tương đương với FROM nginx, nhưng được khai báo đầy đủ:

Cấu hình mặc định không an toàn

Ở file Dockerfile trên không chỉ định USER, điều này không an toàn vì nó sẽ mặc định chỉ định người dùng là root. Khi attacker chiếm được quyền kiểm soát container, với root user, hacker có thể thao tác mọi thứ trên hệ thống (đánh cắp data, RCE, …).
notion image

Chỉ định USER

  • groupadd --gid 53150 -r notroot: Lệnh này tạo một group mới với tên là notroot và ID group là 53150. Tùy chọn -r chỉ ra rằng đây là một system group.
  • useradd -r -g notroot -s "/bin/bash" -create-home --uid 53150 notroot: Lệnh này tạo một user mới với tên notroot với user ID là 53150. User này sẽ thuộc group notroot. Shell mặc định được thiết lập là /bin/bash và một thư mục home sẽ được tạo tự động cho user này. Tùy chọn -r chỉ ra rằng đây là một user hệ thống.
Việc tạo user và group không phải là root như vậy giúp tăng cường bảo mật cho container bằng cách hạn chế quyền truy cập và quyền thực thi của người dùng đó.
notion image
Run container là xem user hiện tại:
notion image
Chạy container với quyền root:
notion image

2. Image signing

Bây giờ ta có 1 image an toàn là example-secure. Nếu muốn người khác sử dụng được nó, ta cần phải docker logindocker push lên registry.
Trong trường hợp attacker đánh cắp được thông tin login vào registry, attacker sẽ push image chứa mã độc lên, khi người dùng pull image đó về, mã độc sẽ được thực thi. Vậy để xác thực được image đó có thật sự là do chủ sở hữu repo đó push lên không, ta có thể sử dụng Image signing.
Docker Image signing là quá trình ký số các Docker image để xác nhận danh tính của tác giả phần mềm và đảm bảo rằng mã không bị thay đổi hoặc bị xâm phạm.
 
Cách thức hoạt động:
Cách Image signing hoạt động có thể được chia thành hai phần:
  • Tại server hoặc developer
  • Tại client
Tại server:
  1. Tạo Hash cho image
    1. Image được hash bằng 1 thuật toán băm như SHA265. Kết quả là một giá trị duy nhất đại diện cho nội dung của image.
  1. Ký vào Hash của image
    1. Giá trị hash của image được ký bằng private key, quá trình này sẽ tạo ra 1 chữ ký số cho giá trị hash của image.
  1. Đóng gói chữ ký với dữ liệu gốc và certificate
    1. Chữ ký số của hash được đóng gói cùng với dữ liệu gốc của image và chứng chỉ (certificate). Chứng chỉ này chứa khóa công khai (public key) tương ứng với khóa riêng đã sử dụng để ký.
  1. Phân phối Image đã ký
    1. Image đã ký, cùng với chữ ký số và chứng chỉ, được phân phối đến khách hàng hoặc người dùng cuối.
notion image
Tại client:
  1. Download image đã ký
    1. Client nhận được image đã ký, bao gồm: image gốc, chữ ký số của hash, và chứng chỉ (certificate).
  1. Tạo hash cho image
    1. Client sử dụng cùng một thuật toán băm (hashing algorithm) để tạo ra giá trị hash của image nhận được.
  1. Xác minh chữ ký
    1. Client sử dụng khóa công khai (public key) từ chứng chỉ để xác minh chữ ký số của hash. Quá trình này đảm bảo rằng chữ ký số là hợp lệ và được tạo ra bằng khóa riêng tương ứng.
  1. So sánh Hashes Client so sánh giá trị hash của image nhận được với giá trị hash đã được ký. Nếu hai giá trị hash này khớp nhau, điều đó có nghĩa là image không bị chỉnh sửa.
notion image

Thiết lập Image signing

Cách chính xác nhất để ký một image là ký vào digest, thay vì ký vào tag (ví dụ: latest). Digest là một giá trị duy nhất được tạo ra từ nội dung của image và không thay đổi trừ khi nội dung của image thay đổi. Để lấy digest của image, ví dụ là ảnh example-secure, có thể sử dụng lệnh sau trong Docker:
notion image
Ở trong image này chưa có digest .
Xem digest của nginx image gốc:
notion image
Tạo digest cho image bằng cách push lên registry
notion image

Image signing

Sử dụng công cụ cosign

Tạo cặp khóa và ký lên image

notion image

Verify lại image đã ký

notion image

3. Making a Software Bill of Materials

Để tạo một Software Bill of Materials (SBOM) cho Docker image, ta có thể sử dụng công cụ syft. SBOM giúp ta biết được những gì có trong Docker image, nó liệt kê tất cả các thành phần phần mềm, bao gồm tên, phiên bản, và nhà cung cấp. Điều này giúp xác định chính xác các thành phần nào đang được sử dụng. Các công cụ bảo mật như Snyk, Grype có thể sử dụng SBOM để kiểm tra lỗ hổng, nó sẽ so sánh thông tin từ SBOM với các lỗ hổng đã biết và báo cáo các lỗ hổng có thể ảnh hưởng đến hệ thống.

Tạo SBOM

Sử dụng công cụ như syft để tạo SBOM
notion image
notion image

Artifacts

Xem tổng số artifacts (số lượng các thành phần phần mềm riêng lẻ được liệt kê trong SBOM, mỗi artifact đại diện cho một thành phần phần mềm cụ thể, chẳng hạn như một thư viện, một module, hoặc một gói phần mềm.)
notion image

4. Vulnerability scanning images

Sử dụng công cụ grype để thực hiện quét lỗ hổng image:
notion image
Kết quả hiển thị các lib tồn tại lỗ hổng, cve tương ứng và mức độ nghiêm trọng.