Skip to content

Commit

Permalink
add packet attribute triage function
Browse files Browse the repository at this point in the history
  • Loading branch information
kimhanbeom committed Sep 27, 2024
1 parent 714de1a commit d708f78
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 3 deletions.
136 changes: 136 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use std::{

use aho_corasick::AhoCorasickBuilder;
use anyhow::{bail, Context, Result};
use bincode::Options;
use chrono::{serde::ts_nanoseconds, DateTime, TimeZone, Utc};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};
Expand Down Expand Up @@ -79,6 +80,7 @@ use super::{
types::{Endpoint, HostNetworkGroup},
Customer, EventCategory, Network, TriagePolicy,
};
use crate::{AttrCmpKind, PacketAttr};

// event levels (currently unused ones commented out)
// const VERY_LOW: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(1) };
Expand Down Expand Up @@ -2571,6 +2573,140 @@ fn get_record_country_short_name(record: &ip2location::Record) -> Option<String>
}
}

fn deserialize<'de, T>(value: &'de [u8]) -> Option<T>
where
T: Deserialize<'de>,
{
bincode::DefaultOptions::new().deserialize::<T>(value).ok()
}

Check warning on line 2581 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2576-L2581

Added lines #L2576 - L2581 were not covered by tests

#[allow(clippy::question_mark)]
fn check_second_value<'de, T, K>(kind: AttrCmpKind, value: &'de Option<Vec<u8>>) -> Option<T>
where
T: TryFrom<K> + std::cmp::PartialOrd,
K: Deserialize<'de>,
{
match kind {

Check warning on line 2589 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2584-L2589

Added lines #L2584 - L2589 were not covered by tests
AttrCmpKind::CloseRange
| AttrCmpKind::LeftOpenRange
| AttrCmpKind::RightOpenRange
| AttrCmpKind::NotOpenRange
| AttrCmpKind::NotCloseRange
| AttrCmpKind::NotLeftOpenRange
| AttrCmpKind::NotRightOpenRange => {
let Some(value_result) = value else {
return None;

Check warning on line 2598 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2597-L2598

Added lines #L2597 - L2598 were not covered by tests
};
let Some(de_second_value) = deserialize::<K>(value_result) else {
return None;

Check warning on line 2601 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2600-L2601

Added lines #L2600 - L2601 were not covered by tests
};
let Ok(convert_second_value) = T::try_from(de_second_value) else {
return None;

Check warning on line 2604 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2603-L2604

Added lines #L2603 - L2604 were not covered by tests
};
return Some(convert_second_value);

Check warning on line 2606 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2606

Added line #L2606 was not covered by tests
}
_ => {}
}
None
}

Check warning on line 2611 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2608-L2611

Added lines #L2608 - L2611 were not covered by tests

fn compare_all_attr_cmp_kind<T>(
cmp_kind: AttrCmpKind,
attr_val: T,
first_val: T,
second_val: Option<T>,
) -> bool
where
T: PartialOrd,
{
match (cmp_kind, second_val) {
(AttrCmpKind::Less, _) => attr_val < first_val,
(AttrCmpKind::LessOrEqual, _) => attr_val <= first_val,
(AttrCmpKind::Equal, _) => attr_val == first_val,
(AttrCmpKind::NotEqual, _) => attr_val != first_val,
(AttrCmpKind::Greater, _) => attr_val > first_val,
(AttrCmpKind::GreaterOrEqual, _) => attr_val >= first_val,
(AttrCmpKind::OpenRange, Some(second_val)) => {
(first_val < attr_val) && (second_val > attr_val)

Check warning on line 2630 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2613-L2630

Added lines #L2613 - L2630 were not covered by tests
}
(AttrCmpKind::CloseRange, Some(second_val)) => {
(first_val <= attr_val) && (second_val >= attr_val)

Check warning on line 2633 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2632-L2633

Added lines #L2632 - L2633 were not covered by tests
}
(AttrCmpKind::LeftOpenRange, Some(second_val)) => {
(first_val < attr_val) && (second_val >= attr_val)

Check warning on line 2636 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2635-L2636

Added lines #L2635 - L2636 were not covered by tests
}
(AttrCmpKind::RightOpenRange, Some(second_val)) => {
(first_val <= attr_val) && (second_val > attr_val)

Check warning on line 2639 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2638-L2639

Added lines #L2638 - L2639 were not covered by tests
}
(AttrCmpKind::NotOpenRange, Some(second_val)) => {
!((first_val < attr_val) && (second_val > attr_val))

Check warning on line 2642 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2641-L2642

Added lines #L2641 - L2642 were not covered by tests
}
(AttrCmpKind::NotCloseRange, Some(second_val)) => {
!((first_val <= attr_val) && (second_val >= attr_val))

Check warning on line 2645 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2644-L2645

Added lines #L2644 - L2645 were not covered by tests
}
(AttrCmpKind::NotLeftOpenRange, Some(second_val)) => {
!((first_val < attr_val) && (second_val >= attr_val))

Check warning on line 2648 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2647-L2648

Added lines #L2647 - L2648 were not covered by tests
}
(AttrCmpKind::NotRightOpenRange, Some(second_val)) => {
!((first_val <= attr_val) && (second_val > attr_val))

Check warning on line 2651 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2650-L2651

Added lines #L2650 - L2651 were not covered by tests
}
_ => false,

Check warning on line 2653 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2653

Added line #L2653 was not covered by tests
}
}

