Giám sát trên môi trường K8S – Phần 2
Ở phần trước, chúng ta đã nắm được cách cấu hình Falco trong K8S. Tiếp tục ở phần 2, chúng tôi sẽ giới thiệu các kiến thức liên quan đến tập luật của Falco
– rule: shell_in_container
desc: notice shell activity within a container
condition: container.id != host and proc.name = bash
output: shell in a container (user=%user.name container_name=%container.name)
priority: warning
tags: [shell, container]

Trên hình là một số rule mặc định của Falco, đi vào chi tiết về một rule cụ thể: Disallowed SSH Connection. Như đã trình bày trước đó, rule ở hình ảnh dưới đây bao gồm các trường, ngoại trừ trường Tags và Maturity, các trường còn lại là bắt buộc

Nói thêm về trường Maturity, trạng thái hiện thái của rule đang được đặt là deprecated. Ngoài ra Maturity còn có 3 trạng thái khác là stable, incubating và sandbox. Trong khi viết rule, các trạng thái này có thể để trong trường Tags. Các trạng thái này hiểu như sau:
Một trong những kiến thức khác cần nắm trong quá trình viết rule là các trường sự kiện, kiểu dữ liệu và các toán tử. Các trường sự kiện trong Falco tương đối khá đa dạng, mở rộng và hỗ trợ tương đối nguồn logs source. Tuy nhiên không phải các trường đều có sẵn cho tất cả các sự kiện, ví dụ một số các trường proc.***, thread.*** liên quan đến tiến trình, threads, container.*** liên quan đến container và nhiều trường dữ liệu khác nữa. Bạn đọc có thể tham khảo thêm tại đây trong để tìm và sử dụng các trường phù hợp trong quá trình viết rule. Các toán tử trong Falco bao gồm các toán tử quan hệ (=, !=, contains, icontains, v.v…) và toán tử logic (and, or hoặc not).
Chúng ta đã nắm được một số kiến thức cơ bản phục vụ cho quá trình viết rule, phần tiếp theo sẽ giới thiệu cách thức viết một rule và tùy chỉnh để rule trông gọn gàng, thuận lợi hơn trong quá trình maintain.
Người dùng có thể mở rộng tập các quy tắc của Falco bằng cách thêm các quy tắc do người dùng tự viết. Tệp tin my_rules.yaml đã có sẵn cú pháp cho phép thực hiện điều này. Bên dưới từ khóa my_rules, thêm một rule mới nhằm phát hiện việc thực thi của tiến trình mount.
customRules:
my_rules: |-
– rule: Unauthorized mount process
desc: There is an unauthorized mount process running
condition: evt.type=execve and proc.name=mount
output: Unauthorized process (%proc.cmdline) running
priority: WARNING
tags: [process, mount]

Sau khi đã thêm rule, re-run lại Falco sử dụng Helm
helm upgrade falco falcosecurity/falco -n falco –reuse-values –version 2.4.2 -f my_rules.yaml

Thử lại với câu lệnh mount –version để kiểm tra xem rule đã được trigger hay chưa

Ở trên chúng ta vừa thử viết một rule, theo cách này chúng ta có thể tự tạo được nhiều rule khác. Tuy nhiên, với rule ở ví dụ trên, khi muốn dùng lại điều kiện này một rule nào đó khác liên quan đến tiến trình mount, chúng ta sẽ sao chép lại điều kiện evt.type=execve and proc.name=mount nhiều lần. Đối với số lượng rule lớn, việc thực hiện này sẽ mất tương đối thời gian, cách viết rule cơ bản như trên cũng khiến quá trình maintain và quá trình chỉnh sửa rule trở nên khó khăn hơn về sau Để khiến các rules được viết trở nên dễ nhìn dễ đọc và dễ dàng theo dõi, Falco giới thiệu 2 khái niệm hỗ trợ trong quá trình viết rule: Macro và Lists.
Đầu tiên với marco: để giảm thiểu việc sử dụng lại các điều kiện (hoặc một phần) nhiều lần trong một tệp rule. Macro cho phép người dùng khai báo các điều kiện đó và sử dụng lại ở bất cứ đâu mà người dùng muốn. Nhìn chung việc sử dụng marco có 3 ưu điểm chính: cho phép sử dụng lại, tránh viết các điều kiện dài và dễ hiểu. Marco được định nghĩa bởi 2 thành phần: Tên của marco (macro) và điều kiện (condition). Sử dụng lại tập luật phát hiện tiến trình mount ở ví dụ trên, sử dụng marco như sau:
customRules:
my_rules: |-
– rule: Unauthorized mount process
desc: There is an unauthorized mount process running
condition: mount_process
output: Unauthorized process (%proc.cmdline) running
priority: WARNING
tags: [process, mount]
– macro: mount_process
condition: evt.type=execve and proc.name=mount

Update rule thông qua Helm và thử lại test case thông qua câu lệnh mount –version xem rule vừa viết đúng hay chưa? HÌnh ảnh bên dưới cho thấy Pod chạy lại không phát sinh lỗi và cũng trigger cảnh báo:

Tiếp theo đến với lists: Danh sách là tập các items mà người dùng có thể thêm vào các rule, macro hoặc trong một danh sách khác. Danh sách bao gồm 2 trường tên của danh sách (list) và các giá trị (items – được đặt trong ngoặc vuông và ngăn cách nhau bằng dấu phẩy) .Xét ví dụ dưới đây, các list lồng nhau và cuối cùng đặt một list trong một marco:
– list: shell_binaries
items: [bash, csh, ksh, sh, tcsh, zsh, dash]
– list: userexec_binaries
items: [sudo, su]
– list: known_binaries
items: [shell_binaries, userexec_binaries]
– macro: safe_procs
condition: proc.name in (known_binaries)
Lưu ý: Không thể sử dụng lists như một biểu thức trong condition. Ví dụ condition: proc.name in some_list, đây là một cách viết không hợp lệ.
Sử dụng lại ví dụ về việc phát hiện phát hiện tiến trình mount, chúng ta sẽ xây dựng tập luật giám sát thêm 2 process mới là sudo và ls, sử dụng đồng thời cả marco và list. Tương tự như các ví dụ trước, sau khi viết lại rule, chúng ta cũng thực hiện cập nhật rule sử dụng Helm và xem lại log xem rule đã được trigger hay chưa để xác nhận việc viết rule là chính xác
customRules:
my_rules: |-
– rule: Unauthorized mount process
desc: There is an unauthorized mount process running
condition: mount_process
output: Unauthorized process (%proc.cmdline) running
priority: WARNING
tags: [process, mount]
– macro: mount_process
condition: evt.type=execve and proc.name in (forbidden_processes)
– list: forbidden_processes
items: [mount, sudo, su]

Sau khi đã nắm được cách thức sử dụng marco và lists trong quá trình xây dựng rule. Bạn đọc có thể có những thắc mắc, liệu người viết rule có thể tác động lên những marco, lists hay thập chí là rule hay không? Câu trả lời là có, Falco cũng hỗ trợ cho người dùng mở rộng những thành phần này với tính năng append, việc sử dụng append có 2 mục đích chính:
Để có thể append, chúng ta thực hiện tuần tự các công việc sau:
Khi thực hiện thêm các thành phần, đối với lists, các items sẽ được thêm vào cuối của list, đối với rule hoặc macro, các chuỗi này sẽ được thêm vào trường condition. Dưới đây là ví dụ về việc thêm các items vào list shell_libraries.
– list: shell_libraries
append: true
items: [pdksh, fish]
Chúng ta xem xét một tập luật của Falco có tên Create Symlink Over Sensitive Files, rule phát hiện hành vi tạo symlinks ở một số tệp tin hoặc thư mục nhạy cảm.

Trong trường hợp người dùng muốn thêm các đường dẫn khác để phục vụ giám sát, ví dụ như /mnt, chúng ta sẽ sử dụng sử dụng từ khóa append để thực hiện việc thêm từ khóa này vào một list. Sau đó chạy lại pod và kiểm tra kết quả


