Insufficiently complex hash function used in `useFetch` means return data cannot be trusted in nuxt/framework

Valid

Reported on

Jul 5th 2022


Description

The useFetch function uses the ohash library to key requests. This hash function outputs a 32 bit number. Finding a collision for this function is easy.

In a situation where useFetch is called more than once, any call after the first that contains untrusted input into any argument is vulnerable.

Propose the following situation:

  • The username is loaded from the API using useFetch
  • HTML to be reflected onto the page is requested using useFetch, a user controlled header lang is passed in the options.

An attacker can do the following:

  • Calculate the hash value of the first API call
  • Find a value for lang that means hash(username request) = hash(html request)
  • Change their username to a HTML payload
  • Attackier triggers the request with the value for lang that causes the collision.

While this scenario would only trigger self XSS, you can imagine how this could cause a variety of issues, from RCE to XSS, due to the fact that this possibility is not documented, and part of this handling occurs on the server side.

Proof of Concept

https://stackblitz.com/edit/nuxt-starter-vxvqw4aaaaaaaaaaaaaa?file=app.vue&file=app.vue

Add ?motd=1 to the url, then add ?motd=y8jZ4OYVgtb4t4CrbwSOz5ZoklNMFOAxPR6lchnFmKU= to the url.

In this example the motd can be replaced with the user's name. While the MOTD was trusted data, the username could be any value provided by the user.

This collision took around 15 minutes to find.

Impact

It's entirely dependant on how the data from useFetch is used. Any subsequent action that is used under the impression that the data is trusted can potentially be exploited.

I'd imagine the most likely issue to occur would be XSS, I was not able to find any examples of this issue occurring within open source projects so I'm unable to provide a better answer.

References

We are processing your report and will contact the nuxt/framework team within 24 hours. 3 months ago
We have contacted a member of the nuxt/framework team and are waiting to hear back 3 months ago
pooya parsa modified the Severity from Medium to Low 3 months ago
pooya parsa modified the Severity from Low to Medium (6.5) 3 months ago
The researcher has received a minor penalty to their credibility for miscalculating the severity: -1
pooya parsa validated this vulnerability 3 months ago

Hi OhB00 and thanks so much for the report.

I can confirm the key hash collision possibility and that it can potentially open vulnerability to malfunction of the web application (thus marked as high for integrity surface)

The possibility of XSS is unlikely since Nuxt escapes all payloads and for rendering, v-html directive used has to be used by care and only on trusted data. It is a developer error if using that.

For the fix, we are working on a new feature in Nuxt 3 that automatically generates payload keys based on (static) code position instead of user input variable: https://github.com/nuxt/framework/pull/4955

As a faster workaround, we could add a length variable salt to the hash but I guess the above improvement should land soon to nuxt>=3.0.0-rc.5 and remove the need for that.

For end-users: Immediate action is to ensure not rendering untrusted data using v-html directive and use a custom { key } prop for useFetch on requests that integration values.

Cheers.

OhB00 has been awarded the disclosure bounty
The fix bounty is now up for grabs
The researcher's credibility has increased: +7
OhB00
3 months ago

Researcher


Thanks for your reply, I was also curious about submitting vulnerability reports for https://github.com/unjs/nitro, what is the correct channel for this?

Daniel Roe
3 months ago

It is also through Huntr: https://huntr.dev/repos/unjs/nitro.

Jamie Slome
2 months ago

Admin


The score has been re-adjusted for this report from 6 to 7 👍

Furthermore, I've created this feature improvement to track the removal of penalities if the severity or vulnerability type is reverted to the original (post-adjustment from a maintainer).

We have sent a fix follow up to the nuxt/framework team. We will try again in 7 days. 2 months ago
We have sent a second fix follow up to the nuxt/framework team. We will try again in 10 days. 2 months ago
We have sent a third and final fix follow up to the nuxt/framework team. This report is now considered stale. 2 months ago
pooya parsa confirmed that a fix has been merged on dcf7e8 a month ago
The fix bounty has been dropped
pooya parsa gave praise a month ago
Thanks for reporting the issue and follow-ups <3
The researcher's credibility has slightly increased as a result of the maintainer's thanks: +1
to join this conversation