Hacker News new | ask | show | jobs
by iterateoften 452 days ago
Maybe im misunderstanding how people are building endpoints these days, but every post about this I see how it can bypass auth.

Wouldn’t this bypass auth only for sites where auth is true/false?

I’ve never worked on a site were auth is a boolean. Auth is always a relative. The middleware is only there to identify the user. Then when querying for objects, you query objects related to that user.

Or if you are serving an admin page you check that the user is an admin.

I honestly find it more astounding that people put an admin security check to check the url of a page and redirect away in a middleware and no security on the views themselves.

Is this form of checking paths in middleware officially from NextJS or did people just get lazy? Seems like the worst way to build auth I could ever dream up across any framework or language.

If a middleware is bypassed all endpoints should return empty responses. In my nextjs apps the middleware is simply a convenience method for the user if they are logged out they get redirected to the login page. But all api endpoints check for the active user and serve objects relative to the user.

6 comments

> “Is this form of checking paths in middleware officially from NextJS or did people just get lazy?”

This is a common way to implement auth in many frameworks, not just JS ones. Off the top of my head I know that Laravel (PHP) does it this way. I guess you could call it “being lazy” but most people would refer to it using the age-old software engineering terms “don’t repeat yourself” and “separation of concerns.”

The authentication middleware can choose to redirect or not based on many things: did the user provide the correct credentials, does the user have the necessary permissions to access the requested resource, etc… And you can put all the logic for determining those many things in a single place, so that it can easily be updated. Individual routes can remain as they are, and you don’t have to worry about forgetting to implement some part of the auth checking logic on one of them.

This attack isn't only about auth, auth is just the most drastic obvious example. Middleware is often used for a wide range of sanity checks. You could bypass, say, limit checks and ask the server to return an infinite number of items per page, quickly overloading the server and resulting in DoS.
I don’t know how to put this any other way but my experience with NextJS or just JS-first full stack is that they are still first and foremost a tech stack for frontend devs and the backend piece in that context is an afterthought.

I’ve worked on a few in my time and ‘API routes’ were rarely, if ever, authenticated, and there wouldn’t be a consistent strategy for data access. If anything, everything was built in the context of satisfying a react hook and getting on with the UI.

But I don’t squarely blame developers for it, it’s more like an inverted full stack where the browser is first class and the serverless edge SSR ISG SSG app router component craziness does not help you build out a stable API. Does sell a hell of a lot of SaaS though.

How serious this vulnerability is depends entirely on how the site that's being attacked uses middleware. The auth thing is just the most obvious example of how an attacker can do bad things if they have the ability to selectively disable middleware by passing names as a colon separated list in an HTTP header.

(I've built sites that would have been affected by this in the past, had I used Next and middleware for auth. I've worked on plenty of systems where there are only a small set of users each with the same level of permissions - gating private documentation for example.)

Probably depends on the complexity of the permissions in the application. I'd also expect something more along the lines you described for more complex applications. The middleware would do authentication, but then just attach that information to the request. Later parts would then use the attached information to make decisions about permissions/authorization.

In more complex cases this would be outside middleware, so it should fail as no authentication/authorization information is attached to the request if you skip that middleware.

But putting the security checks into middleware could easily make sense for more rigid or simple cases. In C# for example I can add attributes to the methods that handle each endpoint. So if you need a basic admin/no-admin check you could add a [RequireAdmin] attribute on the relevant endpoints and use a middleware to check that.

I would agree that checking the URL in middleware to make decision about permissions would be a bad idea, it moves this important check to a mostly invisible place.

This probably also allows different attacks, e.g. skipping middleware that does other security-relevant checks (maybe anti-CSRF mechanisms could be vulnerable here).

I don’t think it really matters. All you have to do is write middleware or handlers that assume upstream middleware have run, and then that’s vulnerable to this attack.

For example it’s common to write middleware on /admin so that all of your /admin/* handlers don’t have to repeat the same authz logic. And the platform breaking invariants that you should be able to depend on is why it’s a security bug.