Heap buffer overflow in Dualshock4Remapper::ProcessTouchData via malicious USB HID device
Categories
(Core :: DOM: Device Interfaces, defect, P2)
Tracking
()
People
(Reporter: fb.secresearch, Assigned: jstutte)
References
Details
(Keywords: csectype-bounds, reporter-external, sec-moderate, Whiteboard: [adv-main150+][adv-esr140.10+])
Attachments
(1 file, 3 external files)
|
18.72 KB,
application/zip
|
Details |
User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36
Steps to reproduce:
- Create a USB HID gadget impersonating a DualShock 4 controller (VID=054c, PID=05c4) with 8-byte HID reports using a valid gamepad descriptor. See attached
setup_gadget_multisize.sh. - Connect the device to a Windows machine running Firefox 148.0.
- Send HID reports at 60Hz (
send_reports.py --size 8). - Navigate to a page that calls
navigator.getGamepads()or registers agamepadconnectedlistener (see attachedpoc.html). No permission dialog is shown.
Tested with Firefox 148.0 Release (Windows 11) and ASAN Nightly (win64-asan-opt).
Attached files:
setup_gadget_multisize.sh creates the USB gadget (Linux configfs).
send_reports.py sends HID reports with configurable size.
poc.html reads and displays the leaked OOB heap bytes via GamepadTouch (requires dom.gamepad.extensions.multitouch=true to visualize the data, but the OOB read in the parent process occurs regardless of this pref).
Any USB composite device (keyboard, charger, etc.) can include a secondary HID interface with Sony's VID/PID to trigger this. The device does not need to look like a game controller.
Actual results:
ProcessTouchData() in GamepadRemapping.cpp:488 reads rawData[35] through rawData[42] using hardcoded offsets without checking the buffer length. With 8-byte reports this reads 26 bytes past the end of a 49-byte heap allocation in the parent process.
ASAN crashes immediately:
==2868==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x11fe452bdd8b
READ of size 1 at 0x11fe452bdd8b thread T135
#0 in mozilla::dom::Dualshock4Remapper::ProcessTouchData
GamepadRemapping.cpp:488
#1 in GamepadWindowProc WindowsGamepad.cpp:1023
0x11fe452bdd8b is located 26 bytes after 49-byte region
[0x11fe452bdd40,0x11fe452bdd71)
The function receives a void* without length. WindowsGamepad.cpp:1023 has raw->data.hid.dwSizeHid available but does not pass it.
Affected VID/PIDs (GamepadRemapping.cpp:2158-2160): 054c:05c4, 054c:09cc, 054c:0ba0.
Affected on Windows and macOS. Linux does not call ProcessTouchData.
When dom.gamepad.extensions.multitouch is enabled, the OOB bytes become readable from JavaScript through GamepadTouch.position[]. The attached log_8.txt shows 2569 unique readings from a single session, containing HTTP headers, internal resource:// URLs, file paths, and token fragments from the parent process heap.
Expected results:
ProcessTouchData should receive the buffer length and check len >= 43 before reading touch offsets. On Windows, dwSizeHid is already available in HandleRawInput. On macOS, report_len is passed to ReportChanged but not forwarded. Reports shorter than 43 bytes should skip touch processing.
Updated•7 months ago
|
Updated•7 months ago
|
Comment 1•7 months ago
|
||
The severity field is not set for this bug.
:cmartin, could you have a look please?
For more information, please visit BugBot documentation.
| Assignee | ||
Comment 3•7 months ago
|
||
Updated•7 months ago
|
| Assignee | ||
Comment 4•7 months ago
|
||
Thank you for the detailed report. The OOB read is confirmed and we have a patch in progress (D290082).
A few notes from our Claude assessment on severity and the information disclosure claim (to be checked):
OOB read — confirmed
ProcessTouchData receives a raw
void*with no length and reads hardcoded offsets 35–42. On Windows, the caller hasdwSizeHidavailable but doesn't pass it. On macOS, the caller only enforces an upper bound on report length, not a lower bound. This is a real bug that should be fixed.Information disclosure — overstated
The claim that OOB heap bytes are readable from JavaScript via
GamepadTouch.position[]deserves closer scrutiny. The OOB bytes go through bit-field extraction (e.g.((rawData[37] & 0xf) << 8) | rawData[36]) producing a 12-bit integer, which is then passed to NormalizeTouch — a linear mapping onto [-1.0, 1.0] over a 1920x942 range. While the linear transform is technically reversible, you recover at most ~12 bits per coordinate per report, not raw heap bytes. ThetouchIdfield leaks 7 bits per touch point.The report claims "2569 unique readings containing HTTP headers, internal resource:// URLs, file paths, and token fragments." Reconstructing meaningful strings from 12-bit quantized floats at this rate would be extremely difficult in practice. The practical information leakage is much lower than the report suggests.
Preconditions
Requires physical USB access to the target machine.
Requires a web page actively using the Gamepad API.
dom.gamepad.extensions.multitouchmust be enabled (default: false) for the touch data to be exposed to JS at all.
Linux is not affected (backend never calls ProcessTouchData).No in-the-wild crashes
Socorro shows zero crashes for ProcessTouchData, Dualshock4Remapper, GamepadRemapping, or WindowsGamepad — legitimate DualShock 4 controllers always send 64-byte reports, so this is not being hit by real devices.
Fix
The fix adds a length parameter to the
ProcessTouchDatavirtual interface and validatesaInputLen >= 43before accessing any offsets. Windows passesdwSizeHid, macOS passesreport_len.Given the physical access requirement, the lossy data path, and the disabled-by-default multitouch pref gating JS exposure, I'd suggest sec-low rather than sec-moderate.
Note: bug 2025404 is a duplicate of this bug (same issue found independently by automated tooling).
Updated•7 months ago
|
Comment 6•7 months ago
|
||
| Assignee | ||
Comment 7•7 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D290082
Updated•7 months ago
|
Comment 8•7 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined/Reason for urgency: A malicious USB HID could cause a heap buffer overflow.
- Code covered by automated testing?: yes
- Fix verified in Nightly?: yes
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing: none
- Risk associated with taking this patch: low
- Explanation of risk level: The patch just adds a bounds check where it should be.
- String changes made/needed?: none
- Is Android affected?: yes
Comment 9•7 months ago
|
||
firefox-esr140 Uplift Approval Request
- User impact if declined/Reason for urgency: A malicious USB HID could cause a heap buffer overflow.
- Code covered by automated testing?: yes
- Fix verified in Nightly?: yes
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing: none
- Risk associated with taking this patch: low
- Explanation of risk level: The patch just adds a bounds check where it should be.
- String changes made/needed?: none
- Is Android affected?: yes
| Assignee | ||
Comment 10•7 months ago
|
||
Original Revision: https://phabricator.services.mozilla.com/D290082
Updated•7 months ago
|
Updated•7 months ago
|
Comment 11•7 months ago
|
||
| uplift | ||
Updated•7 months ago
|
Updated•7 months ago
|
Comment 12•7 months ago
|
||
| uplift | ||
Updated•7 months ago
|
Updated•6 months ago
|
Updated•6 months ago
|
Updated•5 months ago
|
Updated•2 months ago
|
Description
•