Man-in-the-Middle Attack (MitM)
debt(d7/e5/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). Semgrep and Psalm can catch explicit patterns like CURLOPT_SSL_VERIFYPEER set to false, but many MitM vulnerabilities (weak cipher suites, missing HSTS headers, HTTP fallback paths) are not caught by static analysis and only surface during code review or penetration testing. The automated detection noted in detection_hints is narrow — it catches the most egregious cases but misses subtler ones.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix mentions enforcing HTTPS everywhere with HSTS, certificate pinning for mobile apps, and verifying TLS certificates on all outbound PHP requests. This is not a single-line patch — it requires updating server configuration, adding HSTS headers, auditing all curl/HTTP client calls across the codebase, and possibly changing deployment infrastructure. It spans multiple files and concerns.
Closest to 'persistent productivity tax' (b5). The applies_to covers web, api, and cli contexts broadly. Every developer making outbound HTTP requests or configuring TLS must keep MitM mitigations in mind. The burden is not purely localised — it influences API integration patterns, server config, CI pipelines, and mobile app builds — but it does not fully define system architecture, sitting at b5.
Closest to 'serious trap' (t7). The misconception field explicitly states 'HTTPS fully prevents MITM attacks,' which contradicts a widespread and intuitive belief. A competent developer who knows HTTPS exists will commonly assume TLS equals safety, missing SSL stripping, rogue CAs, and weak cipher suites. This directly contradicts how a similar concept (TLS encryption) is understood elsewhere, warranting t7.
Also Known As
TL;DR
Explanation
MitM attacks can occur at the network level (ARP spoofing, rogue Wi-Fi hotspots) or through TLS weaknesses (certificate spoofing, protocol downgrade attacks). Once positioned between client and server, an attacker can eavesdrop on credentials and session tokens or inject malicious content. Defence relies on end-to-end TLS with certificate pinning for sensitive applications, HSTS to prevent protocol downgrade, and rejecting invalid certificates rather than accepting them silently in PHP's cURL or stream contexts.
Diagram
flowchart LR
CLIENT3[Client] -->|thinks connecting to server| MITM[Attacker<br/>MitM position]
MITM -->|forwards to| SERVER2[Real Server]
SERVER2 -->|response| MITM
MITM -->|modified response| CLIENT3
subgraph Defences
TLS2[TLS - encrypt in transit]
CERT[Certificate validation<br/>verify server identity]
PINNING[Certificate pinning<br/>mobile apps]
HSTS2[HSTS - force HTTPS]
end
style MITM fill:#f85149,color:#fff
style TLS2 fill:#238636,color:#fff
style HSTS2 fill:#238636,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Setting CURLOPT_SSL_VERIFYPEER to false, disabling certificate verification entirely.
- Not enforcing HTTPS — allowing HTTP fallback that MITM can strip.
- No HSTS header — browser will not refuse HTTP connections proactively.
- Using self-signed certificates in production that train users to accept certificate warnings.
Code Examples
// Disabling SSL verification — completely open to MITM:
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Never do this in production
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// HTTPS + HSTS — browsers always use HTTPS after first visit
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
// Verify TLS in outbound PHP requests — never disable
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // verify cert chain
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // verify hostname
// NEVER: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// GuzzleHTTP — verification on by default
$client = new GuzzleHttp\Client(); // verify=true by default
// nginx cipher config:
// ssl_protocols TLSv1.2 TLSv1.3;
// ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;