Skip to content

Buffer overflow due to use of `strcpy` in `performRtspHandshake`

High
cgutman published GHSA-4927-23jw-rq62 Dec 14, 2023

Package

moonlight-common-c

Affected versions

>= 0c0a51b10ecc5b3415ea78c21d96d679e2288f9

Patched versions

>= 24750d4b748fefa03d09fcfd6d45056faca354e0

Description

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 issue exists within the performRtspHandshake() function in RtspConnection.c. The RTSP URL received from the game stream server is copied into static buffer rtspTargetUrl of size 256, causing an overflow:

strcpy(rtspTargetUrl, serverInfo->rtspSessionUrl);

The server-provided serverInfo->rtspSessionUrl 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 24750d4

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/

  1. Extract the webserver to a clean directory:
tar xf exploit.tar.xz
  1. Install needed dependencies (ideally within a Python virtual environment):
python3 -m pip install -r requirements.txt
  1. 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
  1. Create a moonlight.conf with the following contents:
address = <ADDRESS_OF_EXPLOIT_SERVER>
bitrate = 20000
  1. Invoke moonlight stream:
moonlight -config path/to/moonlight.conf stream
  1. 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/event5
Failed to open device /dev/input/event6
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/event7
Failed to open device /dev/input/event9
Failed to open device /dev/input/event10
Failed to open device /dev/input/event13
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/event8
Failed to open device /dev/input/event4
Failed to open device /dev/input/event12
Failed to open device /dev/input/event0
Failed to open device /dev/input/event11
=================================================================
==511071==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7fdf58df2a00 at pc 0x563b87ca9c8b bp 0x7ffc3def5e70 sp 0x7ffc3def5638
WRITE of size 131080 at 0x7fdf58df2a00 thread T0
    #0 0x563b87ca9c8a in __interceptor_strcpy (/home/keane/src/moonlight-embedded/build/moonlight+0xe3c8a) (BuildId: 2971e520010823d36c5caa4a027a2b5a8ebd7cca)
    #1 0x7fdf58cad1d3 in performRtspHandshake /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:797:13
    #2 0x7fdf58c07c90 in LiStartConnection /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/Connection.c:415:11
    #3 0x563b87d1902b in stream /home/keane/src/moonlight-embedded/src/main.c:146:3
    #4 0x563b87d1515c in main /home/keane/src/moonlight-embedded/src/main.c:395:5
    #5 0x7fdf582456c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #6 0x7fdf58245784 in __libc_start_main csu/../csu/libc-start.c:360:3
    #7 0x563b87c3bb80 in _start (/home/keane/src/moonlight-embedded/build/moonlight+0x75b80) (BuildId: 2971e520010823d36c5caa4a027a2b5a8ebd7cca)

0x7fdf58df2a00 is located 0 bytes to the right of global variable 'rtspTargetUrl' defined in '/home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:9:13' (0x7fdf58df2900) of size 256
SUMMARY: AddressSanitizer: global-buffer-overflow (/home/keane/src/moonlight-embedded/build/moonlight+0xe3c8a) (BuildId: 2971e520010823d36c5caa4a027a2b5a8ebd7cca) in __interceptor_strcpy
Shadow bytes around the buggy address:
  0x0ffc6b1b64f0: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 f9 f9 f9
  0x0ffc6b1b6500: 00 f9 f9 f9 01 f9 f9 f9 04 f9 f9 f9 01 f9 f9 f9
  0x0ffc6b1b6510: 00 f9 f9 f9 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9
  0x0ffc6b1b6520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffc6b1b6530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ffc6b1b6540:[f9]f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9 00 f9 f9 f9
  0x0ffc6b1b6550: 00 f9 f9 f9 00 f9 f9 f9 00 00 00 00 00 00 00 00
  0x0ffc6b1b6560: 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 04 f9 f9 f9
  0x0ffc6b1b6570: 04 f9 f9 f9 01 f9 f9 f9 01 f9 f9 f9 01 f9 f9 f9
  0x0ffc6b1b6580: 04 f9 f9 f9 01 f9 f9 f9 00 f9 f9 f9 02 f9 f9 f9
  0x0ffc6b1b6590: 00 f9 f9 f9 04 f9 f9 f9 02 f9 f9 f9 01 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
=================================================================
==511071==ERROR: AddressSanitizer: SEGV on unknown address 0x7fdf58e04000 (pc 0x7fdf58373000 bp 0x7ffc3def5e70 sp 0x7ffc3def5628 T0)
==511071==The signal is caused by a WRITE memory access.
    #0 0x7fdf58373000 in __strcpy_avx2 string/../sysdeps/x86_64/multiarch/strcpy-avx2.S:222
    #1 0x563b87ca9cbc in __interceptor_strcpy (/home/keane/src/moonlight-embedded/build/moonlight+0xe3cbc) (BuildId: 2971e520010823d36c5caa4a027a2b5a8ebd7cca)
    #2 0x7fdf58cad1d3 in performRtspHandshake /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/RtspConnection.c:797:13
    #3 0x7fdf58c07c90 in LiStartConnection /home/keane/src/moonlight-embedded/third_party/moonlight-common-c/src/Connection.c:415:11
    #4 0x563b87d1902b in stream /home/keane/src/moonlight-embedded/src/main.c:146:3
    #5 0x563b87d1515c in main /home/keane/src/moonlight-embedded/src/main.c:395:5
    #6 0x7fdf582456c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0x7fdf58245784 in __libc_start_main csu/../csu/libc-start.c:360:3
    #8 0x563b87c3bb80 in _start (/home/keane/src/moonlight-embedded/build/moonlight+0x75b80) (BuildId: 2971e520010823d36c5caa4a027a2b5a8ebd7cca)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV string/../sysdeps/x86_64/multiarch/strcpy-avx2.S:222 in __strcpy_avx2
==511071==ABORTING

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CVE ID

CVE-2023-42800

Weaknesses

Credits