Nov 16, 2022

6.5 - Medium

XSS & Defacement Risk

Full report for Nuxt Devtools path traversal.

This vulnerability was disclosed & fixed, but regressed and was not fixed again.

Description

This is a regression of this vulnerability.

The new version of ohash is using a truncated SHA256 algorithm to produce hashes.

Nuxt's useFetch function relies upon these to store information returned from requests.

Root Cause

ohash has a truncated SHA256 algorithm. This significantly reduces the time taken to find a hash collision for a given key. Only 60 of the available 256 bits need to collide.

useFetchuses this hash function with user supplied input.

  const _key = opts.key || hash([autoKey, unref(opts.baseURL), typeof request === 'string' ? request : '', unref(opts.params)])

Using a Naive probabilistic search you will have a >50% chance of getting a match in < 5.5 months @ 50gh/s, this hash rate is the equivalent of 2 4090 graphics cards (thanks @chick3nman).

With a larger amount of resources this attack becomes far easier.

While this is a quantity of time that may seem unreasonable for an attack, it is still well within the realms of possibility.

Exploitation

First, identify that the site is vulnerable:

  1. A useFetch call that returns trusted input must occur first.
  2. A useFetch call with user input in params on URL must occur next.

Next calculate or identify the key to be overwritten. We can see all keys by viewing nuxt' s payload.

<script>
window.__NUXT__=
{
  data: {
    y6Av1KLiFh:"\u003Cimg src=x onerror=alert(1)\u003ERandomDataHere",
    PbshibZuhD:"\u003Cp\u003EExample Text\u003C\u002Fp\u003E"
  }, 
  ... 
}
</script>

Next identify a parameter value that causes a hash collision with the desired key. This is the hardest step.

Lastly send the request using the collided hash.

Proof of Concept

This proof of concept does not use a real collision as it would be too expensive for me to find one. However it does simulate the effects of a collision by providing the key used.

StackBlitz

Mitigation

Use a larger hash to reduce the risk of collision.

Alternatively do not use a hash or remove user supplied input from hash function.

Notes

Vulnerability was reintroduced in https://github.com/nuxt/framework/pull/6632.

Links: