Closed Bug 1741210 Opened 2 years ago Closed 2 years ago

Potential out-of-bounds write due to integer overflow [@ SnappyUncompress]

Categories

(Core :: Storage: localStorage & sessionStorage, defect, P2)

x86_64
All
defect

Tracking

()

RESOLVED FIXED
96 Branch
Tracking Status
firefox-esr91 --- wontfix
firefox94 --- wontfix
firefox95 --- wontfix
firefox96 --- fixed

People

(Reporter: decoder, Assigned: jjalkanen)

References

Details

(Keywords: csectype-intoverflow, sec-other, Whiteboard: [adv-main96+r])

Attachments

(1 file)

The Snappy code here

https://searchfox.org/mozilla-central/rev/3c8a7970944daaf917b547dffc0790bcd37cadc1/dom/localstorage/SnappyUtils.cpp#62

resizes nsACString dest with the uncompressed length of the data. Since the uncompressed length is larger than the compressed length, this can overflow when calling setLength which takes 32-bit for the length.

The result will be an out-of-bounds write while decompressing.

I talked to :janv about this and since local storage is limited to 5MB per origin, this shouldn't ever be exploitable from content. However, I don't know where this limit is enforced and maybe it is possible to circumvent that via IPC and feed larger data into the SnappyUtils.

Leaving unclassified until we have investigated this further.

Found with -Wshorten-64-to-32 with some custom filters on top of it + manual code inspection.

LSNG was enabled by default for 92+, so I guess the status for ESR91 depends on whether this affects the old localstorage too or not?

Assignee: nobody → jjalkanen
Severity: -- → S2
Priority: -- → P2

Where does the compressed data come from in the first place? I don't think a child could send a string through IPC that's long enough to trigger this, unless the compression is done on the child side. Or is the thing being uncompressed some big storage blob that's accumulated over many separate web content writes to storage?

If this data could come from the child this could lead to a sandbox escape that would be sec-high. But otherwise if we can't get strings big enough this might not be exploitable at all.

Flags: needinfo?(jjalkanen)

Local storage can use 5M of quota per origin, and the IPC messages are limited to 512M. The data field sizes in the underlying database are limited to the maximum signed 32-bit integer.

The compression header stores the uncompressed size as a 32-bit unsigned integer which is cast to size_t only on return, see https://searchfox.org/mozilla-central/source/other-licenses/snappy/src/snappy.cc#431 , https://searchfox.org/mozilla-central/source/other-licenses/snappy/src/snappy-stubs-internal.h#535 and another implementation https://searchfox.org/mozilla-central/source/other-licenses/snappy/src/snappy.cc#779

For me, it's not easy to see how to exploit this.

Flags: needinfo?(jjalkanen)
Keywords: sec-other
Group: dom-core-security → core-security-release
Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 96 Branch
Flags: qe-verify-
Whiteboard: [adv-main96+r]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: