Possible RCE execution in StationUrl #54
Labels
No labels
bug
duplicate
enhancement
feature request
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
spacebar/rust-nex#54
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A few years ago we found a universal RCE path in all NEX clients on the 3DS, Wii U, and Switch. We reported this to Nintendo and they confirmed that they had fixed it already on the NSO servers, but every client still has the vulnerable code
I was only just yesterday given permission to disclose the bug, so I'm alerting relevant parties so everyone can make sure everything is safe, including you guys
TLDR,
nn::nex::StationURL::Formatin the NEX client has no bounds checks and only allocates enough space for a URL up to length 1024 (some older RDV clients also have this bug, but Quazal/Ubisoft fixed it themselves at some point in the client itself). StationURLs can be submitted by the client to the server and can contain any data (this is by design, since games are allowed to define custom URL parameters outside of the standard ones, which several Ubisoft games do make use of), and the server relays them back to other clients during matchmaking, and there's a code path that calls theFormatfunction when this happens. When we tested this on a 3DS years ago, we got a PoC that was "easy mode" RCENintendo patched this on the server-side by just checking the submitted URL length by the client, which is what we also did at Pretendo Network
I poked around here for a bit and didn't see the same kind of server-side checks, and while you do limit the fields a StationURL can contain, and none of those fields allow for a value of arbitrary length, I believe there is still a path here to trigger the bug
rnex seems to not de-duplicate fields, decoding them into a list rather than a keyed map (or some other method to prevent duplicate fields). This means that a client can send a StationURL string with the same, short, field many times, getting past the 1024 limit
I took out the encoding/decoding methods from rnex to do an isolated test, and got rnex to produce a StationURL longer than 1024 by just repeating the
addressfield 43 times (I chose that field because it was just the longest and so required to least duplication, but this applies to any field). This test was made using the default branch of the repo, if changes are in another branch that fix this then I have not tested those:I will admit that I am by no means a Rust expert, nor am I well versed in your libraries specifically. I may have made a mistake here or misunderstood something. This is an isolated test with the encoder/decoder, I may have missed some other prevention elsewhere (like if you check the string length in an RMC handler or something), but I didn't see anything like that in my poking. If there are other mitigations for this in place elsewhere, disregard
Thank you for the report, let me just run a check on the refactor branch to see if this is still an issue as we are planning on merging that into main soon
Issue should be fixed in dca2900263 for the
v0branch, I have the fix for refactor in my local tree but we haven't deployed that to any production servers and I'm working on fixing some NAT probing issues on it so I won't push that just yet. On my side I ran your code on both refactor and v0 and it seems to be fine now but if you could double check on your side in case I missed something?That should be good enough, that's basically what we/Nintendo did as well. My only suggestion would be to use a proper error code here since a StationURL longer than 1024 is invalid, but the rejection itself handles the fix just fine
@jonbarrow wrote in #54 (comment):
I might add the error code to the refactor but honestly if someone has a station URL of 1024+ that's probably not a real console anyways so the error code would have no effect
Fair enough. Sounds good, always happy to help