Bảo mật Runtime cho Kubernetes với Falco: Phát hiện hành vi bất thường trong thời gian thực

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Bảo mật Runtime cho Kubernetes với Falco: Phát hiện hành vi bất thường trong thời gian thực

Chào anh em IT từ itfromzero.com! Khi làm việc với Kubernetes, hẳn anh em đều nhận thấy bảo mật là một thách thức liên tục. Chúng ta cần chú ý đến nhiều khía cạnh, từ bảo vệ API server, quản lý RBAC, cho đến việc đảm bảo các image container an toàn. Tuy nhiên, có một khía cạnh thường bị bỏ qua cho đến khi sự cố xảy ra: đó là **bảo mật runtime**.

Có lần, team mình triển khai một ứng dụng mới lên Kubernetes. Mọi thứ tưởng chừng ổn, nhưng sau vài ngày, mình nhận được cảnh báo về một tiến trình lạ chạy trong một pod của ứng dụng đó. Hóa ra, một dependency trong image có lỗ hổng, và kẻ tấn công đã lợi dụng để thực thi lệnh từ xa.

May mà Falco đã kịp thời ‘tóm’ được hành vi bất thường này, giúp mình xử lý trước khi có thiệt hại lớn hơn. Từ đó, mình luôn coi trọng việc giám sát runtime, đặc biệt là trong môi trường K8s năng động. Bài viết này, mình sẽ chia sẻ kinh nghiệm thực chiến với Falco để anh em có thể tự tin bảo vệ cluster của mình.

Bối cảnh & Tại sao cần bảo mật Runtime cho Kubernetes?

Kubernetes mang lại sự linh hoạt và khả năng mở rộng tuyệt vời, đi kèm với những thách thức bảo mật riêng. Các giải pháp truyền thống thường tập trung vào tường lửa, phát hiện xâm nhập mạng (IDS/IPS) hay quét lỗ hổng ảnh (image scanning). Ngược lại, bảo mật runtime tập trung vào những gì *thực sự diễn ra* bên trong các container và node của bạn *trong quá trình hoạt động*.

Hãy hình dung thế này: Anh em đã khóa cửa cẩn thận (firewall), kiểm tra lý lịch người ra vào (image scanning), nhưng một khi kẻ gian đã vào được nhà (container bị compromise), làm sao anh em biết được chúng đang làm gì? Đó là lúc bảo mật runtime phát huy tác dụng.

Các mối đe dọa runtime phổ biến bao gồm:

  • Container Escape: Kẻ tấn công thoát khỏi container và truy cập vào node host.
  • Thực thi lệnh độc hại: Chạy các shell, sửa đổi file hệ thống, tải về malware.
  • Truy cập dữ liệu nhạy cảm: Đọc các file cấu hình, secret, hoặc dữ liệu ứng dụng.
  • Thay đổi cấu hình không mong muốn: Sửa đổi các file hệ thống quan trọng hoặc cấu hình mạng (ví dụ: thay đổi `/etc/hosts` hoặc `/etc/resolv.conf`).

Falco, một dự án mã nguồn mở của CNCF, thực sự là lựa chọn lý tưởng để giải quyết bài toán này. Nó đóng vai trò là một hệ thống phát hiện mối đe dọa runtime (Runtime Threat Detection). Falco hoạt động bằng cách giám sát các sự kiện cấp độ hệ thống (system calls) và đối chiếu chúng với bộ quy tắc đã định. Nếu phát hiện hành vi vi phạm quy tắc, Falco sẽ lập tức cảnh báo cho anh em.

Cài đặt Falco trên Kubernetes

Cách tốt nhất và được khuyến nghị để cài đặt Falco trên Kubernetes là sử dụng Helm. Falco sẽ được triển khai dưới dạng DaemonSet, đảm bảo nó chạy trên mọi node trong cluster của bạn để giám sát toàn diện.

Bước 1: Thêm Helm repository của Falco

Đầu tiên, anh em cần thêm repository của Falco vào Helm của mình:

helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update

Bước 2: Tạo Namespace (tùy chọn nhưng nên làm)

Mình thường tạo một namespace riêng cho các công cụ bảo mật để dễ quản lý:

kubectl create namespace falco

Bước 3: Cài đặt Falco bằng Helm

