Snort Rules là gì? Điểm khác biệt giữa các phiên bản Community, Registered và Subcriber

Snort sử dụng các luật được lưu trữ trong các file text, gọi là Snort Rules. Mỗi dạng rule được lưu trong file khác nhau. Snort đọc những luật này vào lúc khởi tạo và xây dựng cấu trúc dữ liệu để cung cấp các luật để bắt giữ dữ liệu. Ngoài ra, Snort có một tập hợp các luật được định nghĩa trước đồng thời hỗ trợ thêm/xóa/sửa các luật phù hợp với mục đích quản trị. Một luật có thể được sử dụng để tạo ra một thông điệp cảnh báo, ghi lại một thông điệp…

Phân biệt giữa các phiên bản Community, Registered và Subcriber:

  • Bản Community là bản miễn phí chứa các rules cơ bản nhất. Những hệ thống nhỏ với nhu cầu cơ bản có thể sử dụng hệ những rules này.
    • Người dùng có thể thoải mái biên soạn lại các rules tuỳ theo mục đích
    • Cải tiến: có thể phát triển các rules.
    • Bản này bị hạn chế số lượng rules có thể phát triển. Mặc định là 3456 rules.
  • Bản Registered là bản cũng gần như miễn phí vì bạn chỉ cần đăng ký là có thể generation code tải các rules này. Bản này gần với bản subscriber nhưng chỉ trong 30 ngày. Quá 30 ngày các rules sẽ không nhận được cập nhật nếu không chuyển lên bản Subcribe.
    • Bản này bị giới hạn lượng rules là 1.000.000 nhưng con số này là quá nhiều để phát triển trong vòng 1 tháng.
  • Subcriber: bản này thì không có giới hạn vì bạn phải trả phí để dùng nó. Có nhiều gói để chọn lừa tuỳ nhu cầu và thời gian sử dùng. Ngoài việc phát triển rules thì nếu chỉ là người sử dụng có thể có thể một kho có rules đã được phát triển sẵn cho nhiều mục đích khác nhau.

Cách viết một Snort Rule như thế nào

Để có thể một Rule của Snort ta cần phải hiểu về cấu trúc của một Rules trong Snort.

Rule của Snort gồm hai phần: Rule HeaderRule Options:

Rule Header

Đây là phần xác định Rules sẽ làm gì (Actions), giao thức (Protocol), địa chỉ IP nguồn và đích, netmask, port nguồn và đích của rule, xác định xem rule áp dụng gói tin gì, của ai, ở đâu, và hành động gì cần thực hiện khi nhận được gói tin đáp ứng điều kiện đó.

  • Actions: xác định hoạt động của Rule sẽ làm với gói tin được nhận.

5 action mặc định trong Snort là alert, log, pass, activate, và dynamic.

  • alert – Tạo ra một cảnh báo bằng cách sử dụng phương pháp cảnh báo đã được chọn và ghi chép gói tin.
  • log – Ghi chép gói tin vào cơ sở dữ liệu.
  • pass – Bỏ qua gói tin, góp phần tăng tốc độ của Snort khi không cần áp dụng các kiểm tra lên một số gói tin nhất định.
  • activate – Cảnh báo và sau đó bật một rule dynamic khác để kiểm tra thêm điều kiện. Activate được sử dụng khi ta cần kiểm tra thêm một hay các gói tin nhận được. Dynamic rule được sử dụng kèm với activate.
  • dynamic – Không làm gì cho đến khi được kích hoạt bởi một rule activate, sau đó hoạt động như một rule log (ghi chép). Chỉ có thể được kích hoạt bằng rule activate.

Nếu chạy ở mode inline, Snort có thêm các action như drop, reject và sdrop.

  • drop – Block và ghi chép gói tin.
  • reject – Block và ghi chép gói tin, gửi TCP reset nếu giao thức là TCP và gửi ICMP port unreachable nếu giao thức là ICMP.
  • sdrop – Block gói tin nhưng không ghi chép về nó.

Protocol: xác định loại giao thức mạng (định dạng gói tin UDP, TCP, ICMP, IP, ARP, …)

IP Address: xác định địa chỉ mạng ngoại vi và nội bộ.

Port: cổng ra tại mạng ngoại vi và cổng vào của gói tin tại mạng nội bộ.

Direction (hướng): trong rule xác định hướng của traffic mà rule được áp dụng.

Có 2 toán tử hướng:

  • ->: địa chỉ IP và port nằm bên trái toán tử được xem là nguồn của traffic, còn bên phải là đích của traffic.
  • <> : toán tử 2 hướng, giống như -> nhưng hoạt động 2 chiều, yêu cầu Snort xem xét các cặp địa chỉ IP và port ở cả 2 hướng nguồn và đích, thường được sử dụng để theo dõi hay phân tích cả 2 bên của cuộc hội thoại.

Ví dụ một số rule header:

  • alert tcp !192.168.1.0/24 any -> 192.168.1.0/24 111
  • log tcp !192.168.1.0/24 any <> 192.168.1.0/24 23

Rule Options

Rule options theo sau Rule header và nằm trong một dấu ngoặc đơn. Một rule có thể có một hoặc nhiều option và các option cách nhau bởi dấu chấm phẩy (;). Nhiều option được sử dụng tương tự như việc sử dụng phép AND chúng với nhau. Action được định nghĩa trong rule chỉ được thực thi khi tất cả điều kiện trong phần options được thỏa.

Rule options thường gồm 2 phần: từ khóa (keyword) và tham số được phân cách với nhau bằng dấu hai chấm (:).

4 loại rule options chính: General, payload, non-payload và post-detection.

– General rule options

Các option cung cấp thông tin về rule nhưng không có bất kỳ ảnh hưởng nào trong quá trình phát hiện. Một số options phổ biến:

  • msg – Định nghĩa thông điệp được in ra khi loại bỏ gói tin hay khi cảnh báo. Với những ký tự đặc biệt được sử dụng trong rule của Snort như ta dùng thêm \ để phân biệt.

Định dạng: msg:“<message text>”;

  • reference – Cho phép rule tham chiếu đến các hệ thống nhận dạng tấn công bên ngoài.

Định dạng: reference:<id system>,<id>;

  • gid – Xác định phần nào của Snort tạo ra sự kiện khi một rule được thực hiện. Từ khóa gid không bắt buộc, nếu không được xác định cụ thể thì giá trị của nó mặc định là 1 và rule này thuộc hệ thống phụ general rule. Khuyến khích sử dụng gid có giá trị từ 1000000.

Định dạng: gid:<generator id>;

  • sid – Được dùng để định danh duy nhất cho rule của Snort, nên được dùng với từ khóa rev. Các khoảng giá trị của sid có những ý nghĩa nhất định:

< 100: dành riêng để sử dụng sau này

100 – 999999: các rule chứa trong Snort distribution

>= 1000000: dùng cho các local rule.

Định dạng: sid:<snort rules id>;

  • rev – Sử dụng để định danh duy nhất phiên bản rule.

Định dạng: rev:<revision interger>;

  • classtype – Dùng để phân loại một rule khi phát hiện tấn công là một phần của một loại tấn công chung khác.

Định dạng: classtype:<class name>;

Định nghĩa của classtype được cấu hình trong file classification.config với định dạng sau:

config classification: <ten class>,<mô tả class>,<độ ưu tiên mặc định>

  • priority – Gán một mức độ cần thiết, độ ưu tiên cho rule. Giá trị priority càng thấp thì độ ưu tiên càng cao và ngược lại. Một classtype với giá trị ưu tiên cấu hình trong các file cấu hình có thể được ghi đè với option này.

Định dạng: priority:<priority integer>;

  • metadata – Thêm một số thông tin cho rule, thường dưới dạng từ khóa – giá trị. Một số cặp từ khóa và giá trị có ý nghĩa trong Snort như engine, soid, service, còn lại Snort sẽ bỏ qua. Từ khóa với key cách nhau bởi khoảng trắng, nhiều từ khóa phân biệt bằng dấu phẩy (,)

Định dạng: metadata:key1 value1[, key2 value2];

– Payload rule options

Các option tìm kiếm dữ liệu bên trong payload của gói tin. Một số options phổ biến:

  • content – Cho phép tìm kiếm một nội dung nhất định trong payload của packet và hành động dựa trên dữ liệu này. Tham số của option này có thể ở dạng text hay nhị phân. Ở dạng nhị phân, dữ liệu nằm trong cặp ký hiệu | | dưới dạng bytecode (hexan). Toán tử phủ định (!) có thể được dùng để biểu diễn điều kiện không chứa nội dung trên.

Định dạng: content:[!]“<content string>”;

Từ khóa content có một số từ khóa bổ nghĩa cho nó, thay đổi cách nó thực hiện:

  • protected_content – Có hầu hết chức năng của từ khóa content, tuy nhiên nội dung được bảo vệ cho phép che giấu nội dung bằng cách chỉ hiển thị giá trị hash của nó. Ban đầu phần nội dung của gói tin đến được hash và so sánh với giá trị được cung cấp. Toán tử phủ định (!) cũng được sử dụng để biểu diễn điều kiện không chứa nội dung trên. Khi dùng option này, cần xác định thuật toán hash với từ khóa hash và độ dài của dữ liệu với length.

Định dạng:  protected_content:[!]”<content hash>”, length:orig_len[,hash:md5|sha256|sha512];

  • uricontent – tìm kiếm các trường request URI được chuẩn hóa. Từ khóa này tương đương với bổ ngữ http_uri của content. Nếu như ta viết rules chứa những điều đã được chuẩn hóa, ví dụ như %2f hoặc đường dẫn thư mục, rule sẽ không linh hoạt.

Định dạng: uricontent:[!]“<content string>”;

  • urilen – Xác định độ dài chính xác, độ dài nhỏ nhất và lớn nhất hoặc khoảng độ dài của URI để phù hợp.

Định dạng: urilen:min<>max[,<uribuf>];

urilen:[<|>]<number>[,<uribuf>];

Giá trị của uribuf có thể là norm cho buffer chuẩn hóa và raw cho raw buffer, mặc định là raw buffer: <uribuf> : “norm” | “raw”

  • isdataat – Kiểm tra trong payload có dữ liệu ở vị trí xác định, có thể tìm kiếm dữ liệu sau vị trí vừa tìm thấy nội dung trước đó với bổ ngữ relative. Toán tử phủ định (!) được sử dụng để kiểm tra lượng dữ liệu nhất định không có trong payload.

Định dạng: isdataat:[!]<int>[,relative|rawbytes];

  • pkt_data – Gán giá trị con trỏ được dùng để tìm kiếm payload. Bất kỳ kết quả tìm kiếm phù hợp tương đối hay tuyệt đối và các rule option tìm kiếm khác theo sau pkt_data sẽ áp dụng cho payload TCP/UDP hoặc buffer chuẩn hóa đến khi con trỏ được gán lại.

Định dạng: pkt_data;

  • byte_test – Kiểm tra một khu vực byte với các giá trị cho trước. Có khả năng kiểm tra giá trị nhị phân hoặc chuyển các chuỗi byte sang giá trị nhị phân và kiểm tra.

Định dạng:

byte_test:<bytes_to_convert>,[!]<operator>,<value>,<offset>\

   [,relative][,<endian>][,string,<number type>][,dce];

Trong đó:

  • bytes_to_convert: số byte cần lấy từ gói tin, giá trị cho phép từ 1 – 10, nếu dùng thêm dce, giá trị là 1, 2, 4.
  • operator: kiểm tra giá trị nhỏ hơn (<), lớn hơn (>), nhỏ hơn hoặc bằng (<=), lớn hơn hoặc bằng (>=), bằng (=), AND bit (&), OR bit (^), dùng toán tử phủ định (!) để kiểm tra nếu phép so sánh không đúng.
  • value: giá trị để so sánh.
  • offset: số byte từ payload để bắt đầu xử lý.
  • relative: offset tương đối với vị trí tìm thấy trước đó.
  • endian: mặc định big endian (big), có thể chuyển sang little endian (little)
  • string: dữ liệu lưu dưới dạng chuỗi ký tự trong gói tin.
  • number type: kiểm số được đọc: hệ 16 (hex), hệ 10 (dec), hệ 8 (oct).
  • dce: chuyển cho DCE/RPC 2 preprocessor quyết định thứ tự byte của giá trị được chuyển đổi.
  • byte_jump – Đọc một số lượng bytes, chuyển sang dạng số, di chuyển qua từng đó bytes và gán con trỏ cho việc tìm kiếm sau này, cho phép bỏ qua một số byte trong gói tin và thực hiện tìm kiếm ở vị trí xác định.

Định dạng:

byte_jump:<bytes_to_convert>,<offset>\ [,relative][,multiplier <mul value>][,<endian>] \ [,string,<number_type>][,align][,from_beginning]\ [,post_offset <adjustment value>][,dce];

