Skip to content

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

High
cgutman published GHSA-r8cf-45f4-vf8m Dec 14, 2023

Package

moonlight-common-c

Affected versions

>= 0c0a51b10ecc5b3415ea78c21d96d679e2288f9

Patched versions

>= 02b7742f4d19631024bd766bd2bb76715780004e

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 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/

  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/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

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-42799

Weaknesses

Credits