Bây giờ, anh em có thể cài đặt Falco vào namespace vừa tạo. Mình thường dùng phiên bản mới nhất và để Falco tự động tải kernel module nếu cần:

helm install falco falcosecurity/falco \n  --namespace falco \n  --set falco.kind=DaemonSet \n  --set falco.loadKernelModule.enabled=true \n  --set falco.loadBPF.enabled=false

Giải thích một chút:

  • falco.kind=DaemonSet: Đảm bảo Falco chạy trên tất cả các node.
  • falco.loadKernelModule.enabled=true: Falco sẽ cố gắng tải kernel module để giám sát system calls. Đây là phương pháp hiệu quả nhất.
  • falco.loadBPF.enabled=false: Nếu kernel module không hoạt động, Falco có thể dùng eBPF. Mình thường ưu tiên kernel module trước, nhưng anh em có thể bật eBPF nếu môi trường của mình hỗ trợ tốt hơn hoặc gặp vấn đề với kernel module.

Bước 4: Kiểm tra trạng thái cài đặt

Sau khi cài đặt, anh em kiểm tra xem các pod của Falco đã chạy ổn định chưa:

kubectl get pods -n falco

Anh em sẽ thấy các pod có trạng thái Running. Tiếp theo, xem log của một trong các pod Falco để đảm bảo nó khởi động thành công và không có lỗi:

kubectl logs -f <tên_pod_falco> -n falco

Cấu hình chi tiết Falco: Sức mạnh của Falco Rules

Trái tim của Falco nằm ở các **Falco Rules**. Đây là những quy tắc định nghĩa hành vi nào là bình thường và hành vi nào là đáng ngờ. Falco đi kèm với một bộ quy tắc mặc định rất tốt, nhưng để thực sự hiệu quả, anh em cần tùy chỉnh chúng cho môi trường của mình.

Cấu trúc của một Falco Rule

Mỗi rule trong Falco được định nghĩa trong file YAML và bao gồm các thành phần chính:

  • rule: Tên duy nhất của quy tắc.
  • desc: Mô tả về quy tắc.
  • condition: Biểu thức Boolean xác định khi nào quy tắc được kích hoạt (sử dụng cú pháp của Falco).
  • output: Thông báo sẽ được hiển thị khi quy tắc kích hoạt.
  • priority: Mức độ ưu tiên của cảnh báo (ví dụ: Critical, Warning, Notice).
  • tags: Các tag để phân loại quy tắc (ví dụ: network, file, shell).

Ví dụ một rule đơn giản:

- rule: Detect Shell in Container
  desc: A shell was spawned in a container. This could be normal for debugging, but often indicates suspicious activity.
  condition: >
    spawned_process and container and proc.name in (bash, sh, csh, ksh, zsh)
    and not user.name in (root)
    and not proc.pname=containerd
  output: >
    Shell spawned in container (user=%user.name container=%container.name
    container_id=%container.id image=%container.image.repository
    command=%proc.cmdline parent=%proc.pname pid=%proc.pid)
  priority: WARNING
  tags: [shell, container, process]

Tùy chỉnh Falco Rules

Mình thường không sửa trực tiếp các file rule mặc định (falco_rules.yaml, falco_rules.local.yaml) mà Falco cung cấp. Thay vào đó, mình tạo một file falco_rules.custom.yaml riêng và mount nó vào pod Falco. Điều này giúp dễ dàng nâng cấp Falco mà không làm mất các thay đổi của mình.

Để thêm các rule tùy chỉnh, anh em có thể cập nhật cấu hình Helm của Falco. Tạo một file values.yaml như sau:

# values.yaml
falco:
  rules:
    customRules:
      my_custom_rules.yaml: |
        # Rule để phát hiện việc tạo file nhạy cảm trong /etc
        - rule: Write Sensitive File in etc
          desc: An attempt to write a sensitive file in /etc directory was made. This is highly suspicious.
          condition: >
            write and fd.name startswith "/etc/" and not fd.name in ("/etc/resolv.conf", "/etc/hostname", "/etc/mtab")
            and container
          output: >
            Sensitive file written in /etc (user=%user.name container=%container.name
            file=%fd.name command=%proc.cmdline)
          priority: CRITICAL
          tags: [filesystem, container, security]

        # Rule để phát hiện việc sử dụng 'kubectl exec' không mong muốn
        - rule: Kubectl Exec into Container
          desc: A kubectl exec command was detected which might indicate an interactive shell session in a container.
          condition: >
            spawned_process and proc.name=kubectl and proc.args contains "exec"
          output: >
            Kubectl exec detected (user=%user.name command=%proc.cmdline)
          priority: NOTICE
          tags: [kubernetes, shell]

        # Rule để phát hiện việc thay đổi quyền của file nhạy cảm
        - rule: Change Sensitive File Permissions
          desc: File permissions changed on a sensitive file. Could indicate an attempt to elevate privileges.
          condition: >
            chmod and fd.name in ("/etc/passwd", "/etc/shadow", "/etc/sudoers")
            and container
          output: >
            Sensitive file permissions changed (user=%user.name container=%container.name
            file=%fd.name mode=%fd.mode command=%proc.cmdline)
          priority: CRITICAL
          tags: [filesystem, permissions, container]

Sau đó, cập nhật cài đặt Falco bằng Helm:

helm upgrade falco falcosecurity/falco \n  --namespace falco \n  -f values.yaml

Falco cũng có các macro và list giúp anh em viết rule ngắn gọn và dễ quản lý hơn. Ví dụ, anh em có thể định nghĩa một list các shell để tái sử dụng.

Cấu hình đầu ra (Outputs)

Mặc định, Falco gửi cảnh báo ra stdout (logs của pod). Anh em có thể cấu hình Falco để gửi cảnh báo đến nhiều nơi khác nhau, giúp việc giám sát trở nên tiện lợi hơn:

  • File: Ghi cảnh báo vào một file log.
  • Syslog: Gửi cảnh báo đến syslog server.
  • HTTP/HTTPS: Gửi cảnh báo dưới dạng webhook đến các dịch vụ như Slack, PagerDuty, hoặc một SIEM (Security Information and Event Management) nào đó.
  • gRPC: Cung cấp một API để các ứng dụng khác có thể nhận cảnh báo.

Để cấu hình output, anh em cũng chỉnh sửa file values.yaml khi cài đặt hoặc nâng cấp Helm chart. Ví dụ, để gửi cảnh báo đến một webhook Slack:

# Thêm vào values.yaml
falco:
  falco.jsonOutput: true
  falco.jsonOutputKey: output
  falco.outputs:
    stdout: true
    webhook:
      enabled: true
      url: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
      insecure: false
      headers:
        Content-Type: "application/json"
      # customHeaders: [] # Nếu cần thêm header tùy chỉnh
      # template: "{"text":"Falco Alert: %output"}" # Tùy chỉnh format của Slack message
      # Tùy chỉnh template để Falco gửi JSON output trực tiếp, nếu Slack webhook hỗ trợ
      # hoặc cần format phức tạp hơn
      # template: |
      #   {
      #     "text": "Falco Alert: %output",
      #     "attachments": [
      #       {
      #         "color": "danger",
      #         "title": "%rule",
      #         "text": "%output",
      #         "fields": [
      #           {
      #             "title": "Priority",
      #             "value": "%priority",
      #             "short": true
      #           },
      #           {
      #             "title": "Container",
      #             "value": "%container.name",
      #             "short": true
      #           }
      #         ],
      #         "ts": "%evt.time.s"
      #       }
      #     ]
      #   }

Sau đó, chạy helm upgrade để áp dụng cấu hình mới.

Kiểm tra & Monitoring

Cài đặt xong thì phải kiểm tra xem nó có hoạt động đúng như mong đợi không, đúng không anh em? Đây là phần mình thấy thú vị nhất.

Kiểm tra Falco bằng cách tạo sự kiện

Mình sẽ tạo một sự kiện vi phạm rule để xem Falco phản ứng thế nào. Hãy thử kích hoạt rule Detect Shell in Container mà Falco cung cấp sẵn.

  1. Tìm một pod bất kỳ: Chọn một pod đang chạy trong cluster của bạn. Ví dụ: một pod nginx đơn giản.
  2. kubectl get pods
  3. Thực thi shell vào pod đó:
  4. kubectl exec -it <tên_pod_của_bạn> -- sh

    Nếu pod không có sh, thử bash, ash, hoặc bất kỳ shell nào có sẵn.

  5. Kiểm tra logs của Falco: Mở một terminal khác và xem logs của một pod Falco:

    kubectl logs -f <tên_pod_falco> -n falco

    Anh em sẽ thấy cảnh báo tương tự như thế này:

    ... Warning Shell spawned in container (user=root container=nginx-xxxx-xxxx container_id=xxxxxxxx image=nginx command=sh parent=runc pid=xxxx) ...

