remove unneccesary pub
This commit is contained in:
@@ -38,7 +38,12 @@ impl Detection {
|
|||||||
&common.detection(&event.system, &event_data);
|
&common.detection(&event.system, &event_data);
|
||||||
//&common.detection(&event.system, &event_data);
|
//&common.detection(&event.system, &event_data);
|
||||||
if channel == "Security" {
|
if channel == "Security" {
|
||||||
&security.detection(event_id, &event.system, &event.user_data, event_data);
|
&security.detection(
|
||||||
|
event_id,
|
||||||
|
&event.system,
|
||||||
|
&event.user_data.as_ref(),
|
||||||
|
event_data,
|
||||||
|
);
|
||||||
} else if channel == "System" {
|
} else if channel == "System" {
|
||||||
&system.detection(event_id, &event.system, event_data);
|
&system.detection(event_id, &event.system, event_data);
|
||||||
} else if channel == "Application" {
|
} else if channel == "Application" {
|
||||||
|
|||||||
@@ -1,308 +1,302 @@
|
|||||||
use crate::models::event;
|
use crate::models::event;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
// eventlogが用意できていない
|
// eventlogが用意できていない
|
||||||
// 4674
|
// 4674
|
||||||
// 4756
|
// 4756
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Security {
|
pub struct Security {
|
||||||
max_total_sensitive_privuse: i32,
|
max_total_sensitive_privuse: i32,
|
||||||
max_passspray_login: i32,
|
max_passspray_login: i32,
|
||||||
max_passspray_uniquser: i32,
|
max_passspray_uniquser: i32,
|
||||||
max_failed_logons: i32,
|
max_failed_logons: i32,
|
||||||
alert_all_admin: i32,
|
alert_all_admin: i32,
|
||||||
total_admin_logons: i32,
|
total_admin_logons: i32,
|
||||||
total_failed_logons: i32,
|
total_failed_logons: i32,
|
||||||
total_failed_account: i32,
|
total_failed_account: i32,
|
||||||
total_sensitive_privuse: i32,
|
total_sensitive_privuse: i32,
|
||||||
admin_logons: HashMap<String, HashMap<String, i32>>,
|
admin_logons: HashMap<String, HashMap<String, i32>>,
|
||||||
multiple_admin_logons: HashMap<String, i32>,
|
multiple_admin_logons: HashMap<String, i32>,
|
||||||
account_2_failedcnt: HashMap<String, i32>,
|
account_2_failedcnt: HashMap<String, i32>,
|
||||||
passspray_2_user: HashMap<String, i32>,
|
passspray_2_user: HashMap<String, i32>,
|
||||||
empty_str: String,
|
empty_str: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Security {
|
impl Security {
|
||||||
pub fn new() -> Security {
|
pub fn new() -> Security {
|
||||||
Security {
|
Security {
|
||||||
max_total_sensitive_privuse: 4,
|
max_total_sensitive_privuse: 4,
|
||||||
max_passspray_login: 6,
|
max_passspray_login: 6,
|
||||||
max_passspray_uniquser: 6,
|
max_passspray_uniquser: 6,
|
||||||
max_failed_logons: 5,
|
max_failed_logons: 5,
|
||||||
alert_all_admin: 0,
|
alert_all_admin: 0,
|
||||||
total_admin_logons: 0,
|
total_admin_logons: 0,
|
||||||
total_failed_logons: 0,
|
total_failed_logons: 0,
|
||||||
total_failed_account: 0,
|
total_failed_account: 0,
|
||||||
total_sensitive_privuse: 0,
|
total_sensitive_privuse: 0,
|
||||||
admin_logons: HashMap::new(),
|
admin_logons: HashMap::new(),
|
||||||
multiple_admin_logons: HashMap::new(),
|
multiple_admin_logons: HashMap::new(),
|
||||||
account_2_failedcnt: HashMap::new(),
|
account_2_failedcnt: HashMap::new(),
|
||||||
passspray_2_user: HashMap::new(),
|
passspray_2_user: HashMap::new(),
|
||||||
empty_str: String::default(),
|
empty_str: String::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disp(&self) {
|
pub fn disp(&self) {
|
||||||
if self.total_admin_logons > 0 {
|
if self.total_admin_logons > 0 {
|
||||||
println!("total_admin_logons:{}", self.total_admin_logons);
|
println!("total_admin_logons:{}", self.total_admin_logons);
|
||||||
println!("admin_logons:{:?}", self.admin_logons);
|
println!("admin_logons:{:?}", self.admin_logons);
|
||||||
println!("multiple_admin_logons:{:?}\n", self.multiple_admin_logons);
|
println!("multiple_admin_logons:{:?}\n", self.multiple_admin_logons);
|
||||||
}
|
}
|
||||||
|
|
||||||
let exceed_failed_logons = self.total_failed_logons > self.max_failed_logons;
|
let exceed_failed_logons = self.total_failed_logons > self.max_failed_logons;
|
||||||
let exist_failed_account = self.account_2_failedcnt.keys().count() as i32 > 1;
|
let exist_failed_account = self.account_2_failedcnt.keys().count() as i32 > 1;
|
||||||
if exceed_failed_logons && exist_failed_account {
|
if exceed_failed_logons && exist_failed_account {
|
||||||
println!("High number of total logon failures for multiple accounts");
|
println!("High number of total logon failures for multiple accounts");
|
||||||
println!(
|
println!(
|
||||||
"Total accounts: {}",
|
"Total accounts: {}",
|
||||||
self.account_2_failedcnt.keys().count()
|
self.account_2_failedcnt.keys().count()
|
||||||
);
|
);
|
||||||
println!("Total logon failures: {}\n", self.total_failed_logons);
|
println!("Total logon failures: {}\n", self.total_failed_logons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detection(
|
pub fn detection(
|
||||||
&mut self,
|
&mut self,
|
||||||
event_id: String,
|
event_id: String,
|
||||||
_system: &event::System,
|
_system: &event::System,
|
||||||
user_data: &Option<event::UserData>,
|
user_data: &Option<&event::UserData>,
|
||||||
event_data: HashMap<String, String>,
|
event_data: HashMap<String, String>,
|
||||||
) {
|
) {
|
||||||
self.process_craeted(&event_id, &event_data);
|
self.process_craeted(&event_id, &event_data);
|
||||||
self.se_debug_privilege(&event_id, &event_data);
|
self.se_debug_privilege(&event_id, &event_data);
|
||||||
self.account_created(&event_id, &event_data);
|
self.account_created(&event_id, &event_data);
|
||||||
self.add_member_security_group(&event_id, &event_data);
|
self.add_member_security_group(&event_id, &event_data);
|
||||||
self.failed_logon(&event_id, &event_data);
|
self.failed_logon(&event_id, &event_data);
|
||||||
self.sensitive_priviledge(&event_id, &event_data);
|
self.sensitive_priviledge(&event_id, &event_data);
|
||||||
self.attempt_priviledge(&event_id, &event_data);
|
self.attempt_priviledge(&event_id, &event_data);
|
||||||
self.pass_spray(&event_id, &event_data);
|
self.pass_spray(&event_id, &event_data);
|
||||||
self.audit_log_cleared(&event_id, &user_data);
|
self.audit_log_cleared(&event_id, &user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_craeted(&mut self, event_id: &String, _event_data: &HashMap<String, String>) {
|
fn process_craeted(&mut self, event_id: &String, _event_data: &HashMap<String, String>) {
|
||||||
if event_id != "4688" {
|
if event_id != "4688" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO Check-Commnad
|
// TODO Check-Commnad
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Special privileges assigned to new logon (possible admin access)
|
// Special privileges assigned to new logon (possible admin access)
|
||||||
//
|
//
|
||||||
fn se_debug_privilege(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
fn se_debug_privilege(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
||||||
if event_id != "4672" {
|
if event_id != "4672" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(privileage_list) = event_data.get("PrivilegeList") {
|
if let Some(privileage_list) = event_data.get("PrivilegeList") {
|
||||||
if let Some(_data) = privileage_list.find("SeDebugPrivilege") {
|
if let Some(_data) = privileage_list.find("SeDebugPrivilege") {
|
||||||
// alert_all_adminが有効であれば、標準出力して知らせる
|
// alert_all_adminが有効であれば、標準出力して知らせる
|
||||||
// DeepBlueCLIでは必ず0になっていて、基本的には表示されない。
|
// DeepBlueCLIでは必ず0になっていて、基本的には表示されない。
|
||||||
if self.alert_all_admin == 1 {
|
if self.alert_all_admin == 1 {
|
||||||
println!("Logon with SeDebugPrivilege (admin access)");
|
println!("Logon with SeDebugPrivilege (admin access)");
|
||||||
println!("Username:{}", event_data["SubjectUserName"]);
|
println!("Username:{}", event_data["SubjectUserName"]);
|
||||||
println!("Domain:{}", event_data["SubjectDomainName"]);
|
println!("Domain:{}", event_data["SubjectDomainName"]);
|
||||||
println!("User SID:{}", event_data["SubjectUserSid"]);
|
println!("User SID:{}", event_data["SubjectUserSid"]);
|
||||||
println!("Domain:{}", event_data["PrivilegeList"]);
|
println!("Domain:{}", event_data["PrivilegeList"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.total_admin_logons += 1;
|
self.total_admin_logons += 1;
|
||||||
|
|
||||||
// admin_logons配列にusernameが含まれているか確認
|
// admin_logons配列にusernameが含まれているか確認
|
||||||
match self.admin_logons.get(&event_data["SubjectUserName"]) {
|
match self.admin_logons.get(&event_data["SubjectUserName"]) {
|
||||||
Some(sid) => {
|
Some(sid) => {
|
||||||
// 含まれていれば、マルチユーザが管理者としてログインしているか確認
|
// 含まれていれば、マルチユーザが管理者としてログインしているか確認
|
||||||
// マルチログオンのデータをセット
|
// マルチログオンのデータをセット
|
||||||
if event_data["SubjectUserName"] != event_data["SubjectUserSid"] {
|
if event_data["SubjectUserName"] != event_data["SubjectUserSid"] {
|
||||||
// One username with multiple admin logon SIDs
|
// One username with multiple admin logon SIDs
|
||||||
self.multiple_admin_logons
|
self.multiple_admin_logons
|
||||||
.insert(event_data["SubjectUserName"].to_string(), 1);
|
.insert(event_data["SubjectUserName"].to_string(), 1);
|
||||||
|
|
||||||
let mut count_hash: HashMap<String, i32> = HashMap::new();
|
let mut count_hash: HashMap<String, i32> = HashMap::new();
|
||||||
count_hash.insert(
|
count_hash.insert(
|
||||||
event_data["SubjectUserSid"].to_string(),
|
event_data["SubjectUserSid"].to_string(),
|
||||||
sid[&event_data["SubjectUserSid"]] + 1,
|
sid[&event_data["SubjectUserSid"]] + 1,
|
||||||
);
|
);
|
||||||
self.admin_logons
|
self.admin_logons
|
||||||
.insert(event_data["SubjectUserName"].to_string(), count_hash);
|
.insert(event_data["SubjectUserName"].to_string(), count_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// admin_logons配列にセットUserNameとSIDとカウンタをセット
|
// admin_logons配列にセットUserNameとSIDとカウンタをセット
|
||||||
let mut count_hash: HashMap<String, i32> = HashMap::new();
|
let mut count_hash: HashMap<String, i32> = HashMap::new();
|
||||||
count_hash.insert(event_data["SubjectUserSid"].to_string(), 1);
|
count_hash.insert(event_data["SubjectUserSid"].to_string(), 1);
|
||||||
self.admin_logons
|
self.admin_logons
|
||||||
.insert(event_data["SubjectUserName"].to_string(), count_hash);
|
.insert(event_data["SubjectUserName"].to_string(), count_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// account craeted:OK
|
// account craeted:OK
|
||||||
fn account_created(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
fn account_created(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
||||||
if event_id != "4720" {
|
if event_id != "4720" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("New User Created");
|
println!("New User Created");
|
||||||
println!(
|
println!(
|
||||||
"Username: {}",
|
"Username: {}",
|
||||||
event_data.get("TargetUserName").unwrap_or(&"".to_string())
|
event_data.get("TargetUserName").unwrap_or(&"".to_string())
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"User SID:: {}\n",
|
"User SID:: {}\n",
|
||||||
event_data.get("TargetSid").unwrap_or(&"".to_string())
|
event_data.get("TargetSid").unwrap_or(&"".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add member to security group
|
// add member to security group
|
||||||
fn add_member_security_group(
|
fn add_member_security_group(
|
||||||
&mut self,
|
&mut self,
|
||||||
event_id: &String,
|
event_id: &String,
|
||||||
event_data: &HashMap<String, String>,
|
event_data: &HashMap<String, String>,
|
||||||
) {
|
) {
|
||||||
// check if group is Administrator, may later expand to all groups
|
// check if group is Administrator, may later expand to all groups
|
||||||
if event_data.get("TargetUserName").unwrap_or(&self.empty_str) != "Administrators" {
|
if event_data.get("TargetUserName").unwrap_or(&self.empty_str) != "Administrators" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A member was added to a security-enabled (global|local|universal) group.
|
// A member was added to a security-enabled (global|local|universal) group.
|
||||||
if event_id == "4728" {
|
if event_id == "4728" {
|
||||||
println!("User added to global Administrators group");
|
println!("User added to global Administrators group");
|
||||||
} else if event_id == "4732" {
|
} else if event_id == "4732" {
|
||||||
println!("User added to local Administrators group");
|
println!("User added to local Administrators group");
|
||||||
} else if event_id == "4756" {
|
} else if event_id == "4756" {
|
||||||
println!("User added to universal Administrators group");
|
println!("User added to universal Administrators group");
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Username: {}",
|
"Username: {}",
|
||||||
event_data.get("TargetUserName").unwrap_or(&"".to_string())
|
event_data.get("TargetUserName").unwrap_or(&"".to_string())
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"User SID:: {}\n",
|
"User SID:: {}\n",
|
||||||
event_data.get("TargetSid").unwrap_or(&"".to_string())
|
event_data.get("TargetSid").unwrap_or(&"".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// An account failed to log on.:OK
|
// An account failed to log on.:OK
|
||||||
// Requires auditing logon failures
|
// Requires auditing logon failures
|
||||||
// https://technet.microsoft.com/en-us/library/cc976395.aspx
|
// https://technet.microsoft.com/en-us/library/cc976395.aspx
|
||||||
fn failed_logon(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
fn failed_logon(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
||||||
if event_id != "4625" {
|
if event_id != "4625" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see fn disp()
|
// see fn disp()
|
||||||
self.total_failed_logons += 1;
|
self.total_failed_logons += 1;
|
||||||
let username = event_data.get("TargetUserName").unwrap_or(&self.empty_str);
|
let username = event_data.get("TargetUserName").unwrap_or(&self.empty_str);
|
||||||
let failed_cnt = self.account_2_failedcnt.get(username).unwrap_or(&0) + &1;
|
let failed_cnt = self.account_2_failedcnt.get(username).unwrap_or(&0) + &1;
|
||||||
self.account_2_failedcnt
|
self.account_2_failedcnt
|
||||||
.insert(username.to_string(), failed_cnt);
|
.insert(username.to_string(), failed_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sensitive Privilege Use (Mimikatz)
|
// Sensitive Privilege Use (Mimikatz)
|
||||||
fn sensitive_priviledge(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
fn sensitive_priviledge(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
||||||
if event_id != "4673" {
|
if event_id != "4673" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.total_sensitive_privuse += 1;
|
self.total_sensitive_privuse += 1;
|
||||||
// use == operator here to avoid multiple log notices
|
// use == operator here to avoid multiple log notices
|
||||||
if self.max_total_sensitive_privuse == self.total_sensitive_privuse {
|
if self.max_total_sensitive_privuse == self.total_sensitive_privuse {
|
||||||
println!("Sensititive Privilege Use Exceeds Threshold");
|
println!("Sensititive Privilege Use Exceeds Threshold");
|
||||||
println!(
|
println!(
|
||||||
"Username: {}",
|
"Username: {}",
|
||||||
event_data.get("SubjectUserName").unwrap_or(&self.empty_str)
|
event_data.get("SubjectUserName").unwrap_or(&self.empty_str)
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"Domain Name: {}",
|
"Domain Name: {}",
|
||||||
event_data
|
event_data
|
||||||
.get("SubjectDomainName")
|
.get("SubjectDomainName")
|
||||||
.unwrap_or(&self.empty_str)
|
.unwrap_or(&self.empty_str)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attempt_priviledge(&mut self, _event_id: &String, _event_data: &HashMap<String, String>) {
|
fn attempt_priviledge(&mut self, _event_id: &String, _event_data: &HashMap<String, String>) {
|
||||||
// event log cannot get...
|
// event log cannot get...
|
||||||
}
|
}
|
||||||
|
|
||||||
// A logon was attempted using explicit credentials.
|
// A logon was attempted using explicit credentials.
|
||||||
fn pass_spray(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
fn pass_spray(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
|
||||||
if event_id != "4648" {
|
if event_id != "4648" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetusername = event_data.get("TargetUserName").unwrap_or(&self.empty_str);
|
let targetusername = event_data.get("TargetUserName").unwrap_or(&self.empty_str);
|
||||||
let spray_cnt = self.passspray_2_user.get(targetusername).unwrap_or(&0) + 1;
|
let spray_cnt = self.passspray_2_user.get(targetusername).unwrap_or(&0) + 1;
|
||||||
self.passspray_2_user
|
self.passspray_2_user
|
||||||
.insert(targetusername.to_string(), spray_cnt);
|
.insert(targetusername.to_string(), spray_cnt);
|
||||||
|
|
||||||
// check targetuser's attempt count.
|
// check targetuser's attempt count.
|
||||||
if self.passspray_2_user.get(targetusername).unwrap_or(&0) <= &self.max_passspray_login {
|
if self.passspray_2_user.get(targetusername).unwrap_or(&0) <= &self.max_passspray_login {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check exceeded targetuser count.
|
// check exceeded targetuser count.
|
||||||
let spray_uniq_user = self
|
let spray_uniq_user = self
|
||||||
.passspray_2_user
|
.passspray_2_user
|
||||||
.values()
|
.values()
|
||||||
.filter(|value| value > &&self.max_passspray_login)
|
.filter(|value| value > &&self.max_passspray_login)
|
||||||
.count() as i32;
|
.count() as i32;
|
||||||
if spray_uniq_user <= self.max_passspray_uniquser {
|
if spray_uniq_user <= self.max_passspray_uniquser {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let usernames: String = self.passspray_2_user.keys().fold(
|
let usernames: String = self.passspray_2_user.keys().fold(
|
||||||
self.empty_str.to_string(),
|
self.empty_str.to_string(),
|
||||||
|mut acc: String, cur| -> String {
|
|mut acc: String, cur| -> String {
|
||||||
acc.push_str(cur);
|
acc.push_str(cur);
|
||||||
acc.push_str(" ");
|
acc.push_str(" ");
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("Distributed Account Explicit Credential Use (Password Spray Attack)");
|
println!("Distributed Account Explicit Credential Use (Password Spray Attack)");
|
||||||
println!("The use of multiple user account access attempts with explicit credentials is ");
|
println!("The use of multiple user account access attempts with explicit credentials is ");
|
||||||
println!("an indicator of a password spray attack.");
|
println!("an indicator of a password spray attack.");
|
||||||
println!("Target Usernames: {}", usernames.trim());
|
println!("Target Usernames: {}", usernames.trim());
|
||||||
println!(
|
println!(
|
||||||
"Accessing Username: {}",
|
"Accessing Username: {}",
|
||||||
event_data.get("SubjectUserName").unwrap_or(&self.empty_str)
|
event_data.get("SubjectUserName").unwrap_or(&self.empty_str)
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"Accessing Host Name: {}\n\n",
|
"Accessing Host Name: {}\n\n",
|
||||||
event_data
|
event_data
|
||||||
.get("SubjectDomainName")
|
.get("SubjectDomainName")
|
||||||
.unwrap_or(&self.empty_str)
|
.unwrap_or(&self.empty_str)
|
||||||
);
|
);
|
||||||
|
|
||||||
// reset
|
// reset
|
||||||
self.passspray_2_user = HashMap::new();
|
self.passspray_2_user = HashMap::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn audit_log_cleared(
|
fn audit_log_cleared(&mut self, event_id: &String, user_data: &Option<&event::UserData>) {
|
||||||
&mut self,
|
if event_id != "1102" {
|
||||||
event_id: &String,
|
return;
|
||||||
user_data: &Option<event::UserData>
|
}
|
||||||
) {
|
|
||||||
if event_id != "1102" {
|
println!("Audit Log Clear");
|
||||||
return;
|
println!("The Audit log was cleared.");
|
||||||
}
|
user_data.and_then(|u| u.log_file_cleared.as_ref());
|
||||||
|
|
||||||
println!("Audit Log Clear");
|
let username = user_data.and_then(|u| u.log_file_cleared.and_then(|l| l.subject_user_name));
|
||||||
println!("The Audit log was cleared.");
|
println!("Security ID: {}", username.unwrap_or("".to_string()));
|
||||||
let username = user_data.as_ref().and_then(|u| {
|
}
|
||||||
u.log_file_cleared
|
}
|
||||||
.as_ref()
|
|
||||||
.and_then(|l| l.subject_user_name.as_ref())
|
|
||||||
});
|
|
||||||
println!("Security ID: {}", username.unwrap_or(&"".to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,133 +1,133 @@
|
|||||||
extern crate serde;
|
extern crate serde;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
#[serde(rename = "Name")]
|
#[serde(rename = "Name")]
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
pub text: Option<String>,
|
pub text: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct TimeCreated {
|
pub struct TimeCreated {
|
||||||
#[serde(rename = "SystemTime")]
|
#[serde(rename = "SystemTime")]
|
||||||
pub system_time: String,
|
pub system_time: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
struct Execution {
|
struct Execution {
|
||||||
#[serde(rename = "ProcessID")]
|
#[serde(rename = "ProcessID")]
|
||||||
process_id: i32,
|
process_id: i32,
|
||||||
#[serde(rename = "ThreadID")]
|
#[serde(rename = "ThreadID")]
|
||||||
thread_id: i32,
|
thread_id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct Provider {
|
pub struct Provider {
|
||||||
#[serde(rename = "Name")]
|
#[serde(rename = "Name")]
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
#[serde(rename = "Guid")]
|
#[serde(rename = "Guid")]
|
||||||
guid: Option<String>,
|
guid: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct System {
|
pub struct System {
|
||||||
#[serde(rename = "Provider")]
|
#[serde(rename = "Provider")]
|
||||||
pub provider: Provider,
|
pub provider: Provider,
|
||||||
#[serde(rename = "EventID")]
|
#[serde(rename = "EventID")]
|
||||||
pub event_id: String,
|
pub event_id: String,
|
||||||
#[serde(rename = "Version")]
|
#[serde(rename = "Version")]
|
||||||
pub version: Option<String>,
|
version: Option<String>,
|
||||||
#[serde(rename = "Level")]
|
#[serde(rename = "Level")]
|
||||||
level: String,
|
level: String,
|
||||||
#[serde(rename = "Task")]
|
#[serde(rename = "Task")]
|
||||||
task: String,
|
task: String,
|
||||||
#[serde(rename = "Opcode")]
|
#[serde(rename = "Opcode")]
|
||||||
opcode: Option<String>,
|
opcode: Option<String>,
|
||||||
#[serde(rename = "Keywords")]
|
#[serde(rename = "Keywords")]
|
||||||
keywords: String,
|
keywords: String,
|
||||||
#[serde(rename = "TimeCreated")]
|
#[serde(rename = "TimeCreated")]
|
||||||
pub time_created: TimeCreated,
|
pub time_created: TimeCreated,
|
||||||
#[serde(rename = "EventRecordID")]
|
#[serde(rename = "EventRecordID")]
|
||||||
pub event_record_id: String,
|
pub event_record_id: String,
|
||||||
#[serde(rename = "Correlation")]
|
#[serde(rename = "Correlation")]
|
||||||
correlation: Option<String>,
|
correlation: Option<String>,
|
||||||
#[serde(rename = "Execution")]
|
#[serde(rename = "Execution")]
|
||||||
execution: Option<Execution>,
|
execution: Option<Execution>,
|
||||||
#[serde(rename = "Channel")]
|
#[serde(rename = "Channel")]
|
||||||
pub channel: String, // Security, System, Application ...etc
|
pub channel: String, // Security, System, Application ...etc
|
||||||
#[serde(rename = "Computer")]
|
#[serde(rename = "Computer")]
|
||||||
computer: String,
|
computer: String,
|
||||||
#[serde(rename = "Security")]
|
#[serde(rename = "Security")]
|
||||||
security: String,
|
security: String,
|
||||||
#[serde(rename = "Message")]
|
#[serde(rename = "Message")]
|
||||||
pub message: Option<String>,
|
pub message: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct EventData {
|
pub struct EventData {
|
||||||
#[serde(rename = "Data")]
|
#[serde(rename = "Data")]
|
||||||
pub data: Option<Vec<Data>>,
|
pub data: Option<Vec<Data>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct UserData {
|
pub struct UserData {
|
||||||
#[serde(rename = "LogFileCleared")]
|
#[serde(rename = "LogFileCleared")]
|
||||||
pub log_file_cleared: Option<LogFileCleared>,
|
pub log_file_cleared: Option<LogFileCleared>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct LogFileCleared {
|
pub struct LogFileCleared {
|
||||||
#[serde(rename = "SubjectUserSid")]
|
#[serde(rename = "SubjectUserSid")]
|
||||||
pub subject_user_sid: Option<String>,
|
pub subject_user_sid: Option<String>,
|
||||||
#[serde(rename = "SubjectUserName")]
|
#[serde(rename = "SubjectUserName")]
|
||||||
pub subject_user_name: Option<String>,
|
pub subject_user_name: Option<String>,
|
||||||
#[serde(rename = "SubjectDomainName")]
|
#[serde(rename = "SubjectDomainName")]
|
||||||
pub subject_domain_name: Option<String>,
|
pub subject_domain_name: Option<String>,
|
||||||
#[serde(rename = "SubjectLogonId")]
|
#[serde(rename = "SubjectLogonId")]
|
||||||
pub subject_logon_id: Option<String>,
|
pub subject_logon_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct Evtx {
|
pub struct Evtx {
|
||||||
#[serde(rename = "System")]
|
#[serde(rename = "System")]
|
||||||
pub system: System,
|
pub system: System,
|
||||||
#[serde(rename = "EventData")]
|
#[serde(rename = "EventData")]
|
||||||
pub event_data: Option<EventData>,
|
pub event_data: Option<EventData>,
|
||||||
#[serde(rename = "UserData")]
|
#[serde(rename = "UserData")]
|
||||||
pub user_data: Option<UserData>,
|
pub user_data: Option<UserData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Evtx {
|
impl Evtx {
|
||||||
//
|
//
|
||||||
// 文字列データを取得する
|
// 文字列データを取得する
|
||||||
//
|
//
|
||||||
fn get_string(v: &Data) -> String {
|
fn get_string(v: &Data) -> String {
|
||||||
let mut ret = "".to_string();
|
let mut ret = "".to_string();
|
||||||
if let Some(text) = &v.text {
|
if let Some(text) = &v.text {
|
||||||
ret = text.to_string();
|
ret = text.to_string();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// EventDataをHashMapとして取得する
|
// EventDataをHashMapとして取得する
|
||||||
//
|
//
|
||||||
pub fn parse_event_data(&self) -> HashMap<String, String> {
|
pub fn parse_event_data(&self) -> HashMap<String, String> {
|
||||||
let mut values = HashMap::new();
|
let mut values = HashMap::new();
|
||||||
|
|
||||||
if let Some(event_data) = &self.event_data {
|
if let Some(event_data) = &self.event_data {
|
||||||
if let Some(data) = &event_data.data {
|
if let Some(data) = &event_data.data {
|
||||||
for v in data.iter() {
|
for v in data.iter() {
|
||||||
if let Some(name) = &v.name {
|
if let Some(name) = &v.name {
|
||||||
values.insert(name.to_string(), Evtx::get_string(v));
|
values.insert(name.to_string(), Evtx::get_string(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
values
|
values
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user