#[cfg(test)]
mod penetration_tests {
use std::sync::{Arc, Barrier};
use std::thread;
use tempfile::TempDir;
#[test]
fn exploit_race_condition_data_loss() {
println!("\n🔴 EXPLOIT 1: Race Condition Data Loss Attack");
println!("================================================");
let temp_dir = TempDir::new().unwrap();
let original_dir = std::env::current_dir().unwrap();
std::env::set_current_dir(temp_dir.path()).unwrap();
unsafe { std::env::set_var("NARU_ENCRYPTION_KEY", "test_key_for_race_condition") };
if let Err(e) = crate::core::persistence::init_project() {
println!("Init failed: {:?}", e);
let _ = std::env::set_current_dir(&original_dir);
unsafe { std::env::remove_var("NARU_ENCRYPTION_KEY") };
return;
}
let mut config: crate::core::models::ConfigFile =
match crate::core::persistence::load_json(crate::core::constants::CONFIG_FILE) {
Ok(c) => c,
Err(e) => {
println!("Failed to load config: {:?}", e);
let _ = std::env::set_current_dir(&original_dir);
unsafe { std::env::remove_var("NARU_ENCRYPTION_KEY") };
return;
}
};
if let Some(env_config) = config.environments.get_mut("development") {
env_config.entries.insert(
"SHARED_KEY".to_string(),
crate::core::models::ConfigValueEntry::new("initial_value", "string", false),
);
}
let _ = crate::core::persistence::save_json(crate::core::constants::CONFIG_FILE, &config);
let barrier = Arc::new(Barrier::new(3));
let mut handles = vec![];
for i in 0..3 {
let barrier_clone = Arc::clone(&barrier);
let handle = thread::spawn(move || {
barrier_clone.wait();
let mut config: crate::core::models::ConfigFile =
match crate::core::persistence::load_json(crate::core::constants::CONFIG_FILE) {
Ok(c) => c,
Err(_) => return,
};
if let Some(env_config) = config.environments.get_mut("development") {
env_config.entries.insert(
"SHARED_KEY".to_string(),
crate::core::models::ConfigValueEntry::new(
&format!("thread{}_value", i),
"string",
false,
),
);
}
let _ = crate::core::persistence::save_json(
crate::core::constants::CONFIG_FILE,
&config,
);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let final_value: String = crate::core::persistence::load_json(crate::core::constants::CONFIG_FILE)
.ok()
.and_then(|config: crate::core::models::ConfigFile| {
config.environments.get("development")
.and_then(|e| e.entries.get("SHARED_KEY"))
.map(|e| e.value.clone())
})
.unwrap_or_default();
println!("Final value after race: {}", final_value);
let valid_values = [
"initial_value",
"thread0_value",
"thread1_value",
"thread2_value",
];
if !valid_values.contains(&final_value.as_str()) {
println!(
"⚠️ RACE CONDITION DETECTED: Unexpected value '{}'",
final_value
);
} else {
println!("✓ No obvious race condition detected in this run");
}
let _ = std::env::set_current_dir(original_dir);
unsafe { std::env::remove_var("NARU_ENCRYPTION_KEY") };
}
#[test]
fn exploit_path_traversal_attack() {
println!("\n🔴 EXPLOIT 2: Path Traversal Attack");
println!("====================================");
let malicious_path = "../../../etc/passwd";
let result = crate::core::security::sanitize_file_path(malicious_path);
if result.is_ok() {
println!("⚠️ PATH TRAVERSAL SUCCESSFUL: Attacker could read /etc/passwd");
} else {
let error = result.unwrap_err();
if error.contains("traversal") || error.contains("Absolute paths") {
println!("✓ Path traversal blocked: {}", error);
} else {
println!("? Path traversal blocked: {}", error);
}
}
}
#[test]
fn exploit_null_byte_injection() {
println!("\n🟠 EXPLOIT 3: Null Byte Injection Attack");
println!("==========================================");
let null_byte_key = "MALICIOUS_KEY\0.txt";
let result = crate::core::security::validate_config_key(null_byte_key);
if result.is_ok() {
println!("⚠️ NULL BYTE INJECTION SUCCESSFUL");
} else {
println!("✓ Null byte injection blocked: {}", result.unwrap_err());
}
}
#[test]
fn exploit_regex_dos_attack() {
println!("\n🟡 EXPLOIT 4: Regex DoS (ReDoS) Attack");
println!("========================================");
use std::time::Instant;
let pathological_pattern = r"(a+)+$";
let malicious_input = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!";
let start = Instant::now();
let re = regex::Regex::new(pathological_pattern).unwrap();
let _result = re.is_match(malicious_input);
let duration = start.elapsed();
if duration.as_millis() > 100 {
println!(
"⚠️ ReDoS VULNERABILITY: Pattern took {:?} to evaluate",
duration
);
} else {
println!("✓ Regex evaluation completed in {:?} (safe)", duration);
}
}
#[test]
fn exploit_audit_log_injection() {
println!("\n🟡 EXPLOIT 5: Audit Log Injection Attack");
println!("==========================================");
let malicious_key = "KEY\n{\"injected\": true}";
let validation_result = crate::core::security::validate_config_key(malicious_key);
println!("✓ Key validation result: {:?}", validation_result);
}
#[test]
fn exploit_secret_masking_bypass() {
println!("\n🟡 EXPLOIT 6: Secret Masking Bypass");
println!("====================================");
let test_keys = [
"DB_PWD",
"API_SECRET_KEY",
"AUTH_TOKEN",
"MY_PASSPHRASE",
];
for key in &test_keys {
let result = crate::core::security::validate_config_key(key);
println!(" Key {}: {:?}", key, result);
}
println!("✓ All keys validated properly");
}
#[test]
fn exploit_integer_overflow() {
println!("\n🟢 EXPLOIT 7: Integer Overflow Test");
println!("====================================");
let overflow_values = [
"9223372036854775808", "-9223372036854775809", "18446744073709551616", ];
use crate::core::models::FieldDefinition;
use crate::core::validation::validate_value;
let field = FieldDefinition {
key: "OVERFLOW_KEY".to_string(),
r#type: "integer".to_string(),
description: None,
validation: None,
is_secret: false,
};
for value in &overflow_values {
let result = validate_value(value, &field);
if result.is_ok() {
println!("⚠️ Integer overflow accepted: {}", value);
} else {
println!("✓ Integer overflow rejected: {}", value);
}
}
}
#[test]
fn exploit_unicode_normalization() {
println!("\n🟠 EXPLOIT 8: Unicode Normalization Attack");
println!("============================================");
use unicode_normalization::UnicodeNormalization;
let composed = "café"; let decomposed = "cafe\u{0301}";
println!("Composed: {} (bytes: {})", composed, composed.len());
println!("Decomposed: {} (bytes: {})", decomposed, decomposed.len());
println!("NFC equal: {}", composed.nfc().eq(decomposed.nfc()));
let composed_result = crate::core::security::validate_config_key(composed);
let decomposed_result = crate::core::security::validate_config_key(decomposed);
println!("Composed validation: {:?}", composed_result);
println!("Decomposed validation: {:?}", decomposed_result);
assert!(composed_result.is_ok());
assert!(decomposed_result.is_ok());
println!("✓ Unicode normalization handled correctly");
}
#[test]
fn run_all_penetration_tests() {
println!("\n");
println!("╔══════════════════════════════════════════════════════════╗");
println!("║ NARU PENETRATION TESTING SUITE ║");
println!("╚══════════════════════════════════════════════════════════╝");
exploit_path_traversal_attack();
exploit_null_byte_injection();
exploit_regex_dos_attack();
exploit_audit_log_injection();
exploit_secret_masking_bypass();
exploit_integer_overflow();
exploit_unicode_normalization();
println!("\n");
println!("╔══════════════════════════════════════════════════════════╗");
println!("║ PENETRATION TESTING COMPLETE ║");
println!("╚══════════════════════════════════════════════════════════╝");
}
}