Files
s-b-repo-rustsploit/docs/Security-Validation.md
T
2026-04-21 17:01:52 +02:00

219 lines
6.9 KiB
Markdown

# Security & Input Validation
Rustsploit implements defence-in-depth throughout the codebase. All contributors must follow these patterns when writing modules or modifying core code.
---
## Validation Constants
| File | Constant | Value | Purpose |
|------|----------|-------|---------|
| `shell.rs` | `MAX_INPUT_LENGTH` | 4096 | Maximum shell input length |
| `sanitize.rs` | `MAX_TARGET_LENGTH` | 2048 | Maximum target string length |
| `shell.rs` | `MAX_URL_LENGTH` | 2048 | Maximum URL length |
| `shell.rs` | `MAX_PATH_LENGTH` | 4096 | Maximum file path length |
| `utils.rs` | `MAX_FILE_SIZE` | 10 MB | Maximum file size to read |
| `config.rs` | `MAX_HOSTNAME_LENGTH` | 253 | DNS hostname limit |
| `api.rs` | `MAX_REQUEST_BODY_SIZE` | 1 MB | API request body limit |
| `api.rs` | `MAX_TRACKED_IPS` | 100,000 | IP tracker limit |
---
## Security Patterns
### 1. Input Length Validation
```rust
if input.len() > MAX_INPUT_LENGTH {
return Err(anyhow!("Input too long (max {} characters)", MAX_INPUT_LENGTH));
}
```
### 2. Input Sanitization
The `sanitize_string_input()` function performs multiple layers of cleaning:
1. **Null byte removal** -- inputs containing `\0` are rejected outright
2. **Control character filtering** -- all control characters (except `\t`) are stripped from the input
3. **Length enforcement** -- inputs exceeding `MAX_COMMAND_LENGTH` are rejected
```rust
// Reject null bytes, then filter control characters (except tab)
let sanitized: String = input.chars()
.filter(|c| !c.is_control() || *c == '\t')
.collect();
```
For command-specific validation (`validate_command_input`), null bytes are stripped and length is enforced against `MAX_COMMAND_LENGTH`.
If suspicious patterns (`bash`, `sudo`, `../`) are detected, a warning is printed but the string is still returned unmodified:
```
[!] Input contains shell/path patterns. Treated as literal text string.
```
### 3. Path Traversal Prevention
```rust
if input.contains("..") || input.contains("//") {
return Err(anyhow!("Path traversal detected"));
}
```
### 4. Target / Hostname Validation
Always use the framework's `normalize_target` function:
```rust
use crate::utils::normalize_target;
let normalized = normalize_target(raw_target)?;
// Handles IPv4, IPv6, hostnames, URLs, CIDR with full validation
```
For custom character validation:
```rust
use regex::Regex;
let valid_chars = Regex::new(r"^[a-zA-Z0-9.\-_:\[\]]+$").unwrap();
if !valid_chars.is_match(target) {
return Err(anyhow!("Invalid characters in target"));
}
```
### 5. Overflow Protection
```rust
// Use saturating_add to prevent integer overflow
counter = counter.saturating_add(1);
```
### 6. Prompt Attempt Limiting
```rust
const MAX_ATTEMPTS: u8 = 10;
let mut attempts = 0u8;
loop {
attempts += 1;
if attempts > MAX_ATTEMPTS {
println!("Too many invalid attempts. Using default.");
return Ok(default);
}
// prompt logic
}
```
### 7. File Operations
When reading files:
1. Validate path does not contain `..`
2. Use `canonicalize()` to resolve the real path
3. Check file size before reading (ref: `MAX_FILE_SIZE`)
4. Skip symlinks for security
---
## API Security
The API server (`api.rs`) implements:
- **`RequestBodyLimitLayer`** — prevents DoS via oversized payloads (1 MB max)
- **Rate limiting** — 3 failed auth attempts → 30 s block per IP
- **Auto-cleanup** — old entries purged at 100,000 entries
- **IP tracking + key rotation** — suspicious activity triggers auto-rotation in hardening mode
- **Secure defaults** — by default, considers `127.0.0.1` as the intended private bind
- **WebSocket limits** — max 100 concurrent connections, 1 MiB frame cap, 30s heartbeat
---
## MCP Server Security
The MCP server (`mcp/server.rs`) implements:
- **`isolate_protocol_stdout()`** — redirects fd 1 to /dev/null so module `println!` cannot corrupt the JSON-RPC stream
- **`MAX_LINE_BYTES`** — 1 MiB cap on incoming lines to prevent memory exhaustion
- **Binary-safe reads** — uses `read_until()` instead of `read_line()` for no UTF-8 requirement
- **Non-UTF-8 error handling** — returns proper JSON-RPC error responses for malformed input
---
## Spool Security
The spool system (`spool.rs`) implements:
- **`O_NOFOLLOW`** — prevents TOCTOU race conditions on symlinked spool files
- **Parent symlink check** — rejects spool paths with symlinked parent directories
- **Lock-first pattern** — acquires write lock before creating files to prevent orphaned files
- **`write_line()` returns `Result`** — callers handle write failures instead of silently dropping output
---
## Privilege Checks
Modules requiring raw sockets call `require_root()` at startup:
```rust
use crate::utils::privilege::require_root;
require_root("ICMP raw socket")?;
```
Returns a descriptive error with the current euid instead of a cryptic "permission denied" from the socket layer. Used by DoS modules, ping sweep, and raw packet scanners.
---
## Honeypot Detection
The framework automatically runs `basic_honeypot_check` before any module execution when a target is set.
- Scans **200 common ports** with a 250 ms timeout each
- If **11 or more** ports respond, warns that the target is likely a honeypot
- Runs automatically in the shell's `run` and `run_all` commands
- Can be called manually from module code:
```rust
use crate::utils::basic_honeypot_check;
basic_honeypot_check(&ip).await;
```
---
## IP Exclusion Ranges (`EXCLUDED_RANGES`)
Standard across mass-scan capable modules (e.g., `camxploit`, `telnet_hose`, `telnet_bruteforce`, exploit modules with 0.0.0.0/0 support):
| CIDR | Category |
|------|----------|
| `10.0.0.0/8` | Private |
| `127.0.0.0/8` | Loopback |
| `172.16.0.0/12` | Private |
| `192.168.0.0/16` | Private |
| `224.0.0.0/4` | Multicast |
| `240.0.0.0/4` | Reserved |
| `0.0.0.0/8` | This network |
| `100.64.0.0/10` | Carrier-grade NAT |
| `169.254.0.0/16` | Link-local |
| `198.18.0.0/15` | Benchmarking |
| `198.51.100.0/24` | Documentation |
| `203.0.113.0/24` | Documentation |
| `255.255.255.255/32` | Broadcast |
| Public DNS | 1.1.1.1, 8.8.8.8, etc. |
Uses the `ipnetwork` crate for proper CIDR matching.
---
## Persistent Storage Security
All persistent data uses atomic write-to-temp-then-rename to prevent corruption:
| File | Purpose | Sensitivity |
|------|---------|-------------|
| `~/.rustsploit/global_options.json` | Global options (setg) | Low — user preferences |
| `~/.rustsploit/creds.json` | Discovered credentials | **High — contains passwords/hashes** |
| `~/.rustsploit/workspaces/<name>.json` | Hosts, services, notes | Medium — engagement data |
| `~/.rustsploit/loot_index.json` | Loot metadata | Medium |
| `~/.rustsploit/loot/` | Loot files | **High — may contain sensitive data** |
| `~/.rustsploit/results/` | Module output files | Medium |
| `~/.rustsploit/history.txt` | Shell command history | Medium |
**Important:** The `creds.json` and `loot/` files may contain sensitive data. Protect `~/.rustsploit/` with appropriate file permissions (e.g., `chmod 700`).