heap-use-after-free in WebTransportChild::RecvRemoteClosed
Categories
(Core :: DOM: Networking, defect, P1)
Tracking
()
People
(Reporter: ssherkito, Assigned: jesup)
References
Details
(Keywords: csectype-uaf, reporter-external, sec-high, Whiteboard: [necko-triaged][necko-priority-queue][adv-main136+][adv-esr128.8+][adv-esr115.21+])
Attachments
(5 files)
|
12.91 KB,
text/x-log
|
Details | |
|
733 bytes,
text/html
|
Details | |
|
216.21 KB,
application/x-zip-compressed
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
dmeehan
:
approval-mozilla-beta+
dmeehan
:
approval-mozilla-esr115+
dmeehan
:
approval-mozilla-esr128+
tjr
:
sec-approval+
|
Details | Review |
|
193 bytes,
text/plain
|
Details |
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
Firefox for Android
Steps to reproduce:
class WebTransportChild : public PWebTransportChild { public: NS_INLINE_DECL_REFCOUNTING(WebTransportChild) explicit WebTransportChild(WebTransport* aTransport) : mTransport(aTransport) {} ... protected: WebTransport* mTransport; // WebTransport holds a strong reference to us, and // calls Shutdown() before releasing it virtual ~WebTransportChild() { MOZ_ASSERT(!mTransport); } }; [0]
void WebTransport::Cleanup(WebTransportError* aError, const WebTransportCloseInfo* aCloseInfo, ErrorResult& aRv) { ... // Step 12: if (aCloseInfo) { // 12.1: Resolve closed with closeInfo. LOG(("Resolving mClosed with closeinfo")); mClosed->MaybeResolve(*aCloseInfo); [1] // 12.2: Assert: ready is settled. MOZ_ASSERT(mReady->State() != Promise::PromiseState::Pending); // 12.3: Close incomingBidirectionalStreams // This keeps the clang-plugin happy RefPtr<ReadableStream> stream = mIncomingBidirectionalStreams; stream->CloseNative(cx, IgnoreErrors()); // 12.4: Close incomingUnidirectionalStreams stream = mIncomingUnidirectionalStreams; stream->CloseNative(cx, IgnoreErrors());
The WebTransport Renderer IPC channel objectmanages the WebTransport Owner object as a raw pointer. [0]
The vulnerability occurs because the Cleanup function is called in the RecvRemoteClosed function, and a user event is called in that function. [1]
https://searchfox.org/mozilla-central/source/dom/webtransport/child/WebTransportChild.h#51 [0]
https://searchfox.org/mozilla-central/source/dom/webtransport/child/WebTransportChild.cpp#34 [1]
The http3 server was created using the open source https://github.com/aiortc/aioquic/tree/main and the demo.py wt function code was edited.
An easy patch that I thought of would be to either pass a WebTransport object to the stack in RecvRemoteClosed as a RefPtr, or check by handling WeakPtr since there is no part of the code that references the WebTransport object later.
(In reply to sherkito from comment #0)
Created attachment 9462034 [details]
asan.logUser Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
Firefox for AndroidSteps to reproduce:
public: NS_INLINE_DECL_REFCOUNTING(WebTransportChild) explicit WebTransportChild(WebTransport* aTransport) : mTransport(aTransport) {} ... protected: WebTransport* mTransport; // WebTransport holds a strong reference to us, and // calls Shutdown() before releasing it virtual ~WebTransportChild() { MOZ_ASSERT(!mTransport); } }; [0]``` ```void WebTransport::Cleanup(WebTransportError* aError, const WebTransportCloseInfo* aCloseInfo, ErrorResult& aRv) { ... // Step 12: if (aCloseInfo) { // 12.1: Resolve closed with closeInfo. LOG(("Resolving mClosed with closeinfo")); mClosed->MaybeResolve(*aCloseInfo); [1] // 12.2: Assert: ready is settled. MOZ_ASSERT(mReady->State() != Promise::PromiseState::Pending); // 12.3: Close incomingBidirectionalStreams // This keeps the clang-plugin happy RefPtr<ReadableStream> stream = mIncomingBidirectionalStreams; stream->CloseNative(cx, IgnoreErrors()); // 12.4: Close incomingUnidirectionalStreams stream = mIncomingUnidirectionalStreams; stream->CloseNative(cx, IgnoreErrors());``` The WebTransport Renderer IPC channel objectmanages the WebTransport Owner object as a raw pointer. [0] The vulnerability occurs because the Cleanup function is called in the RecvRemoteClosed function, and a user event is called in that function. [1] `https://searchfox.org/mozilla-central/source/dom/webtransport/child/WebTransportChild.h#51 [0]` `https://searchfox.org/mozilla-central/source/dom/webtransport/child/WebTransportChild.cpp#34 [1]` The http3 server was created using the open source `https://github.com/aiortc/aioquic/tree/main` and the demo.py `wt` function code was edited. An easy patch that I thought of would be to either pass a WebTransport object to the stack in RecvRemoteClosed as a RefPtr, or check by handling WeakPtr since there is no part of the code that references the WebTransport object later.
Updated•1 year ago
|
Updated•1 year ago
|
Updated•1 year ago
|
| Assignee | ||
Updated•1 year ago
|
| Assignee | ||
Comment 4•1 year ago
|
||
Thanks for the detailed report. So I can verify the bug and fixes, how are you starting the aioquic server?
python examples/demo.py --certificate tests/ssl_cert.pem --private-key tests/ssl_key.pem exits for me without errors, so I'm probably not starting it correctly
(In reply to Randell Jesup [:jesup] (needinfo me) from comment #4)
Thanks for the detailed report. So I can verify the bug and fixes, how are you starting the aioquic server?
python examples/demo.py --certificate tests/ssl_cert.pem --private-key tests/ssl_key.pemexits for me without errors, so I'm probably not starting it correctly
I used the command python examples/http3_server.py -c cert.pem -k key.pem --host 127.0.0.1
First, run python http3_server.py -c cert.pem -k key.pem and if it doesn't work, try running it with --host 127.0.0.1 append as above
| Assignee | ||
Comment 6•1 year ago
|
||
Aha, from above I thought you were running demo.py. I can run now, but I don't have the cert/key mentioned above, which have to match the cert specified in the poc. I commented out the cert from the POC, and that changes the error, but I still don't hit an ASAN failure. It never get to 'ready'; I appear to be getting a rejection creating the session from the server:
[Child 1781830: Main Thread]: D/WebTransport Creating WebTransport for https://127.0.0.1:4433/wt
[Child 1781830: Main Thread]: D/WebTransport Creating WebTransport 51100033d8c0
[Child 1781830: Main Thread]: D/WebTransport Created datagram streams
[Child 1781830: Main Thread]: D/WebTransport Connecting WebTransport to parent for https://127.0.0.1:4433/wt
[Parent 1781656: IPDL Background]: D/WebTransport Created WebTransportParent 516000149a80 https://127.0.0.1:4433/wt Dedicated congestion=Default
[Parent 1781656: Socket Thread]: D/WebTransport Binding parent endpoint
[Parent 1781656: Main Thread]: D/WebTransport WebTransport 516000149a80 AsyncConnect
[Parent 1781656: Main Thread]: D/WebTransport webtransport 516000149a80 session creation failed code= 0, reason=
[Child 1781830: Main Thread]: D/WebTransport isreject: 0 nsresult 0x80004005
[Child 1781830: Main Thread]: D/WebTransport Rejected connection 51100033d8c0 80004005
[Child 1781830: Main Thread]: D/WebTransport Cleanup started
[Child 1781830: Main Thread]: D/WebTransport Rejecting mClosed
[Child 1781830: Main Thread]: D/WebTransport WebTransportChild::Shutdown() for 51300020a480 (51100033d8c0)
[Parent 1781656: Socket Thread]: D/WebTransport ActorDestroy WebTransportParent 3
JavaScript error: , line 0: WebTransportError: WebTransport connection rejected
[Parent 1781656: Socket Thread]: D/WebTransport Destroying WebTransportParent 516000149a80
JavaScript error: , line 0: WebTransportError: WebTransport connection rejected
(In reply to Randell Jesup [:jesup] (needinfo me) from comment #6)
Aha, from above I thought you were running demo.py. I can run now, but I don't have the cert/key mentioned above, which have to match the cert specified in the poc. I commented out the cert from the POC, and that changes the error, but I still don't hit an ASAN failure. It never get to 'ready'; I appear to be getting a rejection creating the session from the server:
[Child 1781830: Main Thread]: D/WebTransport Creating WebTransport for https://127.0.0.1:4433/wt [Child 1781830: Main Thread]: D/WebTransport Creating WebTransport 51100033d8c0 [Child 1781830: Main Thread]: D/WebTransport Created datagram streams [Child 1781830: Main Thread]: D/WebTransport Connecting WebTransport to parent for https://127.0.0.1:4433/wt [Parent 1781656: IPDL Background]: D/WebTransport Created WebTransportParent 516000149a80 https://127.0.0.1:4433/wt Dedicated congestion=Default [Parent 1781656: Socket Thread]: D/WebTransport Binding parent endpoint [Parent 1781656: Main Thread]: D/WebTransport WebTransport 516000149a80 AsyncConnect [Parent 1781656: Main Thread]: D/WebTransport webtransport 516000149a80 session creation failed code= 0, reason= [Child 1781830: Main Thread]: D/WebTransport isreject: 0 nsresult 0x80004005 [Child 1781830: Main Thread]: D/WebTransport Rejected connection 51100033d8c0 80004005 [Child 1781830: Main Thread]: D/WebTransport Cleanup started [Child 1781830: Main Thread]: D/WebTransport Rejecting mClosed [Child 1781830: Main Thread]: D/WebTransport WebTransportChild::Shutdown() for 51300020a480 (51100033d8c0) [Parent 1781656: Socket Thread]: D/WebTransport ActorDestroy WebTransportParent 3 JavaScript error: , line 0: WebTransportError: WebTransport connection rejected [Parent 1781656: Socket Thread]: D/WebTransport Destroying WebTransportParent 516000149a80 JavaScript error: , line 0: WebTransportError: WebTransport connection rejected
Here's how I solved the certificate errors.
- Issue a certificate with a command like
cargo run --example gencertviahttps://github.com/BiagioFesta/wtransportand specify the serverCertificateHashes value in poc.html with the output key value - Since the certificate created above is not an official certificate, Firefox does not process WebTransport properly. To solve this, I set the value of
network.http.http3.disable_when_third_party_roots_foundinabout:configlisted inhttps://github.com/BiagioFesta/wtransport/issues/241to true
| Assignee | ||
Comment 8•1 year ago
|
||
just a small correction, set network.http.http3.disable_when_third_party_roots_found to false. Thanks!
| Assignee | ||
Comment 9•1 year ago
|
||
I can run the poc now, thanks! But in repeated attempts I haven't been able to trigger an ASAN fault (though I believe it's real). Anything else about your environment which might affect it? OS, Firefox version, etc? I'm running a local ASAN build on Fedora 41, optimized.
| Assignee | ||
Comment 10•1 year ago
|
||
I'll bet it's due to this: JavaScript error: http://127.0.0.1/webtrans.html, line 5: ReferenceError: FuzzingFunctions is not defined
| Assignee | ||
Comment 11•1 year ago
|
||
With a --enable-fuzzing build, and fuzzing.enabled = true, I can repro. Thanks
| Assignee | ||
Comment 12•1 year ago
|
||
Updated•1 year ago
|
| Assignee | ||
Comment 13•1 year ago
|
||
Comment on attachment 9462561 [details]
Bug 1944126: Update WebTransportChild r=#dom-storage-reviewers!
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Possible
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Yes
- Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: all
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: Trivial
- How likely is this patch to cause regressions; how much testing does it need?: Impossible
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
Beta/Release Uplift Approval Request
- User impact if declined/Reason for urgency: Sec-high
- Is this code covered by automated tests?: No
- Has the fix been verified in Nightly?: No
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): Just holds a refptr
- String changes made/needed: none
- Is Android affected?: Yes
Updated•1 year ago
|
Updated•1 year ago
|
Comment 14•1 year ago
|
||
Comment on attachment 9462561 [details]
Bug 1944126: Update WebTransportChild r=#dom-storage-reviewers!
Approved to land
Updated•1 year ago
|
Comment 15•1 year ago
|
||
Comment 16•1 year ago
|
||
Comment 17•1 year ago
|
||
Comment on attachment 9462561 [details]
Bug 1944126: Update WebTransportChild r=#dom-storage-reviewers!
Approved for 136.0b2
Comment 18•1 year ago
|
||
| uplift | ||
Updated•1 year ago
|
Comment 19•1 year ago
|
||
Comment on attachment 9462561 [details]
Bug 1944126: Update WebTransportChild r=#dom-storage-reviewers!
Approved for 128.8esr
Comment 20•1 year ago
|
||
| uplift | ||
Updated•1 year ago
|
Updated•1 year ago
|
Comment 21•1 year ago
|
||
Comment on attachment 9462561 [details]
Bug 1944126: Update WebTransportChild r=#dom-storage-reviewers!
Approved for 115.21esr
Comment 22•1 year ago
|
||
| uplift | ||
Updated•1 year ago
|
Updated•11 months ago
|
Comment 23•11 months ago
|
||
Updated•11 months ago
|
| Reporter | ||
Comment 24•7 months ago
|
||
Is there no bounty for this bug?
Updated•7 months ago
|
Comment 25•6 months ago
|
||
(In reply to sherkito from comment #24)
Is there no bounty for this bug?
My apologies. It looks like a bug bounty was never requested when you filed this? Flagging it for the committee meeting next week.
Comment 26•6 months ago
|
||
FWIW you can file your bugs through the form at https://bugzilla.mozilla.org/form.client.bounty to make sure the bounty-request flag is properly set.
Updated•6 months ago
|
Description
•