Cũng liên quan đến marco, trong Falco có một số rule gọi là placeholder, các rule này cần các điều kiện và thông tin cụ thể để người dùng có thể viết rule cho phù hợp, cho phép ghi đè các rule vào marco cùng tên. Để sử dụng người dùng cũng cần thực hiện enable rule. Để hiểu rõ hơn về rule được gọi là placeholder, chúng ta xét ví dụ dưới đây
– macro: ssh_port
condition: fd.sport=22
– macro: allowed_ssh_hosts
condition: ssh_port
– rule: Disallowed SSH Connection
desc: Detect any new ssh connection to a host other than those in an allowed group of hosts
condition: (inbound_outbound) and ssh_port and not allowed_ssh_hosts
enabled: false
output: Disallowed SSH Connection (command=%proc.cmdline pid=%proc.pid connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository)
priority: NOTICE
tags: [network, mitre_remote_service]
Theo mặc định, rule trên được đặt ở trạng thái disable enabled: false, bạn đọc hãy để ý đến marco allowed_ssh_hosts, macro này có điều kiện là macro ssh_port, như vậy điều kiện ở rule sẽ tương đương ssh_port and not ssh_port (???), với quy tắc này, không có bất kỳ sự kiện nào có thể trigger được rule này, và cần người dùng chỉnh sửa cho phù hợp như hình ảnh bên dưới. Bạn đọc có thể tự chỉnh sửa lại rule này và re-run lại Falco để xem kết quả.

Trước khi tiếp tục với việc giới thiệu các kiến thức liên quan trong quá trình viết rule, chúng ta sẽ đi tới khái niệm dễ gây nhầm lẫn, khiến việc thực hiện cập nhật các rule mới thông qua Helm sẽ khiến pod Falco phát sinh lỗi. Người dùng tránh việc nhầm lẫn giữa Falco engine và Falco version. Giá trị của Falco engine có thể tăng khi có những thay đổi liên quan đến việc tăng tính tương thích với các định dạng file rules hay các trường hay toán tử mởi được thêm vào. Khi viết rule, Falco engine sẽ được khai báo trong trường require_engine_version, nếu người dùng cấu hình một số lớn hơn phiên bản Falco engine đang được Falco sử dụng, pod sẽ phát sinh lỗi

Như trên ảnh, engine_version đang có giá trị là 15, chúng ta thử thực hiện update rule mới và chỉ định giá trị require_engine_version là 16, chạy lại pod, như ở hình ảnh dưới, pod đã phát sinh lỗi CrashLoopBackOff. Để khắc phục vấn đề này, chúng ta cần khai báo engine version nhỏ hơn giá trị 15.


Lưu ý: Không thể chỉ định các tham số theo cách thức sau: -T/-D
Mặc dù bộ rule của Falco là hữu ích, giúp phát hiện nhiều cách thức tấn công. Tuy nhiên, đối với các hệ thống thật, tùy thuộc vào nghiệp vụ của từng đơn vị vẫn có thể xảy ra những exceptions. Các ngoại lệ này là có thể là một daemon nào đó cần lập lịch (cron jobs) để thực hiện các công việc kiểm tra hệ thống định kỳ, hay một chương trình đã được xác nhận là an toàn cần đọc ghi dữ liệu từ đường dẫn /bin…. Những hành vi này, chúng ta có thể whitelist để tránh noise cho hệ thống, Falco cũng hỗ trợ triển khai thác rule exceptions theo cú pháp sau:
– rule: <the_name_of_the_rule>
desc: (…)
condition: (…)
output: (…)
tags: (…)
exceptions:
– name: <name_of_the_exception>
fields: [proc.name, fd.name]
comps: [=, in]
values:
– [my_bin_A, [my_file_A]]
– [custom_bin_B, [allowed_file_for_B, other_B_file]]

customRules:
custom_rules_from_default: |-
(…)
– rule: Run shell untrusted
(…)
exceptions:
– name: app1_shell_runner
fields: [proc.pname, proc.cmdline]
comps: [=, =]
values:
– [apache2, bash -c ls /root > /tmp/pmt]
(…)


Trên đây là những giới thiệu và hướng dẫn tương đối cơ bản để bạn đọc có thể tự tạo cũng như tùy chỉnh các rule. Để thuận lợi hơn trong quá trình viết rule, có những công cụ mà người dùng có thể sử dụng để kiểm tra độ hiệu quả của các rule. Atomic redteam hiện tại cũng mô phỏng các kỹ thuật tấn công trên môi trường container, dựa vào các mô phỏng này, người viết rule có thể xem lại các logs và tinh chỉnh lại rule cho phù hợp. Bên cạnh Atomic, event-generator cũng sinh ra các mẫu hành vi cho cả syscall và k8s audit log. Phần 2 cho loạt bài về Falco sẽ kết thúc ở đây.
Author: Purple Team