1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/// Penetration Testing Module for Naru
/// This module contains proof-of-concept exploits for identified vulnerabilities
#[cfg(test)]
mod penetration_tests {
use std::sync::{Arc, Barrier};
use std::thread;
use tempfile::TempDir;
// ========================================================================
// EXPLOIT 1: Race Condition Attack (CRITICAL)
// CWE-362: Concurrent Execution using Shared Resource
// ========================================================================
#[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") };
// Initialize naru using persistence API directly
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;
}
// Set initial value using atomic API
let _ = crate::core::persistence::atomic_update_config(|config| {
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),
);
}
Ok(())
});
// Simulate concurrent writes (race condition) using atomic API
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();
// All threads try to set different values simultaneously
let _ = crate::core::persistence::atomic_update_config(|config| {
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,
),
);
}
Ok(())
});
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
// Get the final value using atomic API
let final_value: String = crate::core::persistence::atomic_read_config(|config| {
config
.environments
.get("development")
.and_then(|e| e.entries.get("SHARED_KEY"))
.map(|e| e.value.clone())
})
.ok()
.flatten()
.unwrap_or_default();
println!("Final value after race: {}", final_value);
// With atomic operations, we should NOT lose any writes in a way that produces an invalid state
// but since they are all overwriting the same key, the last one wins.
// The important part is that we don't have partial data or corruption.
let valid_thread_values = ["thread0_value", "thread1_value", "thread2_value"];
if !valid_thread_values.contains(&final_value.as_str()) {
println!(
"⚠️ RACE CONDITION DETECTED: Unexpected value '{}'",
final_value
);
} else {
println!("✓ Atomic operations prevented data corruption during race");
}
let _ = std::env::set_current_dir(original_dir);
unsafe { std::env::remove_var("NARU_ENCRYPTION_KEY") };
}
// ========================================================================
// EXPLOIT 2: Path Traversal Attack (HIGH)
// CWE-22: Improper Limitation of a Pathname to a Restricted Directory
// ========================================================================
#[test]
fn exploit_path_traversal_attack() {
println!("\n🔴 EXPLOIT 2: Path Traversal Attack");
println!("====================================");
// Try path traversal attack - test the security function directly
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);
}
}
}
// ========================================================================
// EXPLOIT 3: Null Byte Injection (HIGH)
// CWE-693: Protection Mechanism Failure
// ========================================================================
#[test]
fn exploit_null_byte_injection() {
println!("\n🟠 EXPLOIT 3: Null Byte Injection Attack");
println!("==========================================");
// Try null byte injection in key name - test the security function directly
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());
}
}
// ========================================================================
// EXPLOIT 4: Regex DoS Attack (MEDIUM)
// CWE-1333: Inefficient Regular Expression Complexity
// ========================================================================
#[test]
fn exploit_regex_dos_attack() {
println!("\n🟡 EXPLOIT 4: Regex DoS (ReDoS) Attack");
println!("========================================");
use std::time::Instant;
// Test pathological regex pattern
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);
}
}
// ========================================================================
// EXPLOIT 5: Audit Log Injection (MEDIUM)
// CWE-117: Improper Output Neutralization for Logs
// ========================================================================
#[test]
fn exploit_audit_log_injection() {
println!("\n🟡 EXPLOIT 5: Audit Log Injection Attack");
println!("==========================================");
// Try to inject malicious content via key name - test validation directly
let malicious_key = "KEY\n{\"injected\": true}";
let validation_result = crate::core::security::validate_config_key(malicious_key);
println!("✓ Key validation result: {:?}", validation_result);
}
// ========================================================================
// EXPLOIT 6: Secret Masking Bypass (MEDIUM)
// CWE-532: Insertion of Sensitive Information into Log File
// ========================================================================
#[test]
fn exploit_secret_masking_bypass() {
println!("\n🟡 EXPLOIT 6: Secret Masking Bypass");
println!("====================================");
// Test key validation for various key patterns
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");
}
// ========================================================================
// EXPLOIT 7: Integer Overflow in Validation (LOW)
// CWE-190: Integer Overflow or Wraparound
// ========================================================================
#[test]
fn exploit_integer_overflow() {
println!("\n🟢 EXPLOIT 7: Integer Overflow Test");
println!("====================================");
// Try integer overflow values - test validation directly
// Note: This test doesn't need project initialization since it tests
// the validation function directly
let overflow_values = [
"9223372036854775808", // i64::MAX + 1
"-9223372036854775809", // i64::MIN - 1
"18446744073709551616", // u64::MAX + 1
];
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);
}
}
}
// ========================================================================
// EXPLOIT 8: Unicode Normalization Attack (HIGH)
// CWE-179: Incorrect Behavior Order: Early Validation
// ========================================================================
#[test]
fn exploit_unicode_normalization() {
println!("\n🟠 EXPLOIT 8: Unicode Normalization Attack");
println!("============================================");
use unicode_normalization::UnicodeNormalization;
// Two visually identical strings with different Unicode representations
let composed = "café"; // Single codepoint for é
let decomposed = "cafe\u{0301}"; // e + combining acute accent
println!("Composed: {} (bytes: {})", composed, composed.len());
println!("Decomposed: {} (bytes: {})", decomposed, decomposed.len());
println!("NFC equal: {}", composed.nfc().eq(decomposed.nfc()));
// Test if validation treats them the same
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);
// Both should be valid
assert!(composed_result.is_ok());
assert!(decomposed_result.is_ok());
println!("✓ Unicode normalization handled correctly");
}
// ========================================================================
// SUMMARY
// ========================================================================
#[test]
fn run_all_penetration_tests() {
println!("\n");
println!("╔══════════════════════════════════════════════════════════╗");
println!("║ NARU PENETRATION TESTING SUITE ║");
println!("╚══════════════════════════════════════════════════════════╝");
// Run tests that don't require directory changes
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!("╚══════════════════════════════════════════════════════════╝");
}
}