Check warning on line 2655 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2655

Added line #L2655 was not covered by tests

fn process_attr_compare_bool(attr_val: bool, packet_attr: &PacketAttr) -> bool {
deserialize::<bool>(&packet_attr.first_value).is_some_and(|compare_val| {
match packet_attr.cmp_kind {
AttrCmpKind::Equal => return attr_val == compare_val,
AttrCmpKind::NotEqual => return attr_val != compare_val,
_ => false,

Check warning on line 2662 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2657-L2662

Added lines #L2657 - L2662 were not covered by tests
}
})
}

Check warning on line 2665 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2664-L2665

Added lines #L2664 - L2665 were not covered by tests

fn process_attr_compare_string(attr_val: &str, packet_attr: &PacketAttr) -> bool {
deserialize::<String>(&packet_attr.first_value).is_some_and(|compare_val| {
let cmp_result = attr_val.contains(&compare_val);
match packet_attr.cmp_kind {
AttrCmpKind::Contain => return cmp_result,
AttrCmpKind::NotContain => return !cmp_result,
_ => false,

Check warning on line 2673 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2667-L2673

Added lines #L2667 - L2673 were not covered by tests
}
})
}

Check warning on line 2676 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2675-L2676

Added lines #L2675 - L2676 were not covered by tests

fn process_attr_compare_addr(attr_val: IpAddr, packet_attr: &PacketAttr) -> bool {
if let Some(first_val) = deserialize::<IpAddr>(&packet_attr.first_value) {
let second_val = if let Some(serde_val) = &packet_attr.second_value {
deserialize::<IpAddr>(serde_val)

Check warning on line 2681 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2678-L2681

Added lines #L2678 - L2681 were not covered by tests
} else {
None

Check warning on line 2683 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2683

Added line #L2683 was not covered by tests
};
return compare_all_attr_cmp_kind(packet_attr.cmp_kind, attr_val, first_val, second_val);
}
false
}

Check warning on line 2688 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2685-L2688

Added lines #L2685 - L2688 were not covered by tests

fn process_attr_compare_number<'de, T, K>(attr_val: T, packet_attr: &'de PacketAttr) -> bool
where
T: TryFrom<K> + PartialOrd,
K: Deserialize<'de>,
{
if let Some(first_val) = deserialize::<K>(&packet_attr.first_value) {
if let Ok(first_val) = T::try_from(first_val) {
let second_val =
check_second_value::<T, K>(packet_attr.cmp_kind, &packet_attr.second_value);
return compare_all_attr_cmp_kind(
packet_attr.cmp_kind,
attr_val,
first_val,
second_val,
);
}
};
return false;
}

Check warning on line 2708 in src/event.rs

View check run for this annotation

Codecov / codecov/patch

src/event.rs#L2690-L2708

Added lines #L2690 - L2708 were not covered by tests

#[cfg(test)]
mod tests {
use std::{
Expand Down
67 changes: 64 additions & 3 deletions src/event/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,33 @@ use std::{fmt, net::IpAddr, num::NonZeroU8};

use chrono::{serde::ts_nanoseconds, DateTime, Utc};
use serde::{Deserialize, Serialize};
use tracing::warn;

use super::{common::Match, EventCategory, TriagePolicy, TriageScore, HIGH, MEDIUM};
use super::{
common::Match, process_attr_compare_addr, process_attr_compare_bool,
process_attr_compare_number, process_attr_compare_string, EventCategory, TriagePolicy,
TriageScore, HIGH, MEDIUM,
};
use crate::event::common::{triage_scores_to_string, vector_to_string};

const DNS_S_IP: &str = "dns-id.orig_h";
const DNS_S_PORT: &str = "dns-id.orig_p";
const DNS_D_IP: &str = "dns-id.resp_h";
const DNS_D_PORT: &str = "dns-id.resp_p";
const DNS_PROTO: &str = "dns-proto";
const DNS_QUERY: &str = "dns-query";
const DNS_ANSWER: &str = "dns-answers";
const DNS_TRANS_ID: &str = "dns-trans_id";
const DNS_RTT: &str = "dns-rtt";
const DNS_QCLASS: &str = "dns-qclass";
const DNS_QTYPE: &str = "dns-qtype";
const DNS_RCODE: &str = "dns-rcode";
const DNS_AA_FLAG: &str = "dns-AA";
const DNS_TC_FLAG: &str = "dns-TC";
const DNS_RD_FLAG: &str = "dns-RD";
const DNS_RA_FLAG: &str = "dns-RA";
const DNS_TTL: &str = "dns-TTLs";

#[derive(Deserialize, Serialize)]
pub struct DnsEventFields {
pub source: String,
Expand Down Expand Up @@ -189,8 +212,46 @@ impl Match for DnsCovertChannel {
Some(self.confidence)
}

fn score_by_packet_attr(&self, _triage: &TriagePolicy) -> f64 {
0.0
fn score_by_packet_attr(&self, triage: &TriagePolicy) -> f64 {
let mut attr_total_score = 0.0;

Check warning on line 216 in src/event/dns.rs

View check run for this annotation

Codecov / codecov/patch

src/event/dns.rs#L215-L216

Added lines #L215 - L216 were not covered by tests

for attr in &triage.packet_attr {
let mut score = 0.0;
let result = match attr.attr_name.as_str() {
DNS_S_IP => process_attr_compare_addr(self.src_addr, attr),
DNS_S_PORT => process_attr_compare_number::<u16, i64>(self.src_port, attr),
DNS_D_IP => process_attr_compare_addr(self.dst_addr, attr),
DNS_D_PORT => process_attr_compare_number::<u16, i64>(self.dst_port, attr),
DNS_PROTO => process_attr_compare_number::<u8, i64>(self.proto, attr),
DNS_QUERY => process_attr_compare_string(&self.query, attr),
DNS_ANSWER => self
.answer
.iter()
.any(|answer| process_attr_compare_string(answer, attr)),
DNS_TRANS_ID => process_attr_compare_number::<u16, i64>(self.trans_id, attr),
DNS_RTT => process_attr_compare_number::<i64, i64>(self.rtt, attr),
DNS_QCLASS => process_attr_compare_number::<u16, i64>(self.qclass, attr),
DNS_QTYPE => process_attr_compare_number::<u16, i64>(self.qtype, attr),
DNS_RCODE => process_attr_compare_number::<u16, i64>(self.rcode, attr),
DNS_AA_FLAG => process_attr_compare_bool(self.aa_flag, attr),
DNS_TC_FLAG => process_attr_compare_bool(self.tc_flag, attr),
DNS_RD_FLAG => process_attr_compare_bool(self.rd_flag, attr),
DNS_RA_FLAG => process_attr_compare_bool(self.ra_flag, attr),
DNS_TTL => self
.ttl
.iter()
.any(|ttl| process_attr_compare_number::<i32, i64>(*ttl, attr)),

Check warning on line 243 in src/event/dns.rs

View check run for this annotation

Codecov / codecov/patch

src/event/dns.rs#L218-L243

Added lines #L218 - L243 were not covered by tests
_ => {
warn!("invalid dns's attribute field");
false

Check warning on line 246 in src/event/dns.rs

View check run for this annotation

Codecov / codecov/patch

src/event/dns.rs#L245-L246

Added lines #L245 - L246 were not covered by tests
}
};
if result {
score = attr.weight.unwrap(); //weight always exist.
}
attr_total_score = score;

Check warning on line 252 in src/event/dns.rs

View check run for this annotation

Codecov / codecov/patch

src/event/dns.rs#L249-L252

Added lines #L249 - L252 were not covered by tests
}
attr_total_score

Check warning on line 254 in src/event/dns.rs

View check run for this annotation

Codecov / codecov/patch

src/event/dns.rs#L254

Added line #L254 was not covered by tests
}
}

Expand Down

0 comments on commit d708f78

Please sign in to comment.