Thử thêm một số hành vi khác để kiểm tra các rule tùy chỉnh của mình:

  • Trong shell của pod, thử ghi một file vào /etc/:
  • echo "hello" > /etc/my_suspicious_file.txt
  • Hoặc thử thay đổi quyền của một file nhạy cảm (tất nhiên là nếu có quyền):
  • chmod 777 /etc/passwd

Mỗi hành động này sẽ kích hoạt các rule tương ứng và Falco sẽ ghi nhận vào log.

Tích hợp với hệ thống Monitoring & SIEM

Việc chỉ xem logs của Falco là không đủ trong môi trường production. Anh em cần tích hợp Falco với các hệ thống giám sát và quản lý sự kiện để có cái nhìn tổng thể và phản ứng nhanh chóng:

  • Prometheus & Grafana: Falco có thể xuất metrics để Prometheus thu thập và hiển thị trên Grafana. Điều này giúp anh em theo dõi số lượng cảnh báo, loại cảnh báo theo thời gian.
  • ELK Stack (Elasticsearch, Logstash, Kibana): Gửi logs của Falco vào Logstash, sau đó lưu trữ trong Elasticsearch và trực quan hóa bằng Kibana. Đây là cách rất mạnh mẽ để phân tích log và tìm kiếm các mối đe dọa.
  • SIEM thương mại: Các giải pháp SIEM như Splunk, QRadar cũng có thể nhận cảnh báo từ Falco qua Syslog hoặc webhook.

Best Practices & Mẹo thực chiến

  • Giảm False Positives: Đây là một trong những thách thức lớn nhất. Một cảnh báo giả có thể làm anh em bỏ qua cảnh báo thật. Hãy tinh chỉnh rule bằng cách thêm các điều kiện and not để loại bỏ các hành vi hợp lệ. Ví dụ, nếu một tiến trình cụ thể của ứng dụng thường xuyên ghi vào /tmp, hãy thêm and not proc.name=my_app_process vào rule.
  • Ưu tiên cảnh báo: Đặt mức độ ưu tiên (priority) phù hợp cho các rule. Các cảnh báo CRITICAL cần được xử lý ngay, trong khi NOTICE có thể xem xét sau.
  • Tạo rule theo nhu cầu ứng dụng: Mỗi ứng dụng có hành vi riêng. Anh em nên tạo các rule cụ thể cho từng ứng dụng để phát hiện các hành vi bất thường đặc thù.
  • Định kỳ xem xét rule: Môi trường Kubernetes thay đổi liên tục. Hãy định kỳ xem xét và cập nhật các rule của Falco để chúng luôn phù hợp với các ứng dụng và hạ tầng hiện tại.
  • Tích hợp với phản ứng tự động: Đối với các cảnh báo cực kỳ nghiêm trọng, anh em có thể cân nhắc tích hợp Falco với các công cụ phản ứng tự động (ví dụ: Falco Sidekick có thể gửi sự kiện tới một Lambda function để tự động kill pod hoặc scale down deployment).

Lời kết

Falco là một công cụ cực kỳ hiệu quả, gần như là thứ bắt buộc phải có trong bộ công cụ bảo mật Kubernetes hiện nay. Nó bổ sung một lớp bảo vệ runtime cực kỳ quan trọng, giúp anh em phát hiện sớm các hành vi độc hại mà các giải pháp khác có thể bỏ lỡ. Hãy dành thời gian để cài đặt, cấu hình và tinh chỉnh Falco cho môi trường của mình. Bảo mật luôn là một quá trình liên tục, và Falco sẽ là một trợ thủ đắc lực giúp anh em vững tâm hơn trên chặng đường đó.

Nếu có bất kỳ câu hỏi nào hoặc muốn chia sẻ kinh nghiệm của mình với Falco, đừng ngần ngại để lại bình luận nhé!

Share: