diff --git a/Cargo.lock b/Cargo.lock index 0f46c2f..086a2bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,7 +245,7 @@ checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "lin_fh" -version = "0.4.1" +version = "0.4.5" dependencies = [ "arrayvec", "chrono", diff --git a/Cargo.toml b/Cargo.toml index c20baaa..82525bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lin_fh" -version = "0.4.1" +version = "0.4.5" authors = ["brian kellogg "] edition = "2021" diff --git a/src/data_def.rs b/src/data_def.rs index 6b9929d..e2e45d6 100644 --- a/src/data_def.rs +++ b/src/data_def.rs @@ -33,6 +33,8 @@ Options: -p, --port Destination port to send output to [default: 80] -l, --limit Limit CPU use -s, --suidsgid Search for suid and sgid files + - This will search the entire '/' including subdirectories + - Can take a very long time Note: If not run as root some telemetry cannot be harvested. diff --git a/src/main.rs b/src/main.rs index d6c7348..3dc5984 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ mod mutate; mod time; use walkdir::WalkDir; -use std::fs::{self}; +use std::{fs::{self}, path::{PathBuf, Path}}; use regex::Regex; use {data_def::*, file_op::*, mutate::*, time::*}; use std::os::unix::fs::MetadataExt; @@ -162,7 +162,7 @@ fn find_paths(text: &str, already_seen: &mut Vec) -> std::io::Result<()> .expect("Invalid Regex"); } for c in RE.captures_iter(text) { - let path = std::path::Path::new(&c[1]); + let path = Path::new(&c[1]); process_file("FileContent", path, already_seen)?; } Ok(()) @@ -172,7 +172,7 @@ fn find_paths(text: &str, already_seen: &mut Vec) -> std::io::Result<()> check if a given file is one we want to inspect the contents of for interesting strings and references to other files */ -fn watch_file(file_path: &std::path::Path, path: &str, already_seen: &mut Vec) -> std::io::Result<()> { +fn watch_file(file_path: &Path, path: &str, already_seen: &mut Vec) -> std::io::Result<()> { if WATCH_FILES.iter().any(|f| path.contains(f)) { let data = read_file_string(file_path)?; if !data.is_empty() { @@ -185,7 +185,7 @@ fn watch_file(file_path: &std::path::Path, path: &str, already_seen: &mut Vec) -> std::io::Result<()> { +fn process_file(pdt: &str, file_path: &Path, already_seen: &mut Vec) -> std::io::Result<()> { let p: String = file_path.to_string_lossy().into(); if file_path.is_file() && !already_seen.contains(&p.clone()) { already_seen.push(p); // track files we've processed so we don't process them more than once @@ -308,7 +308,7 @@ fn process_open_file(pdt: &str, fd: &str, path: &str, pid: i32, already_seen: &m TxProcessFile::new(pdt.to_string(), data_type.clone(), get_now()?, pid, fd.to_string(), path.to_string(), path_exists(fd)).report_log(); - process_file(&data_type, std::path::Path::new(path), already_seen)?; + process_file(&data_type, Path::new(path), already_seen)?; Ok(()) } @@ -337,7 +337,7 @@ fn process_file_descriptors(path: &str, root_path: &str, pid: i32, data_type: &s } // gather and report process information via procfs -fn process_process(root_path: &str, bin: std::path::PathBuf, already_seen: &mut Vec) -> std::io::Result<()> { +fn process_process(root_path: &str, bin: PathBuf, already_seen: &mut Vec) -> std::io::Result<()> { let path: String = resolve_link(&bin)?.to_string_lossy().into(); let exists = path_exists(&path); let cmd = read_file_string(&push_file_path(root_path, "/cmdline")?)?; @@ -483,7 +483,7 @@ fn process_files(pdt: &str, path: &str, mut already_seen: &mut Vec) -> s "/etc/crontab" => parse_cron(pdt, path)?, _ => {} }; - process_file(&pdt, std::path::Path::new(path), &mut already_seen)?; + process_file(&pdt, Path::new(path), &mut already_seen)?; Ok(()) } @@ -522,7 +522,7 @@ fn process_directory(pdt: &str, path: &str, mut already_seen: &mut Vec) Weird issue getting hung on a /proc dir on my box: /proc/4635/task/4635/net ls: reading directory '/proc/4635/task/4635/net': Invalid argument total 0 -*/ + fn find_suid_sgid(already_seen: &mut Vec) -> std::io::Result<()> { for entry in WalkDir::new("/") .into_iter() @@ -543,6 +543,31 @@ fn find_suid_sgid(already_seen: &mut Vec) -> std::io::Result<()> { } } Ok(()) +}*/ + +// one possible implementation of walking a directory only visiting files +fn find_suid_sgid(dir: &Path, already_seen: &mut Vec) -> std::io::Result<()> { + if dir.is_dir() { + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path: PathBuf = entry.path(); + if path.is_dir() { + find_suid_sgid(&path, already_seen)?; + } else { + let md = match entry.metadata() { + Ok(d) => d, + Err(_e) => continue // catch any errors so we can finish searching all dirs + }; + let mode = md.mode(); + let (is_suid, is_sgid) = is_suid_sgid(mode); + if is_suid || is_sgid { + process_file("SuidSgid", &path, already_seen)?; + } + sleep(); + } + } + } + Ok(()) } /* @@ -572,8 +597,9 @@ fn main() -> std::io::Result<()> { Err(_e) => continue}; } } + // WARNING: searches entire directory structure if ARGS.flag_suidsgid { - find_suid_sgid(&mut already_seen)?; // WARNING: searches entire directory structure + find_suid_sgid(&push_file_path("/", "")?, &mut already_seen)?; } Ok(()) } \ No newline at end of file diff --git a/src/mutate.rs b/src/mutate.rs index 056e89c..bc20bd0 100644 --- a/src/mutate.rs +++ b/src/mutate.rs @@ -61,7 +61,7 @@ pub fn to_int8(num: &str) -> std::io::Result { Therefore have to break the 128bit value into 4 dwords, reverse them and recombine See: https://users.rust-lang.org/t/convert-hex-socket-notation-to-ip-and-port/33858/8 */ -pub fn u128_to_ipv6 (mut n: u128) -> std::io::Result<::std::net::Ipv6Addr> { +pub fn u128_to_ipv6(mut n: u128) -> std::io::Result<::std::net::Ipv6Addr> { unsafe { &mut *(&mut n as *mut u128 as *mut [u32; 4]) } .iter_mut() .for_each(|n: &mut u32| *n = n.swap_bytes());