Impact
A malicious game streaming server could exploit a buffer overflow vulnerability to crash a moonlight client, or achieve remote code execution (RCE) on the client (with insufficient exploit mitigations or if mitigations can be bypassed). The CVSS vulnerabililty severity score is based on the worst-case scenario of a client with no exploit mitigations.
This vulnerability takes place after the pairing process, so it requires the user to be tricked into pairing to a malicious host. It is not possible to perform using a MITM due to public key pinning that takes place during the pairing process.
Summary
A buffer overflow was introduced in this commit due to unmitigated usage of unsafe C functions and improper bounds checking.
Details
A memory corruption exists within the parseUrlAddrFromRtspUrlString
function in RtspConnection.c
. The RTSP URL string received from the game streaming server is copied into urlAddr
, which is a static buffer of length 48:
|
strcpy(destination, rtspUrlScratchBuffer + prefixLen); |
The server-provided
rtspUrlScratchBuffer
contents may be of arbitrary length, so it can overflow
urlAddr
into the surrounding memory, allowing for a crash or RCE.
The vulnerable code path requires the client to have selected a video bitrate of at least 15 Mbps.
Patch
The bug was addressed in 02b7742
Affected Moonlight Client Versions
Known affected clients are listed below for convenience. Not all clients may be vulnerable with the same severity due to differences in built-in exploit mitigations on each platform.
Affected client version ranges (inclusive):
There may be other third-party Moonlight clients and forks that were not investigated for vulnerability.
PoC
A Python webserver can be used to simulate the gamestream server and serve the exploit: https://github.com/k3an3/cve/moonlight-common-c/
- Extract the webserver to a clean directory:
- Install needed dependencies (ideally within a Python virtual environment):
python3 -m pip install -r requirements.txt
- Run the webserver, and a proxy to handle TLS connections (requires
ssl-cert
Debian package, or similar):
socat openssl-listen:47984,fork,reuseaddr,key=/etc/ssl/private/ssl-cert-snakeoil.key,cert=/etc/ssl/certs/ssl-cert-snakeoil.pem,verify=0 tcp:127.0.0.1:47989
python3 app.py
- Create a
moonlight.conf
with the following contents:
address = <ADDRESS_OF_EXPLOIT_SERVER>
bitrate = 20000
- Invoke
moonlight stream
:
moonlight -config path/to/moonlight.conf stream
- The program should crash.
AddressSanitizer output:
$ ./moonlight stream
/home/keane/src/moonlight-embedded/src/config.c:125:20: runtime error: applying non-zero offset 1 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/keane/src/moonlight-embedded/src/config.c:125:20 in
Failed to open device /dev/input/event7
Failed to open device /dev/input/event8
Failed to open device /dev/input/event2
Failed to open device /dev/input/event1
Failed to open device /dev/input/event3
Failed to open device /dev/input/event11
Failed to open device /dev/input/event12
Failed to open device /dev/input/event14
Failed to open device /dev/input/event15
Failed to open device /dev/input/event16
Failed to open device /dev/input/event17
Failed to open device /dev/input/event4
Failed to open device /dev/input/event5
Failed to open device /dev/input/event13
Failed to open device /dev/input/event0
Failed to open device /dev/input/event10
=================================================================
==3625494==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7ff102ff27d0 at pc 0x55e3eee41167 bp 0x7ffc54296810 sp 0x7ffc54295fd8
WRITE of size 131073 at 0x7ff102ff27d0 thread T0
#0 0x55e3eee41166 in __interceptor_strcpy (/home/keane/src/moonlight-embedded/build/moonlight+0xe3166) (BuildId: 86b3510cc7e8650dfd2c4bf59c233cc8c1add2ef)
#1 0x7ff102eb85c6 in parseUrlAddrFromRtspUrlString /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:704:5
#2 0x7ff102eacfdd in performRtspHandshake /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:795:51
#3 0x7ff102e07c80 in LiStartConnection /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/Connection.c:415:11
#4 0x55e3eeeaf22b in stream /home/keane/src/moonlight-embedded/src/main.c:146:3
#5 0x55e3eeeab35c in main /home/keane/src/moonlight-embedded/src/main.c:395:5
#6 0x7ff1024456c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#7 0x7ff102445784 in __libc_start_main csu/../csu/libc-start.c:360:3
#8 0x55e3eedd3b80 in _start (/home/keane/src/moonlight-embedded/build/moonlight+0x75b80) (BuildId: 86b3510cc7e8650dfd2c4bf59c233cc8c1add2ef)
0x7ff102ff27d0 is located 48 bytes to the left of global variable 'rtspTargetUrl' defined in '/home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:9:13' (0x7ff102ff2800) of size 256
0x7ff102ff27d0 is located 0 bytes to the right of global variable 'urlAddr' defined in '/home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:13:13' (0x7ff102ff27a0) of size 48
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/keane/src/moonlight-embedded/build/moonlight+0xe3166) (BuildId: 86b3510cc7e8650dfd2c4bf59c233cc8c1add2ef) in __interceptor_strcpy
Shadow bytes around the buggy address:
0x0ffea05f64a0: 00 00 00 00 f9 f9 f9 f9 04 f9 f9 f9 04 f9 f9 f9
0x0ffea05f64b0: 00 00 f9 f9 01 f9 f9 f9 04 f9 f9 f9 04 f9 f9 f9
0x0ffea05f64c0: 04 f9 f9 f9 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9
0x0ffea05f64d0: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
0x0ffea05f64e0: 00 f9 f9 f9 01 f9 f9 f9 04 f9 f9 f9 01 f9 f9 f9
=>0x0ffea05f64f0: 00 f9 f9 f9 00 00 00 00 00 00[f9]f9 f9 f9 f9 f9
0x0ffea05f6500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ffea05f6510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ffea05f6520: f9 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9 00 f9 f9 f9
0x0ffea05f6530: 00 f9 f9 f9 00 f9 f9 f9 00 00 00 00 00 00 00 00
0x0ffea05f6540: 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 04 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3625494==ERROR: AddressSanitizer: SEGV on unknown address 0x7ff10300b000 (pc 0x7ff102573013 bp 0x7ffc54296810 sp 0x7ffc54295fc8 T0)
==3625494==The signal is caused by a WRITE memory access.
#0 0x7ff102573013 in __strcpy_avx2 string/../sysdeps/x86_64/multiarch/strcpy-avx2.S:226
#1 0x55e3eee41198 in __interceptor_strcpy (/home/keane/src/moonlight-embedded/build/moonlight+0xe3198) (BuildId: 86b3510cc7e8650dfd2c4bf59c233cc8c1add2ef)
#2 0x7ff102eb85c6 in parseUrlAddrFromRtspUrlString /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:704:5
#3 0x7ff102eacfdd in performRtspHandshake /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:795:51
#4 0x7ff102e07c80 in LiStartConnection /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/Connection.c:415:11
#5 0x55e3eeeaf22b in stream /home/keane/src/moonlight-embedded/src/main.c:146:3
#6 0x55e3eeeab35c in main /home/keane/src/moonlight-embedded/src/main.c:395:5
#7 0x7ff1024456c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#8 0x7ff102445784 in __libc_start_main csu/../csu/libc-start.c:360:3
#9 0x55e3eedd3b80 in _start (/home/keane/src/moonlight-embedded/build/moonlight+0x75b80) (BuildId: 86b3510cc7e8650dfd2c4bf59c233cc8c1add2ef)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV string/../sysdeps/x86_64/multiarch/strcpy-avx2.S:226 in __strcpy_avx2
==3625494==ABORTING
Impact
A malicious game streaming server could exploit a buffer overflow vulnerability to crash a moonlight client, or achieve remote code execution (RCE) on the client (with insufficient exploit mitigations or if mitigations can be bypassed). The CVSS vulnerabililty severity score is based on the worst-case scenario of a client with no exploit mitigations.
This vulnerability takes place after the pairing process, so it requires the user to be tricked into pairing to a malicious host. It is not possible to perform using a MITM due to public key pinning that takes place during the pairing process.
Summary
A buffer overflow was introduced in this commit due to unmitigated usage of unsafe C functions and improper bounds checking.
Details
A memory corruption exists within the
parseUrlAddrFromRtspUrlString
function inRtspConnection.c
. The RTSP URL string received from the game streaming server is copied intourlAddr
, which is a static buffer of length 48:moonlight-common-c/src/RtspConnection.c
Line 704 in 2bb026c
The server-provided
rtspUrlScratchBuffer
contents may be of arbitrary length, so it can overflowurlAddr
into the surrounding memory, allowing for a crash or RCE.The vulnerable code path requires the client to have selected a video bitrate of at least 15 Mbps.
Patch
The bug was addressed in 02b7742
Affected Moonlight Client Versions
Known affected clients are listed below for convenience. Not all clients may be vulnerable with the same severity due to differences in built-in exploit mitigations on each platform.
Affected client version ranges (inclusive):
There may be other third-party Moonlight clients and forks that were not investigated for vulnerability.
PoC
A Python webserver can be used to simulate the gamestream server and serve the exploit: https://github.com/k3an3/cve/moonlight-common-c/
ssl-cert
Debian package, or similar):moonlight.conf
with the following contents:moonlight stream
:AddressSanitizer output: