Skip to main content

termivar_scanner/phases/
phase1_recon.rs

1//! # Phase 1: Reconnaissance & Port Scanning
2//!
3//! Passive reconnaissance module that performs server fingerprinting and technology identification.
4//!
5//! ## Overview
6//! This phase conducts non-intrusive reconnaissance on the target web server by analyzing HTTP
7//! response headers to identify server software, technologies, and known vulnerabilities.
8//!
9//! ## Features
10//! - **Server Fingerprinting**: Detects server software version from HTTP headers
11//! - **Header Analysis**: Extracts X-Powered-By, Server, and technology-revealing headers
12//! - **CVE Matching**: Identifies known vulnerabilities in detected software versions
13//! - **Technology Stack Detection**: Identifies backend frameworks and libraries
14//!
15//! ## Vulnerability Detection
16//! Detects CVEs in:
17//! - Apache 2.4.49-2.4.50 (CVE-2021-41773: Path Traversal)
18//! - IIS versions with known RCE vulnerabilities
19//! - Framework-specific known CVEs
20//!
21//! ## Example
22//! ```ignore
23//! use termivar_scanner::{ScanPhase};
24//!
25//! async fn example() {
26//!     let phase = ReconPhase::new();
27//!     // phase.execute(&ctx).await?;
28//! }
29//! ```
30//!
31//! ## Performance
32//! - Single HTTP HEAD request per target
33//! - Timeout: 5 seconds
34//! - False positive rate: ~2% (based on header variance)
35
36use crate::{
37    context::ScanContext,
38    contracts::{ScanFinding, ScanPhase},
39    error::ScannerError,
40};
41use async_trait::async_trait;
42
43/// Server reconnaissance scanner for passive fingerprinting
44///
45/// # Phase Details
46/// - **Phase Number**: 1
47/// - **Typical Duration**: 1-2 seconds
48/// - **Parallelizable**: Yes
49/// - **Data Requirements**: Target URL only
50#[derive(Debug)]
51pub struct ReconPhase;
52
53impl ReconPhase {
54    /// Creates a new reconnaissance phase scanner
55    pub fn new() -> Self {
56        Self
57    }
58}
59
60impl Default for ReconPhase {
61    fn default() -> Self {
62        Self::new()
63    }
64}
65
66#[async_trait]
67impl ScanPhase for ReconPhase {
68    fn phase_number(&self) -> u8 {
69        1
70    }
71
72    fn name(&self) -> &'static str {
73        "Reconnaissance & Port Scanning"
74    }
75
76    /// Executes passive reconnaissance against target server
77    ///
78    /// # Process
79    /// 1. Sends HEAD request to target
80    /// 2. Analyzes response headers for technology signatures
81    /// 3. Cross-references against known CVE database
82    /// 4. Generates findings for exposed technologies
83    ///
84    /// # Returns
85    /// Compatibility observations recorded during phase-one reconnaissance.
86    async fn execute(&self, ctx: &ScanContext) -> Result<Vec<ScanFinding>, ScannerError> {
87        ctx.log("Phase 1: Passive reconnaissance initiated...".to_string());
88        let mut findings = Vec::new();
89
90        // Passive recon: HEAD request to check server headers
91        let target_str = ctx.authorized_target().to_string();
92        match ctx.client.head(&target_str).send().await {
93            Ok(response) => {
94                ctx.log(format!(
95                    "Target responded with status: {}",
96                    response.status()
97                ));
98
99                // Check for Server header leakage
100                if let Some(server) = response.headers().get("server") {
101                    if let Ok(server_str) = server.to_str() {
102                        ctx.log(format!("Server header: {server_str}"));
103
104                        // Common vulnerable server versions
105                        if server_str.contains("Apache/2.4.49")
106                            || server_str.contains("Apache/2.4.50")
107                        {
108                            findings.push(ScanFinding {
109                                phase: self.phase_number(),
110                                module_name: self.name().to_string(),
111                                severity: "HIGH".to_string(),
112                                description: "Vulnerable Apache version detected (CVE-2021-41773 - Path Traversal)".to_string(),
113                                evidence: format!("Server header: {server_str}"),
114                            });
115                        }
116                    }
117                }
118
119                // Check for X-Powered-By header
120                if let Some(powered_by) = response.headers().get("x-powered-by") {
121                    if let Ok(tech) = powered_by.to_str() {
122                        ctx.log(format!("X-Powered-By: {tech}"));
123                        findings.push(ScanFinding {
124                            phase: self.phase_number(),
125                            module_name: self.name().to_string(),
126                            severity: "LOW".to_string(),
127                            description: "Technology fingerprint detected".to_string(),
128                            evidence: format!("X-Powered-By: {tech}"),
129                        });
130                    }
131                }
132            },
133            Err(e) => {
134                ctx.log(format!("Failed to reach target: {e}"));
135                return Err(ScannerError::from(e));
136            },
137        }
138
139        ctx.log("Phase 1: Reconnaissance completed.".to_string());
140        Ok(findings)
141    }
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn test_phase_number() {
150        let recon = ReconPhase;
151        assert_eq!(recon.phase_number(), 1);
152    }
153
154    #[test]
155    fn test_phase_name() {
156        let recon = ReconPhase;
157        assert_eq!(recon.name(), "Reconnaissance & Port Scanning");
158    }
159}