Trong đó ta có:

  • bytes_to_convert: số byte cần lấy từ gói tin, giá trị cho phép từ 1 – 10, nếu dùng thêm dce, giá trị là 1, 2, 4.
  • offset: số byte từ payload để bắt đầu xử lý từ -65535 đến 65535.
  • relative: offset tương đối với vị trí tìm thấy trước đó.
  • multiplier <value>: nhân số byte tính được với <value> và bỏ qua từng đó byte tính được. <value> từ 0 đến 65535
  • endian: mặc định big endian (big), có thể chuyển sang little endian (little)
  • string: dữ liệu lưu dưới dạng chuỗi ký tự trong gói tin.
  • number type: kiểm số được đọc: hệ 16 (hex), hệ 10 (dec), hệ 8 (oct).
  • align: làm trong số được chuyển đến số 32-bit tiếp theo.
  • from_beginning: bỏ qua bắt đầu từ đầu file thay vì từ vị trí hiện tại trong gói tin.
  • post_offset <value>: Bỏ qua tiếp hoặc trở lại <value> byte sau khi options jump khác được áp dụng.
  • dce: chuyển cho DCE/RPC 2 preprocessor quyết định thứ tự byte của giá trị được chuyển đổi.
  • byte_extract – Đọc một số byte từ payload và lưu thành một biến. Những biến này có thể được tham chiếu sau đó trong rule, hay vì sử dụng các giá trị cứng. Mỗi rule byte_extract chỉ có thể tạo 2 biến, có thể được sử dụng lại bao nhiêu lần cũng được.

Định dạng:

byte_extract:<bytes_to_extract>,<offset>,<name>\

   [,relative][,multiplier <mul value>],[,<endian>]\

   [,string][,<number type>][,align <align value>][,dce]

Trong đó:

  • bytes_to_convert: số byte cần lấy từ gói tin, giá trị cho phép từ 1 – 10, nếu dùng thêm dce, giá trị là 1, 2, 4.
  • offset: số byte từ payload để bắt đầu xử lý từ -65535 đến 65535.
  • name: tên của biến. Tên này được sử dụng để tham chiếu đến biến trong các rule option khác.
  • relative: offset tương đối với vị trí tìm thấy trước đó.
  • multiplier <value>: nhân số byte tính được với <value> và bỏ qua từng đó byte tính được. <value> từ 0 đến 65535
  • endian: mặc định big endian (big), có thể chuyển sang little endian (little)
  • string: dữ liệu lưu dưới dạng chuỗi ký tự trong gói tin.
  • number type: kiểm số được đọc: hệ 16 (hex), hệ 10 (dec), hệ 8 (oct).
  • align: làm tròn số byte đến số <value>-bit tiếp theo, <value> có thể là 2 hoặc 4.
  • from_beginning: bỏ qua từ đầu file thay vì vị trí hiện tại trong gói tin.
  • post_offset <value>: Bỏ qua tiếp hoặc trở lại <value> byte sau khi options jump khác được áp dụng.
  • dce: chuyển cho DCE/RPC 2 preprocessor quyết định thứ tự byte của giá trị được chuyển đổi.

Option byte_extract bản thân nó không tìm kiếm gì. Công dụng của option này là trích xuất dữ liệu từ dữ liệu gói tin để dùng trong các rule option khác:

  • asn1 – Giải mã gói tin hoặc 1 phần gói tin, và tìm kiếm nhiều bảng mã độc hại khác nhau. Option này cung cấp khả năng tìm kiếm được lập trình trước cũng như tìm kiếm thêm một số kiểu khác.

Định dạng:

asn1:[bitstring_overflow][,double_overflow]\

   [,oversize_length <value>]\

   [,absolute_offset <value>|relative_offset <value>]

Trong đó ta có:

  • bitstring_overflow: phát hiện đoạn mã bit không hợp lệ, chúng được biết thường dùng để khai thác từ xa.
  • double_overflow: phát hiện một đoạn mã ASCII đôi lớn hơn buffer chuẩn. Đây được biết đến là một hàm khai thác trong Microsoft, nhưng cũng không biết dịch vụ nào có thể bị khai thác.
  • oversize_length <value>: so sánh độ dài kiểu ASN.1 với tham số được cung cấp.
  • absolute_offset <value>: offset tuyệt đối tính từ đầu gói tin. Offset này có thể là âm hoặc dương.
  • relative_offset <value>: offset tương đối tính từ vị trí tìm kiếm trước đó hoặc byte_jump. Offset có thể âm hoặc dương.
  • cvs – hỗ trợ phát hiện Bugtraq-10384, CVE-2004-0396: “Malformed Entry Modified and Unchanged flag insertion”. Port mặc định là 2401 và 514, không thể phát hiện qua các session được mã hóa như SSH.

Định dạng: cvs:<option>;

Option ở đây là invalid-entry dùng để tìm chuỗi Entry không hợp lệ – một cách để gây ra heap overflow và bad pointer dereference trong phiên bản CVS 1.11.15

(Còn tiếp)