SIEM/Log Management Phát Hiện Kết Nối Malware C2 Bằng OpenSearch Term Lookup

Dạo gần đây mình có triển khai một use case giám sát bảo mật khá hay trên cụm OpenSearch: Tự động đối soát log kết nối mạng để săn lùng các máy trạm đang bắt tay với các máy chủ độc hại (Malware C2).

Thông thường, cách làm phổ biến là dùng Ingest Pipeline kết hợp với Enrich Plugin để dán nhãn log ngay khi nó vừa đi vào hệ thống. Tuy nhiên, đời không như là mơ, cụm OpenSearch mình dùng lại bị khuyết (không cài đặt) plugin này.

1779188386739.png


Không đầu hàng hoàn cảnh, mình đã chuyển hướng sang một vũ khí cực mạnh khác có sẵn của OpenSearch: Kỹ thuật "Term Lookup Query" trực tiếp trong Monitor. Hôm nay mình xin chia sẻ lại toàn bộ quy trình triển khai siêu mượt kèm theo loạt lỗi "vỡ mật" mà mình đã gặp và cách fix để anh em đi sau né được vết xe đổ nhé!


1. Ý tưởng bài toán & Chuẩn bị dữ liệu IOC​

Thay vì dán nhãn log tĩnh, mình cấu hình cho Monitor cứ mỗi 1 phút sẽ tự động bốc danh sách IP độc hại (Threat Intel Blacklist) từ index blacklist-ioc đem đi "soi" chéo với log mạng đang đổ về index network-logs-*.

Đầu tiên, tạo một document duy nhất chứa mảng các IP độc hại trong Dev Tools:


PUT blacklist-ioc/_doc/blacklist<span>-1</span><br>{<br> <span>"bad_ips"</span>: [<br> <span>"185.10.20.30"</span>,<br> <span>"45.33.22.11"</span><br> ]<br>}<br>

2. Thiết lập "Mắt thần" - Cấu hình Extraction Query​

Vào Alerting -> Create Monitor, chọn loại Per bucket monitor. Tại ô nhập query, anh em sử dụng cú pháp terms lookup này để ép OpenSearch truy vấn chéo dữ liệu giữa 2 index trong khoảng thời gian 5 phút đổ lại (now-5m):

{<br> <span>"size"</span>: <span>0</span>,<br> <span>"query"</span>: {<br> <span>"bool"</span>: {<br> <span>"must"</span>: [<br> {<br> <span>"terms"</span>: {<br> <span>"destination.ip.keyword"</span>: {<br> <span>"index"</span>: <span>"blacklist-ioc"</span>,<br> <span>"id"</span>: <span>"blacklist-1"</span>,<br> <span>"path"</span>: <span>"bad_ips"</span><br> }<br> }<br> }<br> ],<br> <span>"filter"</span>: [ { <span>"range"</span>: { <span>"@timestamp"</span>: { <span>"gte"</span>: <span>"now-5m"</span> } } } ]<br> }<br> },<br> <span>"aggs"</span>: {<br> <span>"infected_hosts"</span>: {<br> <span>"terms"</span>: { <span>"field"</span>: <span>"source.ip.keyword"</span>, <span>"size"</span>: <span>10</span> }<br> }<br> }<br>}<br>

3. Góc "Xương Máu" - Các lỗi "vỡ mật" khi cấu hình Trigger & Action​

Đoạn này mới là đoạn ly kỳ nhất này ae. Mình đã mất kha khá thời gian vì dính phải 3 cái bẫy kinh điển sau:

Đống rác dấu ngoặc JSON & Thói quen dùng lệnh Dev Tools​

Lúc đầu do copy-paste không cẩn thận, mình làm thừa dấu ngoặc nhọn khiến hệ thống liên tục báo lỗi failed to parse field [must].

1779188433530.png


Chưa hết, vì quen tay chạy lệnh trong tab Dev Tools, mình bê nguyên cả dòng GET network-logs-.../_search dán vào ô Query của Monitor, làm hệ thống đứng hình báo lỗi Invalid JSON.=> Bài học: Ô Extraction Query của Monitor chỉ nhận JSON thuần túy, bắt đầu bằng dấu { thôi ae nhé!

1779188478713.png


Bẫy múi giờ (Timezone Mismatch) khiến Monitor trắng tinh​

Khi mình thử bắn log giả lập để test rule, mặc dù báo created/updated thành công ở Dev Tools nhưng ô Extraction query response của Monitor vẫn trắng xóa không một vệt dữ liệu.

1779188513111.png


Hóa ra thủ phạm là múi giờ! Trên máy tính của mình lúc đó là 17:26 (GMT+7), khi bắn log mình điền mốc thời gian cục bộ dạng 17:26:00.000Z. Nhưng OpenSearch lại hiểu chữ Z ở cuối là giờ chuẩn quốc tế UTC (tức là tận 00:26 đêm nay log mới xuất hiện). Kết quả là bộ quét now-5m trượt hoàn toàn.=> Khắc phục: Phải lấy giờ máy tính trừ đi 7 tiếng để ra giờ UTC chuẩn trước khi nạp log test!

Xung đột giữa Per-Bucket và Per-Query Monitor​

Lỗi nặng nhất làm Bot Telegram của mình "câm nín" suốt buổi là do dán nhầm cú pháp Trigger condition phẳng (ctx.results[0]) vào Monitor dạng cụm (Per-bucket). Hệ thống vả ngay lỗi: Missing required field [buckets_path] for bucket_selector aggregation.

1779188559793.png


Cách fix chuẩn 100% cho ae: * Ô Trigger Condition phải dùng script dạng bucket:

JSON

{<br> <span>"buckets_path"</span>: { <span>"c2_hits"</span>: <span>"_count"</span> },<br> <span>"parent_bucket_path"</span>: <span>"infected_hosts"</span>,<br> <span>"script"</span>: { <span>"source"</span>: <span>"params.c2_hits &gt; 0"</span> }<br>}<br>
  • Ô Message gửi Telegram phải dùng biến cụm {{ctx.bucket.key}} để bóc tách chính xác IP máy bị nhiễm:
JSON

{<br> <span>"chat_id"</span>: <span>"YOUR_CHAT_ID"</span>,<br> <span>"text"</span>: <span>" **[CRITICAL] PHÁT HIỆN KẾT NỐI MALWARE C2** \n- IP Máy Trạm Bị Nhiễm: {{ctx.bucket.key}}\n- Số Lần Gọi Ra: {{ctx.bucket.c2_hits.value}}\n- Biện pháp: Đang tự động kích hoạt cô lập máy trạm!"</span><br>}<br>

4. Telegram nổ chuông tinh tinh!​

Sau khi dọn sạch các lỗi trên, ép Monitor chạy và mồi lại log chuẩn giờ UTC. Kết quả trả về cực kỳ mỹ mãn! Monitor tóm sống được cả 3 địa chỉ IP giả lập cùng lúc.

[Hình ảnh: Đính kèm ảnh Monitor bắt trúng 3 hits độc hại thành công - image_324289.png hoặc image_32512c.png]

Và đây là giao diện kênh Telegram của bên mình, thông báo Malware C2 đã nổ giòn giã song song với các thông báo Port Scan trước đó, không còn bị nuốt log nữa!

1779188579301.png


Hy vọng bài chia sẻ này giúp ích cho những ae nào đang tự xây dựng hệ thống SOC/SIEM bằng OpenSearch mà gặp phải bài toán khuyết Plugin. Ae có cách làm nào tối ưu hơn hoặc thắc mắc gì cứ thoải mái để lại bình luận phía dưới, chúng ta cùng thảo luận nhé!
 
Back
Top